成分有许多亚成分造型

时间:2013-04-08 21:52:44

标签: ruby-on-rails database-design

我有一个Recipe模型和一个Ingredient模型。现在一个食谱 has_and_belongs_to_many :ingredients和成分has_and_belongs_to_many :recipes

因为可以想象一种成分可以由其他成分组成,我是 尝试在该模型上进行自联接,如下所示:

has_many :components, class_name: 'Ingredient', foreign_key: 'parent_id'
belongs_to :parent,   class_name: 'Ingredient'

现在,这有效,但每种成分只能有一个父母,例如蛋黄酱 是在“蟹饼”成分,它是食谱的一部分,但它不能 成为其他食谱中“辣味梅奥”成分的成分 同时进行。

我想要得到的是这样的界面:

r = Recipe.create(name: "Jumbo Lump Crab Cakes")
r.ingredients << Ingredient.create(name: "Crab Cakes")
r.ingredients[0].ingredients # => []
r.ingredients[0].ingredients.create(name: "Mayonnaise")
r.ingredients[0].ingredients # => [#<Ingredient id: 2, name: "Mayonnaise">]
r.ingredients[0].ingredients[0].ingredients.create(name: "Eggs")
r.ingredients[0].ingredients[0].ingredients # => [#<Ingredient id: 3, name: "Eggs">]

Ingredient.last               # => #<Ingredient id: 3, name: "Eggs">
Ingredient.last.parent        # => #<Ingredient id: 2, name: "Mayonnaise">
Ingredient.last.parent.parent # => #<Ingredient id: 1, name: "Crab Cakes">

# Bonus points if a child ingredient can "walk up" its heritage tree to the recipe:
Ingredient.last.recipe        # => #<Recipe id: 1>

显然,我需要一个关联表来存储成分/子成分 关系,但这就是我已经想到的。我试过各种各样的 sourcethrough巫术的壮举,没有运气。

我还搞乱了多态关联,其中一切都有 父母和它的类型成分或食谱类型,但无法得到 用我想要的界面来解决这个问题。

1 个答案:

答案 0 :(得分:0)

想想我弄清楚了。使用this post的修改版本结束。

create_table :ingredients do |t| # :hunts
  t.references :parent # :predator
  t.references :child  # :prey
end

add_index :ingredients, :parent_id # :hunts, :predator_id
add_index :ingredients, :child_id  # :hunts, :prey_id

create_table :components do |t| # :animals
  t.string :name
end

class Component < ActiveRecord::Base # Animal
  has_many :parentage, foreign_key: 'parent_id',
                       class_name: 'Ingredient',
                       dependent: :destroy

  has_many :children, through: :parentage

  has_many :progeny, foreign_key: 'child_id',
                     class_name: 'Ingredient',
                     dependent: :destroy

  has_many :parents, through: :progeny
end

class Ingredient < ActiveRecord::Base # Hunt
  belongs_to :parent, class_name: 'Component'
  belongs_to :child,  class_name: 'Component'
end

对亲子/后代命名非常满意。