user2071444
user2071444

Reputation:

fields_for for has_many association using an array

Controller: project_sub_types_controller.rb

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

Model: 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

View: _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 

After submitting the form the params = "repositories_attributes"=>{"0"=>{"repos_name"=>"svn_hardware"}}} even after checking both the checkboxes it is using the last selected check_box that is 'svn_hardware'

[EDIT]

Desired Output : My final output should be what the user selects so in this case it should be like this in my after submit params = "repositories_attributes"=>{"0"=>{"repos_name"=>"svn_software"}{"1"=>{"repos_name"=>"svn_hardware"}}

Upvotes: 1

Views: 625

Answers (2)

Supersonic
Supersonic

Reputation: 430

As Nicolay explains, the reason you have a 0 is because you build this @project_sub_type.repositories.build object once. Everything in your code is correct. But if you have to select multiple checkboxes then according to the DOCS

In View: _form.html.erb change

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

TO

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

Now you should be able to see the params after submit as below:

=>{"0"=>{"repos_name"=>["svn_software", "svn_hardware"]}}

Upvotes: 1

nicohvi
nicohvi

Reputation: 2270

I believe the reason that both have 0 as a prefix is that you have solely specified one repository object, while your array (@svn_repos) contains two items. Because you only build one new object (through @project_sub_type.repositories.build), you create two checkboxes for the same model.

If you, however, were to instead do this:

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

And then you'd have to iterate over both these objects in your _form partial, and map the names up to the @svn_repos array. I would much prefer this solution though:

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

And then iterate over the repositories in the partial, using the name attribute of the model rather than that of an array.

Upvotes: 1

Related Questions