Rails 3: nested_form, collection_select, accepts_nested_attributes_for and fields_for

Update: reply here .

There are a lot of good questions and answers here, as well as on interweb on how to get nested_form, collection_select, accepts_nested_attributes_for and fields_for to play nicely together, but I'm still at a dead end. Thanks in advance if you can help me.

Purpose: create a new isbn record. Isbn can have many members. I have successfully used the ryanb nested_form gem to dynamically create new contributor fields in the form, if necessary. One of these fields uses drop_select for all name entries in the Contributor. When a new record is created, many contributor identifiers must be written to the connection table (contributors_isbns).

I have a bit of this work, but only to the extent that I can save a single member identifier for a new entry in the isbns table. It seems that I can not write any data to the connection table.

I have three models. Members and Isbns have many different relationships that I made using has_many: through. Isbn can have many members, and a contributor can have many isbns. They are combined through contributors_isbn.

isbn.rb

attr_accessible :contributor_id has_many :contributors, :through => :contributors_isbns has_many :contributors_isbns accepts_nested_attributes_for :contributors accepts_nested_attributes_for :contributors_isbns 

contributor.rb

  attr_accessible :isbn_id has_many :contributors_isbns has_many :isbns, :through => :contributors_isbns accepts_nested_attributes_for :isbns 

contributors_isbn.rb

  class ContributorsIsbn attr_accessible :isbn_id, :contributor_id belongs_to :isbn belongs_to :contributor accepts_nested_attributes_for :contributors 

In the isbns controller:

  def new @isbn = Isbn.new @title = "Create new ISBN" 1.times {@isbn.contributors.build} @isbn.contributors_isbns.build.build_contributor end 

(Obviously, I can't remember which assembly method to use.)

In the isbns view new.html.erb:

 <%= nested_form_for @isbn, :validate => false do |f| %> <h1>Create new ISBN</h1> <%= render 'shared/error_messages', :object => f.object %> <%= render 'fields', :f => f %> <div class="actions"> <%= f.submit "Create" %> </div> <% end %> 

In the _fields part, a partial version with a very simple text field:

 <%= field_set_tag 'Contributor' do %> <%= f.link_to_add "Add Additional Contributor", :contributors %> <li> <%= f.label 'Contributor Sequence Number' %> <%= f.text_field :descriptivedetail_contributor_sequencenumber%> </li> <%= f.fields_for :contributors_isbns, :validate => false do |contrib| %> <li> <%= contrib.label :id, 'contributors_isbns id' %> <%= contrib.text_field :id %> </li> <% end %> <li> <%= f.label 'Contributor Role' %> <%= f.text_field :descriptivedetail_contributor_contributorrole %> </li> <% end %> 

And here is the fancier version, which also does not work:

 <%= f.fields_for :contributors_isbns, :validate => false do |contributors| %> <li> <%= f.label :personnameinverted, 'Contributor Name' %> <%= f.collection_select(:contributor_id, Contributor.all, :id, :personnameinverted ) %> </li> <% end %> 

This code uses the answer here . Both results result in a Missing Block error on the nested_form_for @isbn line.

Thanks a lot in advance.

Update: here is some information about the nested_form jewel that might come in handy for finding such a problem. And here [2009, but still a relevant entry] [4] on accepts_nested_attributes_for.

Update 2: Well, here's the thing. I scrolled through this shortened version in two different models, not using collection_select or has_many through, but only in a simple belongs_to / has_many association. The parent model is the contract, and the child model is Istc. I could not even create a post through a nested form. However, after searching the stack and googling, I get the error message “Warning. You cannot assign protected attributes to mass” I just added :istcs_attributes to my line :attr_accessible , and now I can add entries. There is no critical bit enough, and the case of RTFM, as it is directly in the gem readme. I will update later to find out if this works with the more complex has_many through association.

Update 4: [Here] [5] is another useful post on how to handle the nil write error message.

Update 5: A small detour. When I dynamically added a new set of fields to the form, one of the child records was created. Spirit - I had a “Add” link inside the area of ​​child forms. Here before:

 <%= f.fields_for :istcs do |istc_form| %> <h4> Istc</h4> <%= istc_form.label "istc name" %> <%= istc_form.text_field :title_title_text %> <%= istc_form.link_to_remove "[-] Remove this istc"%> <%= f.link_to_add "[+] Add an istc", :istcs %> <% end %> 

and here after:

 <%= f.fields_for :istcs do |istc_form| %> <h4> Istc</h4> <%= istc_form.label "istc name" %> <%= istc_form.text_field :title_title_text %> <%= istc_form.link_to_remove "[-] Remove this istc"%> <% end %> <%= f.link_to_add "[+] Add an istc", :istcs %> 

Update 6, after the answer:

Oh noes. The collection_select function does not work. This is adding new contributor entries, not using an existing member from the model. Someone else had this problem. Any ideas?

+6
source share
1 answer

Hurrah! Here is the code that makes it all work. Bit verbose, but did not want to leave anything. My basic knowledge:

  • you need to make attr_accessible child attributes in the parent model

  • you need to make the parent and child ids attr_accessible in the connection table model

  • this makes life easier if you create at least one child instance in the parent controller.

contributor.rb model

 class Contributor < ActiveRecord::Base attr_accessible #nothing relevant has_many :contributors_isbns has_many :isbns, :through => :contributors_isbns 

isbn.rb model

 class Isbn < ActiveRecord::Base attr_accessible :contributors_attributes, :contributor_id, :istc_id #etc belongs_to :istc has_many :contributors, :through => :contributors_isbns has_many :contributors_isbns accepts_nested_attributes_for :contributors #if you omit this you get a missing block error 

contributors_isbn model

 class ContributorsIsbn < ActiveRecord::Base belongs_to :isbn belongs_to :contributor attr_accessible :isbn_id, :contributor_id 

isbn controller

  def new @isbn = Isbn.new @title = "Create new ISBN" 1.times {@isbn.contributors.build} end 

new.html.erb

 <td class="main"> <%= nested_form_for @isbn, :validate => false do |f| %> <h1>Create new ISBN</h1> <%= render 'shared/error_messages', :object => f.object %> <%= render 'fields', :f => f %> <div class="actions"> <%= f.submit "Create" %> </div> <% end %> 

_fields.html.erb

 <%= field_set_tag 'Identifier Details' do %> <li> <%= f.label 'Title prefix' %> <%= f.text_field :descriptivedetail_titledetail_titleelement_titleprefix %> </li> <li> <%= f.label 'Title without prefix' %> <%= f.text_field :descriptivedetail_titledetail_titleelement_titlewithoutprefix %> </li> <li> <%= f.label 'ISTC' %> <%= f.collection_select(:istc_id, Istc.all, :id, :title_title_text, :prompt => true) %> </li> <% end %> <%= field_set_tag 'Contributor' do %> <li> <%= f.label 'Contributor Sequence Number' %> <%= f.text_field :descriptivedetail_contributor_sequencenumber%> </li> <%= f.fields_for :contributors, :validate => false do |contributor_form| %> <li> <%= contributor_form.label :personnameinverted, 'Contributor Name' %> <%= contributor_form.collection_select(:isbn_id, Contributor.all, :id, :personnameinverted ) %> </li> <%= contributor_form.link_to_remove "[-] Remove this contributor"%> <% end %> <%= f.link_to_add "[+] Add a contributor", :contributors %> <li> <%= f.label 'Contributor Role' %> <%= f.text_field :descriptivedetail_contributor_contributorrole %> </li> <% end %> 
+3
source

Source: https://habr.com/ru/post/889990/


All Articles