Jump to content

The ultimate community for Ruby on Rails developers.


Getting Error Using fields_for with Nested Attributes Within collection_select

  • Please log in to reply
No replies to this topic

#1 lightbecorp



  • Members
  • 10 posts

Posted 15 August 2013 - 04:26 PM

I am using Rails 3.2.13 and Ruby 1.9.3 for my application.


I have a MediaLibrary model that has many MediaTopics.  MediaTopics belongs to MediaLibrary.  I have a Topic model with a list of names that I use in a collection_select.  I want for a user to be able to select a Topic by name and list all the related MediaLibrary rows.


Initially I was not using nested attributes.  I was manually creating the MediaTopic rows by retrieving the array of topic ids, deleting all the existing MediaTopic rows then adding all the rows using the media_library_id and each topic_id from the array.  I decided however that I wanted to use nested attributes for the first time so that I would not have to manually delete and re-add MediaTopic rows when changes were made. This would clean up my controller.  I also want the Topic names for the selected topics highlighted in my collection_select statement.


Here is how my nested attributes for MediaTopic is set up:

has_many :media_topics, dependent: :destroy
accepts_nested_attributes_for :media_topics, allow_destroy: true
alias_method :underlying_media_topics_attributes=, :media_topics_attributes=

Here is the method that will remove the blank entry in my array of topic ids. From my understanding this has to be done until I upgrade my application to Rails 4 where I can add include_hidden: false to my collection_select statement.

def media_topics_attributes=(hash_of_hashes)
  hash_of_hashes.each { |key, hash| hash[:topic_id].reject!(&:blank?) }

Here is my fields_for statement.  Before when I was doing the manual process I used fields_for, not f.fields_for.

<%= f.fields_for :media_topics do |media_topic| %>
  <%= media_topic.collection_select(:topic_id, Topic.order("name_en"), :id, :name_en, {}, {multiple: true}) %>
<% end %>

When the @media_library.update_attributes statement is executed I get an error * Media topics topic can't be blank.  


Here is my debug log showing the contents of media_topics_attributes:

media_topics_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
    '0': !ruby/hash:ActiveSupport::HashWithIndifferentAccess
      - '2'
      - '47'
      id: '1896'

It appears that it is trying to assign the entire array to topic_id for one MediaTopic row instead of creating/rebuilding multiple MediaTopic rows which is what I want to do.  At this point the check for topic_id in MediaTopic is already being done.  If I remove the validates :topic_id, presence: true  from MediaTopic it will create a row where no corresponding Topic row exists which causes the program to abort when executing the collection_select statement.  I guess I could add a numeric check validation and see if I get a more detailed error message.

It appears that when I do the update_attributes command it is attempting at the same time to update MediaTopic rows.  I guess my question is this.  Is there a way using nested attributes to build/rebuild the individual MediaTopic rows while keeping the validation the topic_id in MediaTopic?  Saying it another way: Can I with a single command update the MediaLibrary row and the MediaTopic rows where it knows which existing rows to remove and which ones to add?  I really like being able to have the selected Topics highlighted in the collection_select statement.  I'm hoping that this is possible by changing my collection_select statement somehow.  I can always go back the the manual process for now since this application is only used for admin purposes.  However I need a solution because I plan to do a similar process on a commercial project where the masses will access those screens.

Any help would be appreciated.


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users