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

我还搞砸了一个多态关联,其中所有东西都有一个父对象,它要么是成分类型,要么是配方类型,但无法通过我想要的界面来解决。

4

1 回答 1

0

想我明白了。最终使用了这篇文章的修改版本。

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

对父母/后代命名相当满意。

于 2013-04-09T04:06:01.917 回答