2

I am using a link from an index page that has a group of nested records (row) that I need to update all at once. The link goes to an edit action that I need to make update the attributes of nested records (prisms).

  1. I tried using the simple_form gem methods for nested models. It gives me a field for all of the objects, when I only want one field to enter a value to them all. The builder from that looks usable, but I don't know how to use it to update the fields. Either way, the form isn't right.

  2. I have tried every variation of form_for and fields_for I could find on Google to develop the edit form. It looks like I'm the only one on Earth trying to solve this problem.

This is how I have my routes set up:

resources :gardens, shallow: true do
    resources :prisms
    resources :rows

Here is how my garden model is now:

class Garden < ApplicationRecord
  mount_uploader :picture, ImageUploader
  belongs_to :user
  has_one :photo
  has_many :rows, :dependent => :destroy
  has_many :prisms
  geocoded_by :address
  after_validation :geocode
  after_commit :populate_garden!

def id
    self[:id]
  end

  def populate_garden!
    # row 0
    (0..length-1).each do |i|
      Row.create(row_num: i, garden_id: id)
    end
  end
end

The garden model creates my rows through the populate_garden! method.

Here is the row model:

class Row < ApplicationRecord
  belongs_to :garden
  has_many :prisms, :dependent => :destroy
  accepts_nested_attributes_for :prisms
  after_commit :populate_rows

  def id
    self[:id]
  end


  def populate_rows
    # row 0
    (0..garden.width-1).each do |i|
        Prism.create(:row_id => self.id, :row_num => self.row_num, :col_num => i, :garden_id => self.garden_id)
    end
  end
end

The row model creates prisms in the populate_rows method.

Here is the prism model:

class Prism < ApplicationRecord
  belongs_to :row
  belongs_to :garden

  include RankedModel
  ranks :column_order
end

Here is the table from my index.html.erb that I click to open the edit action.

<table>

    <% @rows.each_with_index do |gardenrow, index| %>
      <% @rows.select { | row | row.row_num == index}.each do |row| %>

        <td class="prism-cols">
          <%= link_to 'Edit Row', edit_row_path(row), class:"dark-link" %>
          <br /><i class="fas fa-arrow-down"></i>
        </td>

      <% end %>
    <% end %>
</table>

The row passes nicely into the edit action, and I currently have this incorrect form:

<h1>The row brought into this form page is: </h1>
<%= @row.inspect %>

<div class="container">
  <%= simple_form_for @row do |m| %>
    <%= m.simple_fields_for :prisms do |p| %>
      <%= p.input :crop_name %>
    <% end %>
    <%= m.button :submit %>
  <% end %>
</div>

The rows_controller update method looks like this:

def update
    @row = Row.find(params[:row_id])
    @row.prisms.build
    redirect_to root_path
end

I need one form field for crop_name that will change all of the prisms in the selected row with a single submit. I don't have any problems updating one prism at a time through an edit action on the prism. The difficulty I'm having is working through the nesting of prisms inside of a specific row.

With the help of my mentor below I was able to develop a form that works with the controller to make this work. Here is the updated code for later use with this type of problem.

Here is the form data:

<%= form_tag({controller: "rows", action: "update"}, method: "patch") %>
    <%= label_tag(:crop_name, "Crop Name") %>
    <%= text_field_tag(:crop_name) %>
    <%= hidden_field_tag(:row_id, @row.id) %>
    <%= submit_tag("submit") %>

Here is the controller update method:

def update
    @row = Row.find(params[:id])
    @garden = Garden.find_by_id(:garden_id)
    @row.prisms.each do |p|
      p.crop_name = params[:crop_name]
      p.save!
    end
    redirect_to :controller => 'gardens', :action => 'show', id: @row.garden_id
  end

Thanks for the help. I don't think I could have figured this out from the documentation alone.

1 Answers1

0

If I'm understanding correctly, I think simple_form may be limiting you. A basic ruby form may do what you want. I'm not 100% sure what the best way is to do a simple_form on nested fields but this stackoverflow answer may be able to help more.

Using a basic ruby form You want a form that has one field. When submitted, it will take the value from the submitted form and update that field for all prisms of that row. I would recommend digging more into the basics of ruby forms for this kind of scenario and then do something like this.

// html.erb

<%= form_tag({controller: "rows", action: "update_prism_crop_name"}, method: "post", class: "nifty_form") %>
  <%= label_tag(:crop_name, "Crop name") %>
  <%= text_field_tag(:crop_name) %>
  <%= hidden_field_tag(:row_id, @row.id) %>
  <%= submit_tag("Submit") %>
<% end %>


// rows_controller

def update_prism_crop_name
   @row = Row.find(params[:row_id])
   @row.prisms.each do |prism|
      prism.crop_name = params[:crop_name]
      prism.save!
   end
   # other redirect stuff
end

The form_tag explicitly calls out an action but I have to imagine that you'll need to build a route for this custom action as well.

I haven't tested any of this and I'm a bit rusty in rails but I believe something like this would work.

Aarmora
  • 1,143
  • 1
  • 13
  • 26