DEV Community

n350071🇯🇵
n350071🇯🇵

Posted on

2ways for making nested form in Rails

1. fields_for

  • Simple way
<%= form_with(model: rental_form, local: true) do |f| %>
  <%= f.fields_for(:terms, rental_form.terms) do |t| %>
  <div class="row my-3">
    <div class="col-11 mx-auto text-center border shadow">
        <h3>Term</h3>
        <div class="row">
          <div class="col-3 border-right">
            Start ~ End
          </div>
          <div class="col">
            <%= t.date_field :start %>
            ~
            <%= t.date_field :end %>
          </div>
        </div>
    </div>
  </div>
  <% end %>
<% end %>
Enter fullscreen mode Exit fullscreen mode

it needs 2 methods

About the terms_attributes method.

  • It should be as a public method.
  • It is called from initialize of the ActiveModel, so you need to include ActiveModel
class Contracts::RentalForm < ApplicationForm
  attr_accessor :terms
  def terms_attributes=(attributes)
    self.terms = attributes.map{ |_, term_attributes|
      Contracts::Rentals::Term.new(term_attributes)
    }
  end
end
Enter fullscreen mode Exit fullscreen mode
class ApplicationForm
  include ActiveModel::Model
end
Enter fullscreen mode Exit fullscreen mode

Example of the params

attributes #=> {"0"=>{"id"=>"5", "start"=>"2020-12-23", "end"=>""}, "1"=>{"id"=>"6", "start"=>"2020-12-23", "end"=>""}}
Enter fullscreen mode Exit fullscreen mode

2. manual setting

  • You don't need to implement the terms_attributes method.
        <% rental_form.terms.each.with_index do |term, index| %>
        <div class="row">
          <div class="col-3 border-right">
            Start ~ End
          </div>
          <div class="col">
            <%= f.date_field "[terms][#{index}][start]" %>
          </div>
        </div>
        <% end %>
Enter fullscreen mode Exit fullscreen mode

Top comments (0)