6

Estoy teniendo un momento extremadamente difícil para averiguar cómo serializar los atributos anidados de un modelo en rieles. Tengo un RecipeTemplate que almacenará una Receta ya existente en su atributo template_data. La receta tiene atributos anidados a dos niveles de profundidad.¿Cómo serializar el modelo anidado en rieles?

Esto es en los carriles 3.1.0.rc4

class RecipeTemplate < ActiveRecord::Base 
    serialize :template_data, Recipe 
... 
end 

class Recipe < ActiveRecord::Base 
    has_many :ingredients 
    accepts_nested_attributes_for :ingredients 
... 
end 

ingredientes en la receta de atributos también ha anidada (SubIngredients).

Si fijo el template_data con un objeto de esta manera:

Recipe.includes(:ingredients => [:sub_ingredients]).find(1) 

Voy a buscar un TypeError "no se puede volcar Clase clase anónima" que tiene sentido, ya que no sabe cómo serializar los ingredientes o SubIngredientes.

Cómo se puede serializar los atributos anidados en un modelo para que pueda utilizar:

serialize :template_data, Recipe 

O tengo para serializar los datos de alguna otra manera y llevar a cabo el tipo de seguridad comprueba a mí mismo?

Gracias de antemano por cualquier ayuda

+0

¿Puede almacenar datos en el campo serializado? Por ejemplo, ¿puede pasarle una variedad de ingredientes y guardarlos? – thoughtpunch

+0

¿Por qué intenta serializar estos modelos que ya están asociados a través de las relaciones? Parece que está intentando guardar datos relacionados en una sola columna en una tabla cuando todos esos datos ya están guardados en su propia tabla en la base de datos, que es la forma en que debería hacerse en primer lugar. –

Respuesta

-2

¿Por qué no acaba de mantener un campo en el modelo RecipeTemplate con la etiqueta recipe_id

y vincular a la receta que en lugar de intentar serializar una receta ¿objeto?

1

Veo por qué querría que la plantilla se almacenara dentro de una columna serializada, pero necesita un poco más de manipulación de los datos almacenados que lo que permite ese tipo de columna. Esto es lo que haría:

app/modelos/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/modelos/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/modelos/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 

Luego, para crear y usar una plantilla:

# 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 

La diferencia es que está utilizando la columna serializada para almacenar un hash para usar en el contructor de recetas. Si solo desea serializar el objeto, los otros pósters son correctos, solo asocie un objeto.

Cuestiones relacionadas