0

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.

2
  • I haven't read through your whole question, but I usually check for empty params using !params[:name] - if it can help.
    – Justin D.
    Commented Aug 8, 2013 at 0:47
  • The problem is probably related to how I am processing the rows from media_topics. I am manually adding/deleting them using the Topic model that a person selects from. An empty hash/array is valid in this instance. I need to figure out how to get it to display properly. Either that or there may be another way for me to do this process. I will submit another question related to that issue which may solve this problem where I will not have an empty hash when trying to display my views. Commented Aug 8, 2013 at 20:43

1 Answer 1

0

I have been doing more research and noticed that when using fields_for in a form it is designated as f.fields_for, not fields_for as I have them in my application. I changed the view to use f.fields_for and noticed that the selected options are appearing in my drop down list for the Topic model. Hopefully this will take care of the problem I was having in my other question. At least I am no longer getting the 500 error. I will probably rewrite the code I have for updating the MediaTopic rows in my controller since now it is using the media_topic_attributes in my view.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.