fields_for用于使用数组的has_many关联

时间:2014-08-07 11:52:17

标签: ruby-on-rails ruby-on-rails-3

控制器: project_sub_types_controller.rb

  def new
    @svn_repos = ['svn_software','svn_hardware']
    @project_sub_type = ProjectSubType.new
    @project_sub_type.repositories.build
  end

型号: project_sub_type.rb

class ProjectSubType < ActiveRecord::Base
  belongs_to :project_type
  has_many :repositories, :dependent => :destroy
  accepts_nested_attributes_for :repositories

  def repositories_attributes=(attributes)
    # Process the attributes hash
  end
end

查看: _form.html.erb

<%= form_for @project_sub_type, :html => {:class => 'project_subtype_form'} do |f| %>
  <%= f.label :name, "Project sub type name" %>
  <%= f.text_field :name %>
  <%= f.fields_for :repositories do |ff| %>
      <%= ff.label :select_svn_repositories, "Select SVN repositories" %> 
      <% @svn_repos.each do |repos| %>
          <%= ff.check_box :repos_name, {}, "#{repos}", nil %>
          <%= h repos -%>
      <% end %>
<%= f.submit "Save"%>

fields_form inspect element:

<input id="project_sub_type_repositories_attributes_0_repos_name" type="checkbox" value="svn_software" name="project_sub_type[repositories_attributes][0][repos_name]">
svn_software
<input id="project_sub_type_repositories_attributes_0_repos_name" type="checkbox" value="svn_hardware" name="project_sub_type[repositories_attributes][0][repos_name]">
svn_hardware 

在提交表单params = "repositories_attributes"=>{"0"=>{"repos_name"=>"svn_hardware"}}}之后,即使检查了两个复选框,它也使用了最后选择的check_box'svn_hardware'

[编辑]

期望的输出:我的最终输出应该是用户选择的内容,所以在这种情况下,它应该像我之后的提交params =“repositories_attributes”=&gt; {“0”=&gt; { “repos_name”=&gt; “中svn_software”} { “1”=&GT; { “repos_name”=&gt; “中svn_hardware”}}

2 个答案:

答案 0 :(得分:1)

我认为两者都有0作为前缀的原因是您只指定了一个 repository对象,而您的数组(@svn_repos)包含两个项。因为您只构建了一个新对象(通过@project_sub_type.repositories.build),所以为同一模型创建了两个复选框。

但是,如果您要这样做:

# controller (inside new method)
@project_sub_type.repositories.build # 1 new object
@project_sub_type.repositories.build # 2 new objects

然后,您必须在_form部分中迭代这两个对象,并将名称映射到@svn_repos数组。我更喜欢这个解决方案:

# controller (inside new method)
@project_sub_type.repositories.build name: 'svn_software'
@project_sub_type.repositories.build name: 'svn_hardware'

然后使用模型的name属性而不是数组的属性迭代部分中的存储库。

答案 1 :(得分:1)

正如Nicolay解释的那样,你得到0的原因是因为你构建了这个@project_sub_type.repositories.build对象一次。代码中的所有内容都是正确的。但是,如果您必须根据DOCS

选择多个复选框

查看: _form.html.erb 更改

<%= ff.check_box :repos_name, {}, "#{repos}", nil %>

<%= ff.check_box :repos_name, {:multiple => true}, "#{repos}", nil %>

现在您应该能够在提交后看到params,如下所示:

=&gt; {“0”=&gt; {“repos_name”=&gt; [“svn_software”,“svn_hardware”]}}