将局部变量向下传递 Rails 4 中的部分层次结构以进行 Ransack 关联 [英] Passing local variables down Partial hierarchy in Rails 4 for Ransack associations

查看:50
本文介绍了将局部变量向下传递 Rails 4 中的部分层次结构以进行 Ransack 关联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Ransack 在我所有模型的索引页上实现搜索和排序表单.我想尽可能地做到这一点,所以我在我的视图/应用程序文件夹中创建了三个部分:

  • views/application/_table_search_and_sort_form.html.erb
  • views/application/_condition_fields.html.erb
  • views/application/_sort_fields.html.erb

每个代码如下:

views/application/_table_search_and_sort_form.html.erb

<%= search_form_for table_search_and_sort_form do |f|%><%= f.condition_fields 做 |c|%><%= render partial: "condition_fields", locals: { f: c, associations: associations } %><%结束%><p><%= link_to_add_fields "添加条件", f, :condition %></p><%= f.sort_fields 做 |s|%><%=render "sort_fields", f: s %><%结束%><p><%= link_to_add_fields "添加排序", f, :sort %></p><div class="actions"><%= f.submit "Search" %></div><%结束%>

views/application/_condition_fields.html.erb

<%= f.attribute_fields 做 |a|%><%= a.attribute_select 关联:关联 %><%结束%><%= f.predicate_select %><%= f.value_fields 做 |v|%><%= v.text_field :value %><%结束%><%= link_to "remove", '#', class: "remove_fields" %>

views/application/_sort_fields.html.erb

<%= f.sort_select %><%= link_to "remove", '#', class: "remove_fields" %>

在我的每个控制器中,我都有类似的东西:

def 索引@search = Document.search(params[:q])@documents = @search.result.paginate(:page => params[:page])@search.build_condition 如果@search.conditions.empty?@search.build_sort 如果@search.sorts.empty?结尾

然后我通过添加以下内容将表单添加到每个 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 关联:[:status, :job, :project, :language, :data_files] %>

一切正常(对于该模型,在本例中为 Document).当我尝试通过将 :associations 数组从索引向下传递到 _table_search_and_sort_form 并传递到 _conditional_form 来将其扩展到多个模型时,我收到以下错误:

未定义的局部变量或方法`associations'提取的源代码(围绕第 3 行):1 <div class="field" data-object-name="<%= f.object_name %>">2 <%= f.attribute_fields 做 |a|%>3 <%= a.attribute_select 关联:关联%>4<%结束%>5 <%= f.predicate_select %>6 <%= f.value_fields do |v|%>

为什么 associations 数组不会在第一个部分之外传递,即使它被提供给渲染的 locals 哈希?我认为 Rails 并不关心你从一个部分调用了多少个部分?我试图重命名 associations 以避免与 *attribute_select* 的 associations 参数混淆,但这没有区别.

解决方案

问题是我有一个应用程序助手定义为

 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|渲染(type.to_s + "_fields", f: builder)结尾link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})结尾

这个助手在 _table_search_and_sort_form 中被调用,正如你所看到的,'associations' 数组没有传递给它,所以这就是抛出错误的地方,而不是我最初怀疑的第 4 行.我想我可以破解这个方法来传入可选数组,但我宁愿不这样做;它工作正常,因为它适用于 _condition_fields 和 _sort_fields 部分,我想如果我破解或超载它,我会为自己制造头痛.相反,我将寻找另一种方法将一些关联添加到搜索表单中,可能是通过覆盖模型中的 self.ransackable_attributes 或 self.ransackable_associations.我还没有找到很多关于此的可靠文档,但我会尝试一下.希望这对其他人也有帮助.

I'm trying to implement a search and sort form on all of my model's index pages using Ransack. I would like to do this as DRY'ly as possible so I created three partials in my views/application folder:

  • views/application/_table_search_and_sort_form.html.erb
  • views/application/_condition_fields.html.erb
  • views/application/_sort_fields.html.erb

The code for each is as follows:

views/application/_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>

views/application/_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>

views/application/_sort_fields.html.erb

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

In each of my controllers I have something like:

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

and then I add the form to each index.html.erb by adding:

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

Where the :associations array is different for each model depending on the associations I would like to be accessible from the condition form. When I don't try to pass the :associations array down through two partials and just hard code the array into _condition_fields.html.erb such as:

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

Everything works just fine (for that one model, Document in this case). When I try to extend this to multiple models by passing the :associations array down from index to _table_search_and_sort_form and on to _conditional_form I get the following error:

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| %>

How come the associations array doesn't get passed down beyond the first partial even when it's give to render's locals hash? I thought Rails didn't care how many partials you call from a partial? I tried to rename associations to avoid confusion with *attribute_select*'s associations parameter but this makes no difference.

解决方案

The problem was that I have an application helper defined as

  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

This helper is called in _table_search_and_sort_form and as you can see the 'associations' array does not get passed to it and so that's where the error gets thrown, not on line 4 as I initially suspected. I guess I could hack this method to pass in the optional array but I'd rather not do that; it works fine as it is for the _condition_fields and _sort_fields partials and I think I'd be creating a headache for myself if I hack or overload it. Instead, I'm going to look for another way to add some of the associations to the search form, perhaps by overriding self.ransackable_attributes or self.ransackable_associations in the model. I haven't find much solid documentation about this but I'll experiment a bit. Hope this helps someone else too.

这篇关于将局部变量向下传递 Rails 4 中的部分层次结构以进行 Ransack 关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆