Расширение при ответе @ ratbeard следующее работает с любым active_model_serializer версии 0.9.x и выше. Я включил минимальное количество классов active_support и active_model, необходимых для того, чтобы получить сериализуемый хеш-объект PORO для работы с сериализаторами activemodel вне рельсов. Для моих целей в качестве оптимизации я передаю предварительно вычисленный сериализованный массив объектов, который вычисляется в другом месте приложения. Вместо повторного вычисления вы можете перегрузить инициализатор в подкласс ActiveModel :: Serializer, чтобы передать его, если он доступен.
Библиотека/serializable_hash.rb
class SerializableHash < Hash
alias :read_attribute_for_serialization :[]
end
приложение/сериализаторов/электронная почта/foo_serializer.гь
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
Для полноты я также включить этот альтернативный вариант, который использует переменную экземпляр вместо сериализуемой хэш:
приложение/сериализаторы/электронных/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
Тогда чтобы использовать сериализацию объекта верхнего уровня, который вы просто сделали бы
require 'app/serializers/email/foo_serializer'
require 'app/serializers/email/bar_serializer'
Email::FooSerializer.new(Foo.first).as_json
ИЛИ если вы хотите использовать предварительно вычисленный сериализованный массив баров:
# 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
Вы должны принять свой собственный ответ, поскольку он кажется правильным. :) –
Эй, Робин, можете ли вы включить пример своего объекта для людей, которые хотят сделать что-то подобное с нуля? (это неактивный объект записи, включающий поддержку сериализатора) – Will
удалось ли сериализовать массив вложенных сериализованных объектов внутри модели? – Chris