Nested Attributes with Rails

Asked

Viewed 514 times

2

I’m developing a system for study, which will allow the creation of a user. This user, in turn, will have an inventory, which will have several items.

My question is how to save all these resources at once when accessing the action new of UsersController.

I’m using the cocoon, and the error that appears is:

undefined method `new_record?' for nil:NilClass

Models

class User < ActiveRecord::Base
  has_one :inventory

  delegate :items, to: :inventory, prefix: true

  accepts_nested_attributes_for :inventory
end

class Inventory < ActiveRecord::Base
  has_many :inventory_items
  has_many :items, through: :inventory_items

  accepts_nested_attributes_for :inventory_items, reject_if: :all_blank, allow_destroy: true
end

class InventoryItem < ActiveRecord::Base
  belongs_to :item
  belongs_to :inventory
end

Controller

class UsersController < ApplicationController
  def new
    @user = User.new.tap do |user|
      user.inventory = Inventory.new
      user.inventory_items.build
    end
  end

  private

  def user_params
    params
      .require(:user)
      .permit(
        :name,
        :lat,
        :long,
        :age,
        inventory_attributes: [:id, inventory_items_attributes: [:quantity, :inventory_id, :item_id, :_destroy]]
      )
  end
end

Form for user registration

<%= simple_form_for(@user) do |f| %>
  <%= f.error_notification %>

  <div class="form-inputs">
    <%= f.input :name %>
    <%= f.input :lat %>
    <%= f.input :long %>
  </div>

  <h3>Items</h3>
  <div id="inventory_items">
    <%= f.simple_fields_for :inventory do |inventory| %>
      <%= inventory.simple_fields_for :inventory_items do |f| %>
        <%= render 'item_fields', f: f %>
      <% end %>
    <% end %>
  </div>

  <div class="form-actions">
    <%= f.button :submit %>
  </div>
<% end %>

Partial for the items

<div class="nested-fields">
  <%= f.collection_select :item_id, Item.all, :id, :name %>
  <%= f.input :quantity %>
  <%= link_to_remove_association "remove item", f %>
</div>

Observing: The inventory has no attribute other than its id and the user_id.

2 answers

2

Good morning!

Try to change that:

<h3>Items</h3>
  <div id="inventory_items">
    <%= f.simple_fields_for :inventory do |inventory| %>
      <%= inventory.simple_fields_for :inventory_items do |f| %>
        <%= render 'item_fields', f: f %>
      <% end %>
    <% end %>
  </div>

For that reason:

<h3>Items</h3>
  <div id="inventory_items">
    <%= f.simple_fields_for :inventory do |inventory| %>
      <%= inventory.simple_fields_for :inventory_items do |item| %>
        <%= render 'item_fields', f: item %>
      <% end %>
    <% end %>
  </div>

You might be getting lost in the f’s because they’re referencing different things.

I hope I’ve helped.

0

Browser other questions tagged

You are not signed in. Login or sign up in order to post.