如何存储一次记录并在其他表中多次引用它?

时间:2013-03-28 01:18:57

标签: ruby-on-rails database-design activerecord normalization

我有一张食材表。当用户输入一种成分时,它会保存在表格中。现在我注意到的是,许多记录重复,我不希望这样,我想要的是,如果它们已经存在,那么每个记录都会被引用。

例如,我在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_createfirst_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 %>

1 个答案:

答案 0 :(得分:1)

如果没有看到某些代码,很难确切知道你需要什么,但如果我理解正确,你只想在它不存在的情况下创建一种成分。

查看rails dynamic finders。如果您使用方法名称,如

@ingredient = Ingredient.find_or_create_by_name("flour")

如果之前没有名称为“flour”的条目,则会创建一个新对象,或者返回一个名为“flour”的现有成分。在这两种情况下,@ ingredient都将保留上述语句返回的所需条目。只有当它不存在时,Rails才会为你创建它。