У меня есть ситуация, когда я хочу создавать «параметрические» модели в рельсах; например, я хотел бы определить PrototypeRecipe
, а затем иметь возможность сделать несколько DerivedRecipe
; может быть, один производный рецепт использует больше сахара, а другой использует меньше яиц или что-то еще. Критическим моментом является то, что я хочу, чтобы все «производные» экземпляры наследовали свойства от одного общего PrototypeRecipe
, но могли выполнять локальные изменения.
В идеале, я хотел бы иметь возможность определять методы в прототипе (скажем, собирать список покупок), и эти методы реагируют на локальные изменения в производных экземплярах (поэтому, если я указал 3 яйца вместо 2, я мог бы вызвать функцию make_shopping_list
прототипа, и это отражало бы это.
Существует ли существующий метод для достижения чего-то подобного? Вот лучшее, что я могу придумать:
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
Я знаю, что этот код можно сделать намного чище, мне больше интересно, можно ли улучшить общий подход. Основная идея заключается в том, что каждый ингредиент будет иметь уникальный идентификатор. Чтобы изменить рецепт прототипа, вы просто создаете экземпляр DerivedRecipe
, связываете его с прототипом, а затем добавляете ингредиент с тем же UUID, что и у одного из ингредиентов прототипа.