0

我目前有一个接受_nested_attributes_for Features 的客户表单。这些功能可以是任意数量的东西,但为了简单起见,我们假设它们是名字、姓氏和出生日期(我知道这是 EAV 的问题 - 如果您对此有意见,请请参阅我关于该主题的其他问题)。

在我的控制器中,我有:

3.times {@customer.features.build}

这工作正常,并构建了 3 个功能,按预期保存。但是,我想要的是为视图中的每个构建功能指定功能类型。我的观点目前看起来像:

<%= customer.fields_for :features do |features_builder| %>
  <%= render :partial => "features/fixed_feature", :locals => {:feature => features_builder, :fixed_feature_type => "First Name", :form_actions_visible => false} %>
<% end -%>

正如人们所期望的那样,这会创建 3 个 First Name 字段。我想要的是能够指定 3 种不同类型的功能,如下所示:

<%= customer.fields_for :features do |features_builder| %>
  <%= render :partial => "features/fixed_feature", :locals => {:feature => features_builder, :fixed_feature_type => "First Name", :form_actions_visible => false} %>
  <%= render :partial => "features/fixed_feature", :locals => {:feature => features_builder, :fixed_feature_type => "Last Name", :form_actions_visible => false} %>
  <%= render :partial => "features/fixed_feature", :locals => {:feature => features_builder, :fixed_feature_type => "Date of Birth", :form_actions_visible => false} %>
<% end -%>

显然,上面编写的代码不起作用,因为它试图为每个实例创建 3 个字段。我似乎需要的是 fields_for 循环上的索引,它允许我遍历并向每个部分添加一个 if 子句,以便它只触发一次,并且每个都在不同的功能实例上触发。

谁能指出我能做到最好吗?搜索后,我似乎找不到获取 fields_for 循环索引的方法。

编辑:根据第一条评论,为清楚起见:我希望在页面上呈现三个功能,一个用于控制器构建的每个功能。我希望每个功能都以不同的方式呈现(在上面的代码中为 :fixed_feature_type 传递了不同的局部变量)。我正在寻找最好的方法来做到这一点。

编辑2:我知道另一种方法是在控制器中动态构建嵌套属性(而不是最初一次构建3个)-有没有办法做到这一点?

编辑 3:花了一些时间寻找一种动态执行此操作的方法后,我从 Railscast 中找到了一个辅助方法,如下所示:

def link_to_add_fields(name, f, association)
  new_object = f.object.class.reflect_on_association(association).klass.new
  fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
    render(association.to_s.singularize + "_fields", :f => builder)
  end
  link_to_function(name, h("add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"))
end

看来我可以定义一个这样的辅助方法,允许我添加各种功能字段 - 我很乐意将有关如何修改它以适应我当前情况的任何建议标记为答案。

4

1 回答 1

2

我能够通过将我的局部渲染移动到自定义助手来克服这个问题,这允许我根据需要动态构建对象。

编辑:根据要求,我的代码如下:

我已将以下代码添加到我的 application_helper.rb 文件中:

module ApplicationHelper

  def add_feature_fields(feature_types, object_form_builder, actions_visible)
    feature_types.length.times {object_form_builder.object.features.build}
    i = -1
    object_form_builder.fields_for :features do |features_builder|
      i = i + 1
      render :partial => "features/fixed_feature", :locals => {:feature => features_builder, :fixed_feature_type => feature_types[i], :form_actions_visible => actions_visible}
    end
  end
end

在我看来,我这样称呼这个助手:

<%= add_feature_fields(["First Name", "Last Name", "Date of Birth"], customer, false) %>

这允许我通过简单地向数组添加额外的项目来添加模型(在本例中为人)所需的任意数量的特征。

希望这可以帮助!

编辑:'features/_fixed_feature.html.erb'

<%= feature.hidden_field :feature_type_id, :value => FeatureType.where(:value => fixed_feature_type).first.id %>
<fieldset>
        <div class="control-group">
        <label class="control-label"><Value><%= fixed_feature_type %></label>
        <div class="controls">
            <%= feature.text_field :value, :class => 'input-large' %>
        </div>
    </div>
    <% if form_actions_visible == true %>
        <div class="form-actions">
            <%= content_tag :button, :type => :submit, :class => "btn btn-info" do -%>
                Save Changes
            <% end -%>
            <%= content_tag :button, :type => :cancel, :class => "btn btn-warning" do -%>
                Cancel
            <% end -%>
        </div>
    <% end %>
</fieldset>

没有什么特别的,只是使用助手传入的局部变量来渲染标签等,而不需要“特征类型”框和值框(它只渲染一个值框,因此类型是固定的)。

根据您的评论,如果您想为不同的模型添加功能,您只需再次调用帮助程序并更改“客户”部分(这是表单构建器 - 更常见的是“f”,但我更喜欢语义命名)。

于 2012-08-22T21:22:49.260 回答