Ruby on Rails nested attributes not saving into da

2019-08-03 17:26发布

问题:

I'm trying to create a list of items within a "Todo list", however, I'm not sure if I'm doing this correctly with nested attributes. I think using a nested attribute is the right attempt because there's going to be a large list of items, and it will be associated with the correct "Todo list" based on ids.

Example of what the tables might look like when records are populated

Todo table

id         list       
1          grocery shopping
2          health insurance

Item table

id         todo_id        name           
1          1              buy milk
2          1              buy cereal
3          2              Blue Shield
4          2              Healthnet
5          1              buy cherries

Although, with my attempt below, my application is not saving any of the data into the Item database.

Todo Controller

class TodoController < ApplicationController
  def new
    @todo = Todo.new
    @todo.items.build
  end
end

Todo Model

class Todo < ActiveRecord::Base
  belongs_to :user
  has_many :items
  accepts_nested_attributes_for :items
end

Item Model

class Item < ActiveRecord::Base
    belongs_to :todo
end

Todo View

<%= simple_form_for(@todo) do |f| %>
  <%= f.input :list %>

  <%= f.simple_fields_for :items do |g| %>
    <%= g.input :name %>
  <% end%>

  <%= f.button :submit %>
<% end %>

I was able to have the name field show up in my view, but when I save it, it doesn't save into the database, however, I'm able to save the list into the database, and then when I try to edit the record, the name field doesn't show up anymore to be able to edit.


EDIT: to show create method

This is my current Create Method in Todo Controller

def create
  @todo = Todo.new(todo_params)

  respond_to do |format|
    if @todo.save
      format.html { redirect_to @todo, notice: 'Todo was successfully created.' }
      format.json { render :show, status: :created, location: @todo }
    else
      format.html { render :new }
      format.json { render json: @todo.errors, status: :unprocessable_entity }
    end
  end
end

Not sure if Edit needs to have something, but I only have this from generating a scaffold of Todo

def edit
end

EDIT 2 show todo_params

def todo_params
  params.require(:todo).permit(:user_id, :list)
end

回答1:

You must add the nested params to your strong params

def todo_params
  params.require(:todo).permit(:user_id, :list, items_attributes: [:id, :text, ...])
end

Note about todo_id :

You don't need to add :todo_id in items_attributes list, because you already have the TODO as context.

@todo = Todo.new(todo_params)

In the above code, your todo_params will contain some item_attributes linked to @todo. ie, it's similar to doing

@todo.items.build

It will already create an item with a todo_id corresponding to @todo.id



回答2:

You need to add the items to the list of whitelisted attributes

def todo_params
 params.require(:todo).permit(
   :user_id, 
   :list,
   items_attributes: [ # you're missing this
     :id,
     :name
   ]
 )
end