我正在尝试从 Rails 5 中的一个表单创建一个recipe
对象和多个嵌套的ingredient
对象。 就目前而言,我能够创建recipe
对象,但在传递params
以创建ingredient
对象时出现错误,特别是NoMethodError
:
undefined method `ingredient' for #<Ingredient id: nil, ing: "s", amount: "s", recipe_id: nil>
这是我的表格:
<%= form_for(@recipe, url: recipes_new_path) do |f| %>
<h1>
<%= f.label :name %><br>
<%= f.text_field :name %><br>
</h1>
<h1>
<%= f.label :steps %><br>
<%= f.text_area :steps %><br>
</h1>
<%= f.fields_for :ingredient do |p| %>
<h1>
<%= p.label :ing %><br>
<%= p.text_area :ing %><br>
</h1>
<h1>
<%= p.label :amount %><br>
<%= p.text_area :amount %><br>
</h1>
<% end %>
<%= f.submit "Add" %><br>
包含在 routes.rb 中:
....
resources :recipes do
resources :ingredients
end
包含在模型中:
class Ingredient < ApplicationRecord
belongs_to :recipe
....
end
class Recipe < ApplicationRecord
has_many :ingredients, dependent: :destroy
....
accepts_nested_attributes_for :ingredients, allow_destroy: true
validates_associated :ingredients
end
recipe
控制器:
....
def new
@recipe = Recipe.new
@ingredient = @recipe.ingredients.build
end
def create
@recipe = Recipe.new(recipe_params)
@recipe.save
@ingredient = @recipe.ingredients.build(recipe_params[:ingredients_attributes])
if @ingredient.save
redirect_to recipe_path(@recipe)
else
render 'recipes/new'
end
end
....
def recipe_params
params.require(:recipe).permit(:name, :steps, ingredients_attributes: [:ing, :amount])
end
据我所知,我要么错误地传递params
来创建ingredient
对象,要么根本不应该尝试在recipe
控制器中创建ingredient
对象。
编辑
形式变化自
<%= f.fields_for :ingredient do |p| %>
自
<%= f.fields_for :ingredients do |p| %>
编辑
完全错误:
Started POST "/recipes" for ::1 at 2016-12-14 09:19:43 -0600
Processing by RecipesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"RfBXiL7vFla2/SvLqR2WrgzsfFMOqVRpjTavmvrPMJ/YBhF7UR+CeGV5NNRNyQfuALuJXc9hafPre+wPOo6n2A==",
"recipe"=>{"name"=>"a", "steps"=>"a", "ingredients_attributes"=>{"0"=>{"ing"=>"a", "amount"=>"a"}}},
"commit"=>"Add"}
(0.1ms) begin transaction
(0.1ms) rollback transaction
Completed 500 Internal Server Error in 37ms (ActiveRecord: 0.2ms)
NoMethodError (undefined method `ingredient' for #<Ingredient id: nil, ing: "a", amount: "a", recipe_id: nil>
Did you mean? increment):
app/controllers/recipes_controller.rb:14:in `create'
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (5.6ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.8ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (2.5ms)
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (154.0ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/index.html.erb
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/_markup.html.erb (0.7ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/console.js.erb within layouts/javascript
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string (1.5ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string (0.9ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/style.css.erb within layouts/inlined_string
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/style.css.erb within layouts/inlined_string (0.6ms)
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/console.js.erb within layouts/javascript (148.7ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/main.js.erb within layouts/javascript
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/main.js.erb within layouts/javascript (0.6ms)
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/index.html.erb (284.4ms)
我相信你只需要改变你的fields_for
来使用"成分"复数:
<%= f.fields_for :ingredient do |p| %>
这是因为您的食谱has_many :ingredients
.如果您的食谱只has_one :ingredient
那么您的表格将按书面形式工作。
更新:您还应该更改create
方法,如下所示:
def create
@recipe = Recipe.new(recipe_params)
if @recipe.save
redirect_to recipe_path(@recipe)
else
render 'recipes/new'
end
end
因为您是通过recipe
参数传递ingredients_params
,所以您无需单独创建成分 - 它们将由accepts_nested_attributes_for
在您的食谱模式下自动创建。
有关嵌套表单的永恒教程,请参阅 Ryan Bates 的 Railscasts 上的嵌套模型表单。