Question

I have a Modality model with a related model ModalityItem. Modality has many :modality_items and ModalityItem belongs to :modality. One of the fields I want to display is a name field from MediaLibrary where the id matches media_library_id in ModalityItem.

I plan to allow up to 15 ModalityItem rows for each Modality. The Rails application will display either blank rows for ModalityItem when new records need to be added or ModalityItem row data when records exist.

Here is the code I have in the edit method of the modalities_controller where I can also rename the Modality. I have created array @items (Array.new(15)) and load each array element with either a row from ModalityItem or ModalityItem.new. If no ModalityItem rows exist for the selected Modality, the entire array will have 15 elements of ModalityItem.new. If ModalityItem rows exist I want to join the row to the corresponding MediaLibrary row and display its name on the edit view.

@modality = Modality.find(params[:id])
@modality_items = ModalityItem.joins('JOIN media_libraries ON media_libraries.id = modality_items.media_library_id').where("modality_id = ?", @modality.id).all
@items = Array.new(15)

count = 0
while count < @items.size
  if @modality_items && count < @modality_items.size
    @items[count] = @modality_items[count]
  else
    @items[count] = ModalityItem.new
  end
  count    += 1
end

Here is my code in the edit view.

<%= form_for(@modality) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <p style="font-weight: bold; font-size: 114%;"><%= link_to "Return to Manage Modalities", modalities_path %></p><br>
  <%= f.label :name, "Modality Name:" %>&nbsp;<%= f.text_field :name %><br><br>
  <%= f.fields_for :modality_items, @items do |item| %>
    <div class="modality-class">
      <%= item.label :media_library_id, "Media Library" %><%= item.text_field :media_library_id %> 
      <div class="short-label"><%= item.label :rank, "Rank" %></div><%= item.text_field :rank %> 
    </div><br><br>
    <div class="modality-instruct">
      <%= item.label :instructions, "Instructions" %><%= item.text_field :instructions %>
    </div><br><br>
  <% end %>
  <%= f.submit "Save changes to Modality", class: "btn btn-medium btn-custom" %><br><br>
  <p style="font-size: 114%; font-weight: bold;"><%= link_to "Delete this modality?", @modality, method: :delete, data: { confirm: "You sure you want to Delete this modality?" } %></p>
<% end %>

I have only used fields_for with a collection_select statement where I captured the id numbers of multiple items in my drop down list in an array. I used those ids to create another table related to the main table I was updating.

In this scenario I want to gather the information entered on the screen, loop through it and create my records. I plan to delete all existing ModalityItem rows for a Modality and recreate them each time. When I used fields_for with a collection_select I set an instance variable @whatevername equal to params[:whatevername] then looped through the ids. With the code I have included I would set @modality_items = params[:modality_items] then do something with it I guess. I have the following questions about what happens when someone enters data and clicks the button to update:

What does params[:modality_items] contain? Is it an array with all the text fields from the view?

Will @items be updated with the data from the form or will I have to save params[:modality_items]?

I'm sure this is basic information but this is my first time doing this and have been unsuccessful in finding the answer after doing many online searches about fields_for off and on for months now.

Note: I currently do not reference the name from MediaLibrary in my view because I need more information about how to access fields in fields_for before proceeding. I also have the issue of :name being in both the Modality and MediaLibrary models. The name in Modality is updatable but name of MediaLibrary will be display only in the fields_for statement.

Any help would be appreciated.

Was it helpful?

Solution

What does params[:modality_items] contain? Is it an array with all the text fields from the view?

Nothing. You really SHOULD look at your log files to see what is inside the params hash.

The :modality_items is an array nested inside params[:modality] so you get

params[:modality][:modality_items]

So form_for(@modality)gets you params[:modality] and then the f.fields_for (note the f piped in from the form_for) arranges for the fields_for params to be nested inside the modality hash as an array

Will @items be updated with the data from the form or will I have to save params[:modality_items]?

If you are using accepts_nested_attributes_for :modality_items inside your Modality model for the modality_items_attributes and those attributes are accessible (not protected from mass assignment then your rows will automatically be updated or inserted as appropriate. Basically accepts_nested_attributes_for accepts attriobutes nested inside the params hash that correspond to the same name.

This link from the official documentation explains clearly how the params hash is organised http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

And read here for more details on fields_for http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top