I have a Ruby on Rails 3.2.13 application where I have one model related to several models. I will give information about one of them related models to explain the scenario. I have new and edit views that I use in my maintenance screen. I am still pretty new to working with nested attributes. My maintenance screen allows maintenance of a row with associated attributes. I manually grab the selected rows and write them out associated with my parent row. I display them in a list on top of the collection_select drop down list box. However with doing some recent checking after some problems with 500 errors I noticed that I had some software problems I need to correct.
I have my error checking code in the update method where I render edit after finding the error. When it attempts to display the edit view I get a 500 error where it is trying to find the array of one of my nested attributes. Here is an error I recently got.
Completed 500 Internal Server Error in 24ms
ActionView::Template::Error (undefined method `topic_id' for {"topic_id"=>[""]}:ActiveSupport::HashWithIndifferentAccess):
56: <p style="padding-left: 150px; color: #f8ee5f;"><%= display_topics @media_library %></p>
57: <% end %>
58: <%= fields_for :media_topics do |media_topic| %>
59: <%= media_topic.label :topic, "Topics" %><%= media_topic.collection_select(:topic_id, Topic.order("name_en"), :id, :name_en, {}, {multiple: true}) %>
60: <% end %><br>
61:
62: <% if @media_library.media_targets.count > 0 %>
app/views/media_libraries/_media_library_fields.html.erb:59:in `block in _app_views_media_libraries__media_library_fields_html_erb___4316101037373251257_70115028003400'
app/views/media_libraries/_media_library_fields.html.erb:58:in `_app_views_media_libraries__media_library_fields_html_erb___4316101037373251257_70115028003400'
app/views/media_libraries/edit.html.erb:7:in `block in _app_views_media_libraries_edit_html_erb__2448603971022600459_70115028733680'
app/views/media_libraries/edit.html.erb:6:in `_app_views_media_libraries_edit_html_erb__2448603971022600459_70115028733680'
app/controllers/media_libraries_controller.rb:115:in `update'
Here is how I have my MediaLibrary model defined related to the MediaTopic model. I'm only including the portions of the models that relate to my question.
class MediaLibrary < ActiveRecord::Base
attr_accessible :media_topics_attributes
has_many :media_topics, dependent: :destroy
accepts_nested_attributes_for :media_topics
class MediaTopic < ActiveRecord::Base
belongs_to :media_library
Here is the my edit method:
def edit
@media_library = MediaLibrary.find(params[:id])
@edit_page = true
end
This statement is where I grab the array of selected media_topics from the collection_select for the Topic model (where media_topics gets its topic_id value related to the MediaLibrary model)
@media_topics = params[:media_topics]
Here is a sample of the error checking in the update method.
case
when params[:link].blank? && params[:link_video].blank? && params[:link_pdf].blank? && params[:resource].blank? && params[:resource2].blank? && params[:resource3].blank?
flash.now[:error] = "You must enter at least one link before creating a Media Library Item."
render 'edit'
else
some update logic here
end
Here is the code from my edit view. The display_topics helper displays the list of related topic rows above the drop down list of topics.
<% if @media_library.media_topics.count > 0 %>
<p style="padding-left: 150px; color: #f8ee5f;"><%= display_topics @media_library %></p>
<% end %>
<%= 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 %><br>
Here is the display_topics helper:
def display_topics(media_library)
media_library_topics = MediaTopic.where("media_library_id = ?", media_library.id).all
topic_list = nil;
if media_library_topics
i = 1
media_library_topics.each do |mltopic|
topic_row = Topic.find(mltopic.topic_id)
case I18n.locale.to_s
when "fr"
topic_name = topic_row.name_fr
when "pt"
topic_name = topic_row.name_pt
when "es"
topic_name = topic_row.name_es
else
topic_name = topic_row.name_en
end
if i == 1
if media_library_topics.size == 1
topic_list = "#{t :media_label_topic}: "+topic_name
else
topic_list = "#{t :media_label_topics}: "+topic_name
end
else
topic_list = topic_list+" | "+topic_name
end
i += 1
end
"#{topic_list}"
end
end
I do not know of another way to work with the nested_attributes than to manually add them or delete/re-add them.
What I do not know is that when I render 'edit' a second time what happens to the nested attributes from the form? From what I am seeing in this error it seems like this disappear, hence the undefined method :topic_id.
I have done a lot of searching off and on since I developed this function but I have not seen this error mentioned. All of the examples I remember do not show situations with nested attributes where a person is rendering the edit view back to back, first to initially display the records then to show errors.
How do I get my nested attributes back to the view a second time?
Any help would be appreciated.
!params[:name]
- if it can help.