Ausbau Nach @ Ratbeards Antwort funktioniert das Folgende mit jeder active_model_serializer Version 0.9.x und höher. Ich habe die minimale Menge an active_support und active_model-Klassen hinzugefügt, die benötigt werden, um das serialisierbare PORO-Hash-Objekt mit activemodel-Serializern außerhalb von Rails arbeiten zu lassen. Für meine Zwecke als Optimierung übergebe ich ein vorberechnetes serialisiertes Array von Objekten, das an anderer Stelle in der App berechnet wird. Anstatt die Daten neu zu berechnen, können Sie den Initialisierer in der ActiveModel :: Serializer-Unterklasse überladen, um ihn weiterzugeben, wenn er verfügbar ist.
lib/serializable_hash.rb
class SerializableHash < Hash
alias :read_attribute_for_serialization :[]
end
app/Serializer/E-Mail/foo_serializer.rb
require 'active_model/serializer'
require 'active_support/core_ext/object'
require 'active_support/inflector'
require 'active_support/notifications'
class Email::FooSerializer < ActiveModel::Serializer
attributes :id, :bars, :created_at, :updated_at
def initialize(foo, precomputed_serialized_array_of_bars =nil)
unless serialized_bars
serialized_bars = {}
foo.bar.each do | bar |
serialized_searches[bar.baz] ||= []
serialized_searches[bar.baz] << Email::BarSerializer.new(bar).attributes
end
end
super(SerializableHash[
id: foo.id,
bars: serialized_bars,
created_at: foo.created_at
updated_at: foo.updated_at
])
end
end
Der Vollständigkeit halber füge ich auch diese alternative Version, die eine Instanz Variable statt serializable Hash verwendet:
app/Serializer/E-Mail/foo_serializer.rb
require 'active_model/serializer'
require 'active_support/core_ext/object'
require 'active_support/inflector'
require 'active_support/notifications'
class Email::FooSerializer < ActiveModel::Serializer
attributes :id, :bars, :created_at, :updated_at
def initialize(foo, precomputed_serialized_array_of_bars=nil)
@bars = precomputed_serialized_array_of_bars
super(foo)
end
def bars
if @bars
return @bars
else
serialized_bars = {}
object.bars.each do | bar |
serialized_bars[bar.baz] ||= []
serialized_bars[bar.baz] << Email::BarSerializer.new(bar).attributes
end
return serialized_bars
end
end
end
Dann Um das Objekt der obersten Ebene zu serialisieren, würden Sie einfach
require 'app/serializers/email/foo_serializer'
require 'app/serializers/email/bar_serializer'
Email::FooSerializer.new(Foo.first).as_json
oder wenn Sie die vorher berechnete serialisierten Reihe von Bars verwenden wollen:
# pre-compute array_of_serialized_bars somewhere up here
require 'app/serializers/email/foo_serializer'
require 'app/serializers/email/bar_serializer'
Email::FooSerializer.new(Foo.first, array_of_pre_serialized_bars).as_json
Sie sollten Ihre eigene Antwort akzeptieren, da sie korrekt zu sein scheint. :) –
Hey Robin können Sie ein Beispiel für Ihr Objekt für Menschen, die etwas ähnliches von Grund auf neu machen wollen? (Das ist ein nicht aktives Record-Objekt, das die Serializer-Unterstützung enthält) – Will
Haben Sie es geschafft, ein Array verschachtelter serialisierter Objekte innerhalb des Modells zu serialisieren? – Chris