我有一张食材表。当用户输入一种成分时,它会保存在表格中。现在我注意到的是,许多记录重复,我不希望这样,我想要的是,如果它们已经存在,那么每个记录都会被引用。
例如,我在DB中将面粉保存了大约20次。我想让它保存一次,对于每个配方,当用户输入面粉时,它应该只引用数据库中的那个成分。我如何实现这一目标?
我已经有一个Entry模型(配方)和一个JoinIngredient连接模型。因此,只要条目保存已存在的成分,我希望它只引用EntryIngredient表中的那个(作为外键)而不是创建一个新成分。
class Ingredient < ActiveRecord::Base
has_many :entry_ingredients
has_many :entries, :through => :entry_ingredients
end
class EntryIngredient < ActiveRecord::Base
belongs_to :entry
belongs_to :ingredient
accepts_nested_attributes_for :ingredient, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
class Entry < ActiveRecord::Base
belongs_to :user
has_many :entry_ingredients
has_many :ingredients, :through => :entry_ingredients
has_many :steps
accepts_nested_attributes_for :entry_ingredients, :allow_destroy => true
accepts_nested_attributes_for :steps, :reject_if => lambda { |s| s[:description].blank? }, :allow_destroy => true
end
更新
动态查找器听起来像是我们想要的,特别是find_or_create
或first_or_create
,但我无法弄清楚如何在我的设置中使用它们。有人能把我推向正确的方向吗?这就是我尝试过但我意识到这只是在每次调用条目#new时创建一个新的成分...而不是我想要发生的事情
#entries_controller.rb
def new
@entry = Entry.new
@entry.entry_ingredients.build.build_ingredient
@entry.steps.build
@ingredient = Ingredient.where(params[:ingredient]).first_or_create()
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @entry }
end
end
#_entry_ingredient_fields.html.erb
<%= f.fields_for :ingredient do |builder| %>
<%= builder.label :name %>
<%= builder.text_field :name, :class => "ingredient_field" %>
<% end %>
答案 0 :(得分:1)
如果没有看到某些代码,很难确切知道你需要什么,但如果我理解正确,你只想在它不存在的情况下创建一种成分。
查看rails dynamic finders。如果您使用方法名称,如
@ingredient = Ingredient.find_or_create_by_name("flour")
如果之前没有名称为“flour”的条目,则会创建一个新对象,或者返回一个名为“flour”的现有成分。在这两种情况下,@ ingredient都将保留上述语句返回的所需条目。只有当它不存在时,Rails才会为你创建它。