我有一个模型对象,它不是ActiveRecord :: Base的后代,也不存储在数据库中。我为它创建了一个序列化程序(同名+“Serializer”),在我的控制器中我正在调用render json: object_instance
。
结果是来自render
内部的例外。
我实现了一个as_json
方法来实例化序列化程序并调用它,但结果是对象read_attribute_for_serialization
中缺少的方法。
我希望我的对象在Active Model Serializer中至少与ActiveModel兼容的对象起作用,但我在他们的文档中没有看到任何对此的引用。
答案 0 :(得分:54)
模型对象需要包含它:
# active_model_serializers 0.10+
class ModelName
include ActiveModel::Serialization
end
# active_model_serializers < 0.10
class ModelName
include ActiveModel::SerializerSupport
end
这实现了对象中所需的方法,并且还自动发现与对象名称匹配的序列化程序,因此它可以像ActiveRecord对象一样透明地使用。
这适用于active_model_serializers版本0.8.1至至少0.9.3。
答案 1 :(得分:12)
继mutexkid回答后,使用active_model_serializers 0.10.0.rc4,需要以下内容才能使普通的旧ruby对象与序列化程序一起运行:
PORO:
class SearchResult
include ActiveModel::Serialization
attr_reader :stories, :users, :friends
def initialize(search:)
@stories = search.stories
@users = search.users
@friends = search.friends
end
end
串行:
class SearchResultSerializer < ActiveModel::Serializer
attributes :stories, :users, :friends
end
答案 2 :(得分:7)
我在升级到Rails 4.2时遇到了这个问题。已移除ActiveModel::SerializerSupport
以获得0.10稳定值。我最后只是为我的PORO添加了一个别名,似乎可以解决这个问题:
alias :read_attribute_for_serialization :send
(active_model_serializers 0.10.0.rc2)
您还需要在班级中添加包含ActiveModel::Model
。
答案 3 :(得分:5)
我的帐户太新了,无法对Karl Wilbur的回答发表评论,但继承了我添加的代码,因此我可以传入一个哈希对象来序列化:
class SerializableHash < Hash
alias :read_attribute_for_serialization :[]
end
用法:
o = SerializableHash.new(user: current_user, account: current_account)
respond_with(o, serializer: SettingsSerializer)
答案 4 :(得分:5)
从active_model_serializers 0.10.x和Rails 4.2开始,这里是使用带有活动模型序列化器的普通旧ruby对象所需的内容:
普通老红宝石对象:
class SearchResult
extend ActiveModel::Naming
include ActiveModel::Serialization
attr_accessor :stories, :users, :friends
def id
hash
end
def initialize(search:)
@stories = search.stories
@users = search.users
@friends = search.friends
end
def attributes
{ stories: stories,
users: users,
friends: friends
}
end
end
Serializer:
class SearchResultSerializer < ActiveModel::Serializer
attributes :stories, :users, :friends
end
答案 5 :(得分:0)
扩展@ ratbeard&#39;回答以下适用于任何active_model_serializer版本0.9.x及更高版本。我包含了使PORO可序列化哈希对象与rails之外的activemodel序列化程序一起使用所需的最小数量的active_support和active_model类。为了我的目的,我作为一个优化传递一个预先计算的序列化对象数组,该数组在应用程序的其他地方计算。而不是重新计算,您可以重载ActiveModel :: Serializer子类中的初始化程序,以便在它可用时将其传递。
<强> LIB / serializable_hash.rb 强>
class SerializableHash < Hash
alias :read_attribute_for_serialization :[]
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)
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