我正在将一个工作应用程序从 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 获取表单的构建器对象,并将其传递到表单的更新部分?有没有更好的方法来解决这个问题?
感谢您的任何输入/方向。