2013-04-08 34 views
1

我有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魔法,没有运气。

我也搞砸周围的多态关联,这里的一切都有一个 家长和它的任一类型的成分或配方类型,但不能得到 这与我想要的界面锻炼。

+0

而你没有提到配方可以成为另一个配方的成分,或者是成分的一个辅助成分。 – Mori 2013-04-08 21:55:52

+0

我想你可以说一个具有次要成分的成分仅仅是制作这种成分的“配方”,但这更多的是语义学的东西。食谱可以有子食谱对我来说没有必要。 – 2013-04-08 23:44:14

+1

根据经典的物料清单来思考 - 不要挂上术语。蛋黄酱本身可以由蛋黄,油,也许芥末,腌菜等制成。即使是像“蛋”这样的基本“成分”,也可能被看作是由“蛋黄”和“白色”构成的。你所说的'食谱'是一种“配料”和“装配说明”的关联,它本身可以是一个子配件,就像'飞机'由'螺钉,螺栓和垫圈'和a其他几件事 - 以一种特殊的方式。 – Magoo 2013-04-09 00:31:23

回答

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 

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