【发布时间】:2013-11-03 15:27:51
【问题描述】:
我正在尝试使用三个主要模型构建一个配方管理器应用程序:
食谱 - 特定菜肴的食谱
成分 - 成分列表,经过独特性验证
数量 -成分和配方之间的连接表,还反映了特定配方所需的特定成分的量。
我正在使用嵌套表单(见下文),我使用嵌套表单(Part 1、Part 2)上的出色 Railscast 构建以获取灵感。 (由于这个特定模式的需要,我的表单在某些方面比教程更复杂,但我能够使其以类似的方式工作。)
但是,当我提交表单时,列出的所有成分都会重新创建 - 如果该成分已存在于数据库中,则它无法通过唯一性验证并阻止创建配方。总阻力。
所以我的问题是: 有没有办法提交此表单,以便如果存在名称与我的某个成分名称字段匹配的成分,它会引用现有成分,而不是尝试创建新的同名?
下面的代码细节...
在Recipe.rb:
class Recipe < ActiveRecord::Base
attr_accessible :name, :description, :directions, :quantities_attributes,
:ingredient_attributes
has_many :quantities, dependent: :destroy
has_many :ingredients, through: :quantities
accepts_nested_attributes_for :quantities, allow_destroy: true
在Quantity.rb:
class Quantity < ActiveRecord::Base
attr_accessible :recipe_id, :ingredient_id, :amount, :ingredient_attributes
belongs_to :recipe
belongs_to :ingredient
accepts_nested_attributes_for :ingredient
在Ingredient.rb:
class Ingredient < ActiveRecord::Base
attr_accessible :name
validates :name, :uniqueness => { :case_sensitive => false }
has_many :quantities
has_many :recipes, through: :quantities
这是我的嵌套表单,显示在 Recipe#new:
<%= form_for @recipe do |f| %>
<%= render 'recipe_form_errors' %>
<%= f.label :name %><br>
<%= f.text_field :name %><br>
<h3>Ingredients</h3>
<div id='ingredients'>
<%= f.fields_for :quantities do |ff| %>
<div class='ingredient_fields'>
<%= ff.fields_for :ingredient_attributes do |fff| %>
<%= fff.label :name %>
<%= fff.text_field :name %>
<% end %>
<%= ff.label :amount %>
<%= ff.text_field :amount, size: "10" %>
<%= ff.hidden_field :_destroy %>
<%= link_to_function "remove", "remove_fields(this)" %><br>
</div>
<% end %>
<%= link_to 'Add ingredient', "new_ingredient_button", id: 'new_ingredient' %>
</div><br>
<%= f.label :description %><br>
<%= f.text_area :description, rows: 4, columns: 100 %><br>
<%= f.label :directions %><br>
<%= f.text_area :directions, rows: 4, columns: 100 %><br>
<%= f.submit %>
<% end %>
link_to 和 link_to_function 允许动态添加和删除数量/成分对,并且改编自前面提到的 Railscast。他们可以使用一些重构,但或多或少地工作。
更新:根据 Leger 的要求,这里是来自 recipes_controller.rb 的相关代码。在Recipes#new 路由中,3.times { @recipe.quantities.build } 为任何给定配方设置三个空白数量/配料对;这些可以使用上面提到的“添加成分”和“删除”链接即时删除或添加。
class RecipesController < ApplicationController
def new
@recipe = Recipe.new
3.times { @recipe.quantities.build }
@quantity = Quantity.new
end
def create
@recipe = Recipe.new(params[:recipe])
if @recipe.save
redirect_to @recipe
else
render :action => 'new'
end
end
【问题讨论】:
标签: ruby-on-rails ruby ruby-on-rails-3 forms