Я понимаю, почему вы хотите, чтобы сам шаблон хранился внутри сериализованного столбца, но вам нужно немного больше манипулировать сохраняемыми данными, чем это разрешено столбцом этого типа.Вот что я бы сделал:
app / models / recipe_template.rb
class RecipeTemplate < ActiveRecord::Base
serialize :template_data
attr_accessible :name, :recipe
def recipe=(r)
self.template_data = r.serializable_hash_for_template
end
def recipe
Recipe.new(template_data)
end
end
app / models / recipe.rb
class Recipe < ActiveRecord::Base
has_many :ingredients, as: :parent
accepts_nested_attributes_for :ingredients
attr_accessible :name, :ingredients_attributes
def serializable_hash_for_template(options={})
options[:except] ||= [:id, :created_at, :updated_at]
serializable_hash(options).tap do |h|
h[:ingredients_attributes] = ingredients.map(&:serializable_hash_for_template)
end
end
end
app / models / ингридиент.rb
class Ingredient < ActiveRecord::Base
belongs_to :parent, polymorphic: true
has_many :sub_ingredients, class_name: 'Ingredient', as: :parent
accepts_nested_attributes_for :sub_ingredients
attr_accessible :name, :sub_ingredients_attributes
def serializable_hash_for_template(options={})
options[:except] ||= [:id, :parent_id, :parent_type, :created_at, :updated_at]
serializable_hash(options).tap do |h|
h[:sub_ingredients_attributes] = sub_ingredients.map(&:serializable_hash_for_template)
end
end
end
Затем для создания и использования шаблона:
# create a recipe to use as a template
taco_meat = Ingredient.create(name: "Taco Meat")
taco_seasoning = taco_meat.sub_ingredients.create(name: "Taco Seasoning")
sams_tacos = Recipe.create(name: "Sam's Tacos")
sams_tacos.ingredients << taco_meat
# create a template from the recipe
taco_recipe = RecipeTemplate.create(name: "Taco Recipe", recipe: sams_tacos)
# build a new recipe from the template
another_taco_recipe = taco_recipe.recipe
Разница в том, что вы используете сериализованный столбец для хранения хэша для использования в конструкторе рецепта.Если вы просто хотели сериализовать объект, другие плакаты верны - просто свяжите объект.