Nested forms regarding association belongs_to

57 Views Asked by At

I have the classes Person and Fingerprint and I want to work with nested forms in order to fill Fingerprint's attributes.

The implementation is as follows:

class Person < ApplicationRecord
  belongs_to :fingerprint
end

class Fingerprint < ApplicationRecord
end

Person's controller:

def create
    @person = Person.new(person_params)
    @person.build_fingerprint

    respond_to do |format|
      if @person.save
      ....
end

def person_params
  params.require(:person).permit(:name, fingerprints_attributes: [:fingertips_category])
end

Person's form:

%= form_with(model: person) do |form| %>
...

  <div>
    <%= form.label :name, style: "display: block" %>
    <%= form.text_area :name %>
  </div>
    <%= form.fields_for :fingerprint do |fingerprint_form| %>
    <%= fingerprint_form.label :fingertips_category %>
    <%= fingerprint_form.text_field :fingertips_category %>
    <% end %>
  <div>
    <%= form.submit %>
  </div>
<% end %>

Unfortunately, I don't get how to initialize the Fingerprint's attributes with the help of build_fingerprint method.

2

There are 2 best solutions below

0
smathy On

There's nothing about it being a belongs_to association that means you can't use accepts_nested_attributes_for :fingerprint just like a has_* association.

Only thing is that you need fingerprint_attributes (not fingerprints... plural) in your permit call. So then in the create you'd just have the @person = Person.new(person_params) and then @person.save. You haven't shown it here but in your new action you would need to instantiate the fingerprint in the @person record you're using in the form.

0
cd4user On

Solved: I've figured out some useful links for all those people who are struggling with nested forms regarding belongs_to.

As smathy mentioned, it's not possible to use accepts_nested_attributes_for with belongs_to. And actually, you would have to take a circuitous way to reach that goal with belongs_to. So, I will work with has_one instead of belongs_to

https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

https://discuss.rubyonrails.org/t/nested-has-one-object-should-be-built-automatically-when-nessecary/75271/4

Edit: I forgot to give the solution regarding belongs_to:

class Fingerprint < ActiveRecord::Base
end

class Person < ApplicationRecord
  belongs_to :fingerprint

 def fingerprint_attributes=(fingerprint_attributes)
    self.fingerprint = Fingerprint.new
    fingerprint_attributes.each do |i, fingerprint_attribute|
      self.fingerprint.fingertips_category = fingerprint_attribute
    end  
  end

end

Person's controller:

 def new
    @person = Person.new
    @person.build_fingerprint  
  end

  def create
    @person = Person.new(person_params)
    
    respond_to do |format|
      if @person.save
        ...
      end
    end
  end

def person_params
      params.require(:person).permit(:name, fingerprint_attributes: [:fingertips_category])
    end

Person's _form.thml.erb

<%= form_with(model: person) do |form| %>
...

  <div>
    <%= form.label :name, style: "display: block" %>
    <%= form.text_area :name %>
  </div>
    <%= form.fields_for :fingerprint do |fingerprint_form| %>
    <%= fingerprint_form.label :fingertips_category %>
    <%= fingerprint_form.text_field :fingertips_category %>
    <% end %>
  <div>
    <%= form.submit %>
  </div>
<% end %>