Передача локальных переменных вниз Частичная иерархия в Rails 4 для ассоциаций Ransack

Я пытаюсь реализовать форму поиска и сортировки на всех индексных страницах моей модели, используя Ransack. Я хотел бы сделать это как можно СУХИМ, поэтому я создал три частичных файла в своей папке представлений/приложений:

  • представления/приложение/_table_search_and_sort_form.html.erb
  • представления/приложение/_condition_fields.html.erb
  • представления/приложение/_sort_fields.html.erb

Код для каждого выглядит следующим образом:

представления/приложение/_table_search_and_sort_form.html.erb

<div>
  <%= search_form_for table_search_and_sort_form do |f| %>
    <%= f.condition_fields do |c| %> 
      <%= render partial: "condition_fields", locals: { f: c, associations: associations } %>
    <% end %>
    <p><%= link_to_add_fields "Add Conditions", f, :condition %></p>
    <%= f.sort_fields do |s| %>
      <%= render "sort_fields", f: s %>
    <% end %>
    <p><%= link_to_add_fields "Add Sort", f, :sort %></p>
    <div class="actions"><%= f.submit "Search" %></div>
  <% end %>
</div>

представления/приложение/_condition_fields.html.erb

<div class="field" data-object-name="<%= f.object_name %>">
  <%= f.attribute_fields do |a| %>
    <%= a.attribute_select associations: associations %>
  <% end %>
  <%= f.predicate_select %>
  <%= f.value_fields do |v| %>
    <%= v.text_field :value %>
  <% end %>
  <%= link_to "remove", '#', class: "remove_fields" %>
</div>

представления/приложение/_sort_fields.html.erb

<div class="field" data-object-name="<%= f.object_name %>">
    <%= f.sort_select %>
    <%= link_to "remove", '#', class: "remove_fields" %>
</div>

В каждом из моих контроллеров у меня есть что-то вроде:

def index
    @search = Document.search(params[:q])
    @documents = @search.result.paginate(:page => params[:page])
    @search.build_condition if @search.conditions.empty?
    @search.build_sort if @search.sorts.empty?
end

а затем я добавляю форму к каждому index.html.erb, добавляя:

<%= render partial: "table_search_and_sort_form", object: @search, locals: { associations:  [:status, :job, :project, :language, :data_files] } %>

Где массив :associations отличается для каждой модели в зависимости от ассоциаций, которые я хотел бы получить из формы условия. Когда я не пытаюсь передать массив :associations через два партиала и просто жестко кодирую массив в _condition_fields.html.erb, например:

<%= a.attribute_select associations: [:status, :job, :project, :language, :data_files] %>

Все работает просто отлично (для этой модели, в данном случае Document). Когда я пытаюсь распространить это на несколько моделей, передавая массив :associations из index в _table_search_and_sort_form и далее в _conditional_form, я получаю следующую ошибку:

undefined local variable or method `associations'


Extracted source (around line #3):

1  <div class="field" data-object-name="<%= f.object_name %>">
2  <%= f.attribute_fields do |a| %>
3  <%= a.attribute_select associations: associations %>
4  <% end %>
5  <%= f.predicate_select %>
6  <%= f.value_fields do |v| %>

Почему массив associations не передается дальше первого фрагмента, даже если он передан для рендеринга хэша locals? Я думал, что Rails не волнует, сколько партиалов вы вызываете из партиала? Я попытался переименовать ассоциации, чтобы избежать путаницы с параметром ассоциации в *attribute_select*, но это не имеет значения.


person eljaydub    schedule 08.04.2014    source источник
comment
используйте collection вместо locals, чтобы передать свою коллекцию как местных жителей.   -  person Alok Anand    schedule 08.04.2014
comment
Это не вызывает ошибку, но приводит к исчезновению всей формы со страницы. Поправьте меня, если я ошибаюсь, но разве collection не заменяет object, когда вы хотите отображать партиал для каждого члена коллекции, а не только один раз для отдельного объекта? В этом случае я пытаюсь передать переменную (которая оказывается коллекцией) через два партиала и в метод, который принимает массив в качестве параметра - я не пытаюсь отображать каждый элемент в коллекции.   -  person eljaydub    schedule 08.04.2014


Ответы (2)


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

  def link_to_add_fields(name, f, type)
    new_object = f.object.send "build_#{type}"
    id = "new_#{type}"
    fields = f.send("#{type}_fields", new_object, child_index: id) do |builder|
      render(type.to_s + "_fields", f: builder)
    end
    link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
  end

Этот помощник вызывается в _table_search_and_sort_form, и, как вы можете видеть, массив «ассоциаций» не передается ему, поэтому возникает ошибка, а не в строке 4, как я изначально подозревал. Думаю, я мог бы взломать этот метод, чтобы передать необязательный массив, но я бы не стал этого делать; он отлично работает, как и для частичных полей _condition_fields и _sort_fields, и я думаю, что создам себе головную боль, если взломаю или перегружу его. Вместо этого я собираюсь найти другой способ добавления некоторых ассоциаций в форму поиска, возможно, путем переопределения в модели self.ransackable_attributes или self.ransackable_associations. Я не нашел много надежной документации по этому поводу, но я немного поэкспериментирую. Надеюсь, это поможет кому-то еще.

person eljaydub    schedule 10.04.2014

Может быть, это не ответ, но, похоже, слишком долго публиковать в комментариях

Я не уверен, что вы можете использовать locals и object вместе, хотя я могу ошибаться. Может попробовать

<%= render "table_search_and_sort_form", locals: { search: @search, associations:  [:status, :job, :project, :language, :data_files] } %>

Затем измените частичный

<div>
<%= search_form_for search do |f| %>
  <%= f.condition_fields do |c| %> 
    <%= render partial: "condition_fields", locals: { f: c, associations: associations } %>
  <% end %>
  <p><%= link_to_add_fields "Add Conditions", f, :condition %></p>
  <%= f.sort_fields do |s| %>
    <%= render "sort_fields", f: s %>
  <% end %>
  <p><%= link_to_add_fields "Add Sort", f, :sort %></p>
  <div class="actions"><%= f.submit "Search" %></div>
<% end %>
</div>
person engineersmnky    schedule 08.04.2014
comment
Я пробовал это, но получаю ошибку «неопределенная локальная переменная или метод «поиск»» в строке 2 файла _table_search_and_sort_form.html.erb - person eljaydub; 09.04.2014
comment
Когда я добавляю partial: к рендерингу в индексе (т.е. <%= render partial: "table_search_and_sort_form", locals: { search: @search, associations: [:status, :job, :project, :language, :data_files] } %>), поиск распознается, и я возвращаюсь к исходному исключению «неопределенная локальная переменная или метод ассоциаций». - person eljaydub; 09.04.2014