Rails 3.2.13 - Delete Entry From Nested Attributes

2019-08-29 16:08发布

I have a Ruby on Rails 3.2.13 application where I have a collection_select statement. The collection_select statement is in a fields_for statement where I gather selected ids from the collection_select and use them to populate another table. The problem I am having is that the collection_select statement adds a null id entry in the array that stores the collection of selected ids.

Here is my code in my view:

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

Here is an example of how the array looks after selecting two options:

"media_topics_attributes"=>{"0"=>{"topic_id"=>["", "2", "47"], "id"=>"1895"}}

I have found out through another Stack Overflow member that the blank entry in the collection_select is a hidden value that is automatically being included. In Rails 3 there is no way to not include that field. However according to the link provided in an answer to my previous question Rails 3.2 - collection_select Adding A Null Entry In The First Position Of My Array there will be a way to exclude this hidden value in Rails 4.

I was skipping this value and adding the MediaTopic rows manually before I decided to use accepts_nested_attributes_for for the first time. I want to make my controller code cleaner than it is right now. The problem I'm having is figuring out how to skip that blank entry. I have read the API and many other posts on how I should be able to skip this value but none of them are working.

Here is the code I have for the media_topics nested attributes in my MediaLibrary model.

has_many :media_topics, dependent: :destroy
accepts_nested_attributes_for :media_topics, allow_destroy: true, reject_if: proc { |attributes| attributes['id'].blank? }

The Topic model in the collection_select has field :id that will update field :topic_id in model MediaTopic. The other field in MediaTopic is :media_library_id. I have tried field id and topic_id in the accepts_nested_attributes_for command but when I do an update_attributes for the main model I get an error saying that the topic can't be blank. I'm sure the error is coming from trying to create the MediaTopic row for the first blank entry in the array.

I have researched this for several days but nothing I have tried works. I have checked the API, APIDock and other sources to no avail. I want to remove the blank entry from media_topics_attributes before I do update_attributes. I guess I'm not understanding how to write the code. I have seen this in the API as an example but I have no idea where this should go or how I should code this to get rid of the blank value.

params = { member: {
  posts_attributes: [{ id: '2', _destroy: '1' }]
}}

Any help would be appreciated.

UPDATE 8/10/2013 10:46 pm CDT

In my controller I have the following when clause in my case statement after all error checking is complete.

when @media_library.update_attributes(params[:media_library])

UPDATE 8/12/2013 8:20 am CDT

In the MediaLibrary model I changed my accepts_nested_attributes_for to the following.

accepts_nested_attributes_for :media_topics, allow_destroy: true

UPDATE 8/12/2013 10:50 am CDT

Here is what the hash looks like in my debug:

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

However I still get the error Media topics topic can't be blank. I will keep looking.

UPDATE 8/12/2013 12:15 pm CDT

Topic is a model with a list of names (:id, :name)

MediaLibrary is a list of rows that I want to be able to select by Topic.name

MediaTopic is a list of rows that relate Topic to MediaLibrary

MediaLibrary has_many :media_topics, dependent: :destroy

Topic has_many :media_topics

MediaTopic belongs_to :media_library belongs_to :topic

The screen I am working on will make changes to MediaLibrary and update MediaTopic depending on a collection_select statement listing Topic names.

2条回答
啃猪蹄的小仙女
2楼-- · 2019-08-29 16:45

According to @vinodadhikary the null entry in the array is working as expected in Rails 3. I recently rewrote this application in Rails 4. I completely rewrote the logic by first using has_many through to relate all my tables. I also replaced the fields_for logic by just using a collection_select statement. I added include_hidden = false in the first {} and the null entry does not appear in the array. I asked a similar question a few days ago and after a lot of searching I came up with a solution. Details are in the link below.

Rails 4 - Using collection_select to get an array of ids for an Intermediate Table with Nested Attributes

查看更多
地球回转人心会变
3楼-- · 2019-08-29 16:48

in the MediaLibrary model

alias_method :underlying_media_topics_attributes=, :media_topics_attributes=

def media_topics_attributes=(hash_of_hashes)
  hash_of_hashes.each { |key, hash| hash[:topic_id].reject!(&:blank?) }
  self.underlying_media_topics_attributes=(hash_of_hashes)
end
查看更多
登录 后发表回答