我有三个模型。我遇到的两个(食谱和成分)彼此都有has_and_belongs_to_many
关系。该表单似乎正在获取我要求的所有信息,但我似乎无法将成分的名称属性放入我允许的参数中。
形式:
<%= form_for(@recipe, :url => create_path) do |f| %>
<%= f.label :category %>
<%= f.select :category_id, options_for_select(Category.all.map{|c|[c.title, c.id]}) %>
<%= f.label :title %>
<%= f.text_field :title%>
<%= f.label :instruction %>
<%= f.text_area(:instruction, size: "50x10") %>
<%= f.fields_for :indgredient do |i| %>
<%= i.label :name %>
<%= i.text_field :name %>
<% end %>
<%= f.submit "Submit" %>
配方控制器中的相关操作:
def create
safe_params = params.require(:recipe).permit(:title, :instruction,
:category_id, {ingredient: :name})
@recipe = Recipe.new(safe_params)
@recipe.save
@recipe.ingredients.create(name: safe_params[:name])
render body: YAML::dump(safe_params)
end
YAML 转储给了我什么:
--- !ruby/hash:ActionController::Parameters
title: foo
instruction: bar
category_id: '1'
模型代码:
class Category < ActiveRecord::Base
has_many :recipes
end
class Recipe < ActiveRecord::Base
has_and_belongs_to_many :ingredients
accepts_nested_attributes_for :ingredients
belongs_to :category
end
class Ingredient < ActiveRecord::Base
has_and_belongs_to_many :recipes
end
create
方法确实会创建一个新成分,但名称为 nil。提前感谢您的帮助。
您是否在Recipe
模型中添加了accepts_nested_attributes_for :ingredients
?
此外,还有一个 gem 可以处理嵌套形式,称为 cocoon
.
您可以阅读这篇文章,其中确切地解释了您要做的事情。https://hackhands.com/building-has_many-model-relationship-form-cocoon/
首先,将<%= f.fields_for :indgredient do |i| %>
更改为<%= f.fields_for :ingredients do |i| %>
。
并更改new
并create
操作,如下所示
def new
@recipe = Recipe.new
@recipe.ingredients.build
end
def create
@recipe = Recipe.new(safe_params)
if @recipe.save
redirect_to @recipe
else
render 'new'
end
end
private
def safe_params
params.require(:recipe).permit(:title, :instruction, :category_id, ingredients_attributes: [:name])
end
为了补充@Pavan
的答案,你必须记住Ruby正在构建对象(它是一种面向对象的语言),因此,每当你传递相关数据时,你必须引用Ruby内存中的对象。
在您的情况下,您正在尝试通过Recipe
创建新的Ingredient
对象:
#app/models/recipe.rb
class Recipe < ActiveRecord::Base
has_and_belongs_to_many :ingredients
accepts_nested_attributes_for :ingredients
end
。因此,您需要引用ingredients
:
<%= f.fields_for :ingredients do ... %>
--
您还需要确保仅在create
操作中处理Recipe
对象:
def create
@recipe = Recipe.new safe_params
@recipe.save
end
private
def safe_params
params.require(:recipe).permit(:title, :instruction, :category_id, ingredients_attributes: [:name] )
end