Как использовать один частичный в разных контекстах
Я новичок в рельсах и пытаюсь сделать следующее:
Я хотел бы, потому что я использую Bootstrap, чтобы иметь частичное для поля ввода, с его меткой и небольшим значком, который я назвал символом в этом случае.
Вот мой взгляд:
<%= form_for(@user, :class => "form-horizontal" ) do |f| %>
<fieldset>
<%= render 'shared/text_field', function: f, tag: :name, symbol: '<i class="icon-user"></i>' %>
<%= render 'shared/text_field', function: f, tag: :email, symbol: "@" %>
<%= render 'shared/password_field', function: f, tag: :password, symbol: '<i class="icon-log"></i>' %>
<%= render 'shared/password_field', function: f, tag: :password_confirmation, alt: "Passwort wiederholen", symbol: '<i class="icon-log"></i>' %>
<!-- SUBMIT -->
<%= f.submit "Anmeldung", :class => "btn btn-primary" %>
</fieldset>
<% end %>
Здесь подчасти для нормальных полей ввода:
<%= render 'shared/bootstrap/input_field' %>
<% content_for :label do %>
<%= function.label tag, :class => "control-label", :for => "prependedInput" %>
<% end %>
<%content_for :symbol do %>
<%= raw(symbol) %>
<% end %>
<% content_for :field do %>
<%= function.text_field tag, :class => "input-xlarge", :id => "prependedInput", :size => "6" %>
<% end %>
(есть также подчасть для полей пароля, в основном, заменяя function.text_field на function.input_field)
А вот поле ввода input, которое отображается:
<div class="control-group">
<%= yield :label %>
<div class="controls">
<div class="input-prepend">
<span class="add-on"><%= yield :symbol %> </span>
<%= yield :field %>
</div>
</div>
</div>
Итак, мой вопрос: как я могу решить эту проблему простым и понятным способом (это происходит при рефакторинге, и это стало еще хуже, чем лучше) и как я могу заставить его работать, потому что теперь что-то подобное происходит: http://pastebin.com/bNsgT9AR так что yield помещает вместе с каждым content_for контент и контент перед тем (за исключением последнего)
Было бы здорово услышать хорошие решения от вас, должен быть такой более приятный путь, как почти всегда в Rails.
Привет из Германии;)
3 ответа
Как автор The Rails View, я согласен с постом Бена Тайтельбаума по этому вопросу и утверждаю, что Formtastic - отличный вариант для такого рода сложности.
Что касается кода, который вы разместили, то, как разработчики, мы хотим избежать такого рода написания представления по всем направлениям, так как это приводит к неуправляемому беспорядку. Слишком много файлов вовлечено в редактирование формы, и в какой-то момент какой-то другой разработчик придет и перезапишет нашу общую часть, не зная, где еще она была использована, чтобы изменить поведение другой формы. Любая выгода от повторного использования кода, которую мы можем извлечь из такого рода абстракции, полностью исключается из-за потенциальной возможности очень быстрого срыва с разработчиками разных типов.
Хотя Formtastic великолепен, я также часто использую SimpleForm в своих последних приложениях, особенно когда мне не нужны все возможности Formtastic.
SimpleForm будет обрабатывать вашу метку, а также поддерживает i18n. С этим было бы:
<%= simple_form_for @user do |f| %>
<%= f.input :name, :input_html => { :class => 'user-icon' } %>
<%= f.input :email %>
<%= f.input :password, :as => :password, :input_html => { :class => 'log-icon' } %>
<%= f.input :password_confirmation, :as => :password, :input_html => { :class => 'log-icon' } %>
<%= f.button :submit %>
<% end %>
Тогда в вашем файле I18n вы можете иметь:
en:
simple_form:
labels:
user:
username: 'User name'
password: 'Password'
password_confirmation: 'Password confirmation'
de:
simple_form:
labels:
user:
username: 'Benutzername'
password: 'Passwort'
password_confirmation: 'Passwort wiederholen'
И еще, как вам нужно. Вы также можете определить свои подсказки и заполнители в файле i18n.
Кроме того, подумайте о добавлении иконки в качестве псевдокласса CSS:after и сделайте это для каждого класса, который необходимо добавить в код)
input.user-icon:after {
// image as background, positioned properly, etc etc
}
input.log-icon:after {
// image as background, positioned properly, etc etc
}
И таким образом, вы можете удалить такие вещи из вашего ERB/ HTML и поместить их там, где они есть: в CSS (уровень представления).
Я чувствую, что это слишком много обобщений для простого поля ввода. Рассматривали ли вы просто создание одного общего поля ввода частичным и просто передавая имя поля (вы назвали его тегом) и тип поля (text_field или password_field) в качестве параметров? Я вижу, что ваш подход может быть более общим, но если вам сейчас нужны эти два варианта, сделайте его как можно более простым.
Дополнение в ответ на комментарий:
Вы можете просто передать параметры вашему частичному так:
<%= render 'shared/error_messages', object: f.object %>
А затем используйте переменные в вашем частичном. в вашем случае вы могли бы
<%= render 'shared/bootstrap/input_field', function: f, tag: :name, input_field_type: :text_field %>
а затем в _input_field.html.erb
<div class="control-group">
<%= function.label tag, :class => "control-label", :for => "prependedInput" %>
...
В The Rails View есть большой раздел о формах, где они рекомендуют использовать FormBuilders для этого типа вещей (они также обсуждают formtastic, который стоит проверить).
Самый большой урок, который я извлек из этой книги (и я не могу рекомендовать его достаточно!), Заключается в том, что важно сохранять как можно более простые представления, поскольку они, как правило, являются наименее забавной частью приложения rails для отладки, особенно когда приложение становится большим. Так что с этой точки зрения я бы хотел, чтобы представление было красивым и простым, что-то вроде:
<%= semantic_form_for(@user) do |f| %>
<%= f.inputs do %>
<%= f.input :name, class: 'icon-user' %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.input :password_confirmation %>
<% end %>
<%= f.buttons %>
<% end %>
Начните с красивого удобочитаемого представления в качестве цели и добавьте необходимые помощники и формирователи, необходимые для пользовательских типов полей.
Я бы порекомендовал использовать I18n для установки текста кнопки отправки на "Anmeldung" вместо того, чтобы жестко задавать это.
Я не использовал его, но вы можете проверить formtastic-bootstrap для получения желаемой интеграции.