3

我正在将一个工作应用程序从 Rails 2.3 更新(并重构)到 Rails 4.0。这个应用程序包括一个名为“智能组”的功能。一个智能组建立一个搜索查询,可以保存并重新用于查找一组“人”记录。

一个智能组有_many 个智能组规则,每个智能组规则属于具有零个或多个运算符的属性。

创建智能组的表单还处理添加智能组规则。选择规则的属性后,应更新表单以显示所选属性的关联运算符和用于输入规则值的字段。

问题是在选择属性时需要动态更新表单,以便显示所选属性的运算符。这是我在 Rails 4.0 中似乎无法弄清楚的部分。

class SmartGroup < ActiveRecord::Base
  has_many :rules, :class_name => "SmartGroupRule", :foreign_key => "smart_group_id"

  accepts_nested_attributes_for :rules, reject_if: :all_blank, allow_destroy: true
end

class SmartGroupRule < ActiveRecord::Base
  belongs_to :smart_group
  belongs_to :smart_group_property
  belongs_to :operator 
end

class SmartGroupProperty < ActiveRecord::Base
  has_many :smart_group_rules
  has_many :property_operators
  has_many :operators, through: :property_operators  
end

class Operator < ActiveRecord::Base
  has_many :property_operators
  has_many :smart_group_properties, through: :property_operators  
end

一个例子是:

智能组:所有 30 多岁的人。规则 1:年龄大于 29 岁的人。规则 2:年龄小于 40 岁的人。

属性是“年龄”。“年龄”属性有 3 个可选运算符:小于、大于和精确。规则 1 的“值”是 29,规则 2 的“值”是 31。

我正在使用 Ryan Bate 的技术向 Railscast 第 196 集“嵌套模型表单(修订版)”中的表单添加多个规则。

#smart_groups/_form.html.erb
<%= simple_form_for(@smart_group) do |f| %>
  <%= f.error_notification %>

 <%= f.input :name %>
 <%= f.input :definition %>

 <%= f.simple_fields_for :rules do |rule_form| %>
  <%= render 'rule_fields', f: rule_form %>
 <% end %>

 <%= link_to_add_fields "Add Rule", f, :rules %>
    <%= f.button :submit %>
<% end %>

#smart_groups/_rule_form.html.erb
 <%= field_set_tag 'Smart Group Rule' do %>
  <%= f.association :smart_group_property, label_method: :prose, input_html: {class: "property_selector"} %>
  <span id="property-fields">

  </span>
  <%= f.hidden_field :_destroy %>
  <%= link_to "remove this rule", '#', class: "remove_fields" %>
 <% end %>

<script type="text/javascript" charset="utf-8">
 $(".property_selector").observe_field(1, function( ) {
  var data = {'property_id' : $(this).val()};
  var url = '/smart_groups/property_selected';
  $.get(url, data, function(html) {
   $("#property_operator").html(html);
  });
 });
</script>
#this is inline because I can't figure out how to do it unobtrusively.

Railscast 中的辅助方法。

# ApplicationHelper
  def link_to_add_fields(name, f, association)
      new_object = f.object.send(association).klass.new
      id = new_object.object_id
      fields = f.fields_for(association, new_object, child_index: id) do |builder|
        render(association.to_s.singularize + "_fields", f: builder)
      end
      link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
  end

# js.coffee
  $('form').on 'click', '.add_fields', (event) ->
    time = new Date().getTime()
    regexp = new RegExp($(this).data('id'), 'g')
    $(this).before($(this).data('fields').replace(regexp, time))
    event.preventDefault()

这个助手,连同这个咖啡脚本,成功地向页面添加了多个智能组规则表单。

现在的问题是:在规则表单中选择属性值时,需要使用所选属性的运算符更新表单的其余部分。我正在使用上面的内联 js,它使用 jQuery.observe_field 插件来观察属性选择器。调用控制器操作,并将所选属性的 id 作为 property_id 发送到控制器。

class SmartGroupsController < ApplicationController
  def property_selected
    @property = SmartGroupProperty.find(params[:property_id])
    @partial_name = @property.short + "_fields"
  end
end

这允许设置变量@partial_name。

然后使用所选属性的操作符的部分更新视图(或“应该”更新):

#property_selected.js.erb
$("#property-fields").html("<%= j render partial: @partial_name, locals: {f: f} %>");

…但我不知道如何将表单构建器对象发送到表单…或者是否有可能使用 Rails 4 以这种方式接近它。

我收到此错误:

ActionView::Template::Error (undefined local variable or method `f' for #< <Class:0x007f9884088120>:0x007f98824c9e98>):
    1: $("#property-fields").html("<%= j render partial: @partial_name, locals: {f: f} %>");
  app/views/smart_groups/property_selected.js.erb:1:in                                _app_views_smart_groups_property_selected_js_erb__2922231718460238483_70146499765020'

如何通过 property_selected 操作从 _rule_form 获取表单的构建器对象,并将其传递到表单的更新部分?有没有更好的方法来解决这个问题?

感谢您的任何输入/方向。

4

2 回答 2

0

I would prefer you to use a dynamic form generating gems. Those gems have js to event observer for forms dom changes.

You may have a look at this gem. https://github.com/nathanvda/cocoon

于 2014-11-04T18:45:37.910 回答
0

我认为,您不能在此部分中传递表单构建器变量......但您并不真正需要它。如果您只使用fields_for它将创建一个单独的参数并且您可以在控制器中使用此参数集,那就更好了。

<%=fields_for 'properties' do |extra_fields| %>
  <% ... %>
<% end %>

检查你的 development.log 当你提交表单时传递了什么样的参数......

于 2013-07-19T22:21:43.893 回答