我对 Rails 将嵌套表单存储在数据库中的方式有疑问。我正在设计一个食谱网站(爱好),为此我创建了三个模型食谱、成分和成分食谱(代码如下)。成分可通过 has_many 和 Recipe 访问。所以菜谱可以有很多成分,成分可以属于很多菜谱。此外,IngredientRecipe 模型保存了每种配方和成分组合所独有的数量。
我的问题不是创建用于输入数据的嵌套表单,而是它存储在数据库中的方式。使用我当前的代码,每个新条目都会在 IngredienRecipe 模型中生成两行,一行用于配方和数量的组合,另一行用于配方成分关系。但是,我试图以一种方式对其进行设置,即每个条目在成分食谱表中恰好生成一行,将配方、成分和数量的独特组合链接在一起。
任何提示或代码片段都非常感谢,因为我已经被这个问题困扰了几天了:-(
这是我目前的模型:
class Recipe < ActiveRecord::Base
attr_accessible :description, :name
attr_accessible :ingredients_attributes, :ingredient_recipes_attributes
has_many :ingredient_recipes
has_many :ingredients, :through => :ingredient_recipes
accepts_nested_attributes_for :ingredients
accepts_nested_attributes_for :ingredient_recipes
end
class Ingredient < ActiveRecord::Base
attr_accessible :name, :unit
has_many :ingredient_recipes
has_many :recipes, :through => :ingredient_recipes
end
class IngredientRecipe < ActiveRecord::Base
attr_accessible :quantity
belongs_to :recipe
belongs_to :ingredient
end
修改后的配方控制器:
#Modified controller function
def new
@recipe = Recipe.new
@ingredients = @recipe.ingredients.build
@ingredient_recipes = @recipe.ingredient_recipes.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: @recipe }
end
end
和 form_for 视图文件
<%= form_for @recipe do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<%=f.fields_for :ingredients do |ff|%>
<div class="field">
<%= ff.label :name %><br />
<%= ff.text_field :name %>
</div>
<%= f.fields_for :ingredient_recipes do |fff| %>
<div class="field">
<%= fff.label :quantity%><br />
<%= fff.text_field :quantity %>
</div>
<% end -%>
<div class="field">
<%= ff.label :unit %><br />
<%= ff.text_field :unit %>
</div>
<% end -%>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
好的,在多次检查我的代码之后,我终于想出了一个更好的解决我的问题的方法。诀窍在于通过Recipe --> Ingredient --> JOIN table将模型相互嵌套。我当前的解决方案还没有动态添加 fields_for,但是这个版本不需要对 recipes_controller 进行任何更改。如果其他人也在为此苦苦挣扎,这是我的代码:
class Recipe < ActiveRecord::Base
attr_accessible :description, :name, :ingredients_attributes
has_many :unique_recipes
has_many :ingredients, :through => :unique_recipes
accepts_nested_attributes_for :ingredients
end
class UniqueRecipe < ActiveRecord::Base
attr_accessible :quantity, :recipe_id, :ingredient_id
belongs_to :recipe
belongs_to :ingredient
end
class Ingredient < ActiveRecord::Base
attr_accessible :name, :unit, :unique_recipes_attributes
has_many :unique_recipes
has_many :recipes, :through => :unique_recipes
accepts_nested_attributes_for :unique_recipes, allow_destroy: true
end
<%= form_for @recipe, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.label :name, :class => %>
<%= f.text_field :name, :class => 'text_field' %>
<%= f.label :description, :class => 'control-label' %>
<%= f.text_area :description, :class => 'text_area' %>
<%= f.fields_for :ingredients do |ff| %>
<%= ff.label :name, :class => %>
<%= ff.text_field :name, :class => 'text_field' %>
<%= ff.label :unit, :class => %>
<%= ff.text_field :unit, :class => 'text_field' %>
<%= ff.fields_for :unique_recipes do |fff| %>
<%= fff.label :quantity, :class => %>
<%= fff.text_field :quantity, :class => 'text_field' %>
<% end -%>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
recipes_path, :class => 'btn' %>
<% end %>