6

Mam niezmiernie trudny czas na zastanowienie się nad serializacją zagnieżdżonych atrybutów modelu w szynach. Mam RecipeTemplate, który będzie przechowywać już istniejący przepis w jego atrybutu template_data. Przepis ma zagnieżdżone atrybuty na dwóch poziomach.Jak serializować model zagnieżdżony w Railsach?

to na szynach 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 

składników w recepturze ma również zagnieżdżone właściwości (SubIngredients).

Jeżeli ustawić template_data z obiektem tak:

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

Wezmę TypeError „nie można zrzucić anonimowy class”, która ma sens, ponieważ nie wiedzą, jak serializacji Składniki lub SubIngredients.

Jak można szeregować zagnieżdżonych atrybuty w modelu, dzięki czemu można używać:

serialize :template_data, Recipe 

Albo muszę szeregować dane w jakiś inny sposób i wykonywać bezpieczeństwa typu sprawdza się?

Dzięki z góry za wszelką pomoc

+0

Czy jesteś w stanie przechowywać jakiekolwiek dane w zserializowanym polu? Na przykład, czy jesteś w stanie przekazać mu zestaw składników i zdobyć go, aby zaoszczędzić? – thoughtpunch

+0

Dlaczego próbujesz serializować te modele, które są już powiązane przez relacje? Wygląda na to, że próbujesz zapisać powiązane dane w pojedynczej kolumnie w jednej tabeli, gdy wszystkie te dane są już zapisane we własnej tabeli w bazie danych, co należy zrobić w pierwszej kolejności. –

Odpowiedz

-2

Dlaczego nie można po prostu zachować pole w modelu RecipeTemplate z etykietą recipe_id

i odwołują się do przepisu, że zamiast próbować do serializacji przepis obiekt?

1

Widzę, dlaczego chciałbyś, aby sam szablon był przechowywany w kolumnie zserializowanej, ale potrzebujesz trochę więcej manipulacji przechowywanymi danymi, niż jest to dozwolone przez ten typ kolumny. Oto, co chciałbym zrobić:

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

Następnie, aby utworzyć i użyć szablonu:

# 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 

Różnica polega na tym, że używasz zserializowanej kolumny do przechowywania skrótu do użycia w konstruktorze Receptury. Jeśli chcesz tylko serializować obiekt, pozostałe plakaty są poprawne - po prostu powiąż obiekt.

Powiązane problemy