Rail model templates (or instance inheritance)?

I have a situation where I want to make "parametric" models in rails; for example, I would like to define PrototypeRecipe, and then be able to do several DerivedRecipe; perhaps one recipe you use uses more sugar and another uses less eggs or something else. The critical point is that I want all "derived" instances to inherit properties from one common PrototypeRecipe, but to be able to do local modifications.

Ideally, I would like to be able to define methods on a prototype (for example, making a shopping list), and these methods respond to local changes in derived instances (so if I gave 3 eggs instead of 2, I could name the prototype of the function make_shopping_list, and this will reflect this).

Is there an existing method for doing something like this? Here's the best I can think of so far:

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

I know that this code can be made much cleaner, I'm more interested in whether the general approach can be improved. The basic idea is that the ingredients will have a unique identifier. To change the prototype recipe, you simply create an instance DerivedRecipe, associate it with the prototype, and then add the ingredient with the same UUID as one of the prototype components.

+3
1

100% , , .

(STI). PrototypeRecipe, DerivedRecipe.

prototype_recipes type (). Rails, STI. 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

, ?

0

Source: https://habr.com/ru/post/1776106/


All Articles