Rails: Должны ли партиалы знать о переменных экземпляра? - PullRequest
61 голосов
/ 24 марта 2010

nifty_scaffolding Райана Бейтса, например, делает это

edit.html.erb

<%= render :partial => 'form' %>

new.html.erb

<%= render :partial => 'form' %>

_form.html.erb

<%= form_for @some_object_defined_in_action %>

Это скрытое состояние заставляет меня чувствовать себя некомфортно, поэтому я обычно люблю это делать

edit.html.erb

<%= render :partial => 'form', :locals => { :object => @my_object } %>

_form.html.erb

<%= form_for object %>

Итак, что лучше: a) иметь частичные переменные экземпляра доступа или b) передавать частичные все необходимые переменные?

В последнее время я выбираю б), но натолкнулся на небольшой рассол:

some_action.html.erb

<% @dad.sons.each do |a_son| %>
<%= render :partial => 'partial', :locals => { :son => a_son } %>
<% end %>

_partial.html.erb

The son's name is <%= son.name %>
The dad's name is <%= son.dad.name %>

son.dad делает вызов из базы данных, чтобы получить папу! Так что мне нужно было бы либо получить доступ к @dad, что вернулось бы к a) иметь переменные экземпляра доступа к частям , либо мне пришлось бы передать @dad в локальных системах, изменив render: частичный на <% = render: частичный => 'частичный',: locals => {: dad => @dad,: son => a_son}%>, и по какой-то причине передача нескольких переменных в мою частичную часть заставляет меня чувствовать себя неловко. Может быть, другие тоже так чувствуют.

Надеюсь, это имело смысл. Нужно немного разобраться во всем этом ... Спасибо!

Ответы [ 4 ]

103 голосов
/ 24 марта 2010

В последних версиях Rails гораздо проще рендерить партиалы и передавать им локальные объекты. Вместо этого.

<%= render :partial => 'form', :locals => { :item => @item } %>

Вы можете сделать это.

<%= render 'form', :item => @item %>

Я не делаю этого в генераторе Nifty Scaffold, чтобы сохранить обратную совместимость, но я изменю это в следующем выпуске.

Что касается допустимости использования переменных экземпляра в партиалах. Я думаю, что это. Во всей практичности, что является недостатком? Конечно, все может выйти из-под контроля, если вы не согласны, но мне нравится применять эти рекомендации.

  1. Никогда не создавайте переменную экземпляра только для того, чтобы разделить ее между частями. Обычно это означает, что вы будете совместно использовать объект ресурса контроллера.

  2. Если частичное имя совпадает с именем ресурса, передайте его как локальное с <%= render @item %>.

  3. Если частичное будет использоваться несколькими контроллерами, используйте только локальные.

Это то, что у меня хорошо работает в любом случае.

Бонусный совет: Если вы обнаруживаете, что передаете много местных жителей в партиал и хотите, чтобы некоторые из них были необязательными, создайте вспомогательный метод, который визуализирует партиал. Затем всегда используйте вспомогательный метод, чтобы вы могли создать чистый интерфейс с необязательными аргументами для рендеринга частичного.

42 голосов
/ 07 декабря 2012

Использование @instance_variables в партиалах - плохой дизайн.

Использование переменной экземпляра в партиалах работает, но может усложнить поддержку приложений, если изменения когда-либо понадобятся.

Недостатком использования переменных экземпляра в партиалах является то, что вы создаете зависимость в партиале от чего-то вне области партиала (связывание). Это усложняет частичное повторное использование и может вызвать изменения в нескольких частях приложения, если вы хотите внести изменения в одну часть.

Частицы, которые используют переменные экземпляра:

  • должно измениться, когда переменная экземпляра в любом контроллере, который использует частичные изменения, изменяет либо имя переменной экземпляра, либо ее тип, либо структуру данных
  • приводит к тому, что все действия контроллера, использующие частичное, изменяются одинаково в одно и то же время, когда происходят изменения в том, как используется переменная экземпляра
  • препятствует повторному использованию, поскольку их можно легко повторно использовать только в действиях, которые устанавливают переменные экземпляра с тем же именем и данными

Вместо этого передавайте локальные данные частям:

<%= render 'reusable_partial', :item => @item %>

Теперь, поскольку частичное ссылается только на item, а не @item, действие, которое отображает представление, которое отображает reusable_partial, можно свободно изменять, не затрагивая reusable_partial и другие действия / представления, которые его отображают:

<%= render 'reusable_partial', :item => @other_object.item %>

Кроме того, это можно использовать повторно в тех случаях, когда @item:

<%= render 'reusable_partial', :item => @duck %>

Если мой @duck изменится в будущем и больше не будет крякать, как этого ожидает reusable_partial (изменяется интерфейс объекта), я также могу использовать адаптер для передачи того типа элемента, который ожидает reusable_partial:

<%= render 'reusable_partial', :item => itemlike_duck(@duck) %>

Всегда

Существует множество ситуаций, когда вам, вероятно, не нужны расцепленные партиалы, подобные этой, и в краткосрочной перспективе проще использовать переменную экземпляра. Однако трудно предсказать будущие потребности вашего приложения.

Как таковая, это способствует хорошей общей практике при относительно низкой стоимости.

5 голосов
/ 09 октября 2013

Вы можете иметь оба варианта. В верхней части вашего частичного:

<% item ||= @item %>

Таким образом, он работает с локальной переменной или без нее, обеспечивая нормальное значение по умолчанию, но не препятствуя альтернативному использованию частичного.

3 голосов
/ 24 марта 2010

Я голосую за а) по очень конкретной причине - СУХОЙ! Если вы начинаете передавать переменную - вот так - следующая вещь, которую вы знаете - это беспорядок - допустим, вам нужно изменить способ именования вашей переменной или что-то еще об этом - тогда вам нужно перейти на ВСЕ ваши представления и изменить их вместо ОДНОГО частичного. Также - если вы измените свою часть - скажем, она создает таблицу с некоторым результатом, она изменится во всех ваших представлениях, так что вам нужно знать, какие представления используются, надлежащая IDE должна помочь вам в этом, но мне также нравится иметь небольшой раздел комментариев в верхней части представления - где я просто упоминаю, где он используется и почему - помогает другому программисту и помогает помнить в случае, если вам нужно вернуться к частичному и изменить. Но весь смысл частичного состоит в том, чтобы назвать его БЕЗ необходимости передавать что-либо из представления, чтобы вам не приходилось изменять все места, откуда вызывается частичное, если эта переменная каким-либо образом изменяется.

В конечном счете, это выбор дизайна - и, честно говоря, если вы не пользуетесь Facebook, дополнительный поиск, который вы делаете, не так уж важен, но он не очень СУХОЙ.

П.С .: Просто подумайте об этом - вы можете абстрагировать способ, которым вы вызываете частичное в вспомогательном методе, поэтому, если способ, которым вы вызываете частичное, нуждается в изменении - тогда вам просто нужно изменить одно место.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...