I see why you want the template itself to be stored inside a serialized column, but you need to manipulate the stored data a bit more than what this type of column allows. Here is what I will do:
application / 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
application / 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
application / models / ingredient.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
Then to create and use the template:
# 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 Tacos") sams_tacos.ingredients << taco_meat
The difference is that you use a serialized column to store the hash for use in the Recipe Competition. If you just wanted to serialize the object, the other posters are correct - just link the object.