2010-11-21 78 views
3

我有一种情况,我想在轨道中制作'参数化'模型;例如我想定义PrototypeRecipe,然后能够制作多个DerivedRecipe;也许一个派生食谱使用更多的糖,另一个使用较少的鸡蛋或什么。关键的一点是,我希望所有“衍生”实例都从一个共享的PrototypeRecipe继承属性,但能够进行本地修改。理想情况下,我希望能够在原型上定义方法(比如放置一个购物清单),并让这些方法响应派生实例中的局部更改(所以如果我指定了3个鸡蛋而不是2个鸡蛋) ,我可以调用原型的make_shopping_list函数,它会反映这一点)。rails模板(或实例继承)选项?

是否有现成的方法来完成这样的事情?这是我能想出迄今最好的:

class Ingredient << ActiveRecord::Base 
    belongs_to :recipe, :polymorphic => true 

    # uuid => UUID String (for grouping ingredients which change between prototype and derived instances) 
end 

class PrototypeRecipe << ActiveRecord::Base 
    has_many :ingredients 

    def make_ingredient_list(derived_recipe = nil) 
     self.ingredients.map {|i| derived_recipe.nil? ? i : derived_recipe.ingredients.where(:ingredient_uuid => i.uuid).first } 
    end 
end 

class DerivedRecipe << ActiveRecord::Base 
    belongs_to :prototype_recipe 

    has_many :ingredients 

    def method_missing(sym, *args) 
     self.prototype_recipe.send(sym, *args, self) 
    end 
end 

我知道这个代码可以做了很多更清洁,我更想知道,一般的方法可以改善上。基本的想法是,配料每个都有唯一的ID。要修改原型配方,只需创建一个DerivedRecipe实例,将其链接到原型,然后添加一个与原型配料相同的UUID成分。

+0

你的意思是'<'...不是'<<' – Tilo 2011-04-29 21:11:09

回答

0

我不是100%的你想要什么样的行为,所以这里是我的尝试解决方案。

单表继承(STI)。您的基础班级将为PrototypeRecipe,您的孩子班级将为DerivedRecipe

在您的prototype_recipes表中指定type列(文本)。这表示您想要使用STI的Rails。如果您将make_ingredients_list方法放入基类中,则可以从您的子类中访问它。

# app/models/ingredient.rb 
class Ingredient < ActiveRecord::Base 
    belongs_to :recipe, :class_name => "PrototypeRecipe" 
    ... 
end 

# app/models/prototype_recipe.rb 
class PrototypeRecipe < ActiveRecord::Base 
    has_many :ingredients 
    has_many :derived_recipes 

    def make_ingredient_list 
    ... 
    end 
end 

# app/models/derived_recipe.rb 
class DerivedRecipe < PrototypeRecipe 
    belongs_to :prototype_recipe 
end 

现在你可以这样做:

@cupcakes = PrototypeRecipe.create 
@cupcakes_with_extra_eggs = @cupcakes.derived_recipes.create 
print @cupcakes_with_extra_eggs.make_ingredient_list 

难道这就是你要找的人?