Ruby on rails 4 如何使用ActiveRecord::关系数组初始化ActiveModel::Serializer类?

Ruby on rails 4 如何使用ActiveRecord::关系数组初始化ActiveModel::Serializer类?,ruby-on-rails-4,active-model-serializers,Ruby On Rails 4,Active Model Serializers,我有一个序列化程序 class FundingSerializer < ActiveModel::Serializer attributes :id, has_one :user has_one :tournament embed :ids, include: true end 屈服 "{\"users\":[{\"id\":2,\"first_name\":\"Nick\"}],\"tournaments\":[{\"id\":1,\"end_date\":\"20

我有一个序列化程序

class FundingSerializer < ActiveModel::Serializer
  attributes :id, 

  has_one :user
  has_one :tournament
  embed :ids, include: true
end
屈服

"{\"users\":[{\"id\":2,\"first_name\":\"Nick\"}],\"tournaments\":[{\"id\":1,\"end_date\":\"2013-07-21T23:18:54.981Z\",\"start_date\":\"2013-07-14T23:18:54.980Z\"}],\"funding\":{\"id\":1}}"
但是,

获取此错误

undefined method `read_attribute_for_serialization' for #<ActiveRecord::Relation::ActiveRecord_Relation_Funding:0x007f998910a250>
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activerecord-4.0.0/lib/active_record/relation/delegation.rb:121:in `method_missing'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activerecord-4.0.0/lib/active_record/relation/delegation.rb:68:in `method_missing'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:99:in `block in attribute'
    from (eval):3:in `_fast_attributes'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:466:in `rescue in attributes'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:454:in `attributes'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:478:in `_serializable_hash'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:360:in `serializable_hash'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:344:in `as_json'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activesupport-4.0.0/lib/active_support/json/encoding.rb:50:in `block in encode'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activesupport-4.0.0/lib/active_support/json/encoding.rb:81:in `check_for_circular_references'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activesupport-4.0.0/lib/active_support/json/encoding.rb:49:in `encode'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activesupport-4.0.0/lib/active_support/json/encoding.rb:34:in `encode'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activesupport-4.0.0/lib/active_support/core_ext/object/to_json.rb:16:in `to_json'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:333:in `to_json'
    from (irb):1
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/railties-4.0.0/lib/rails/commands/console.rb:90:in `start'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/railties-4.0.0/lib/rails/commands/console.rb:9:in `start'
    from /Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/railties-4.0.0/lib/rails/commands.rb:64:in `<top (required)>'
的未定义方法'read\u attribute\u for\u serialization'#
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activerecord-4.0.0/lib/active\u-record/relation/delegation.rb:121:in'method\u-missing'
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activerecord-4.0.0/lib/active\u-record/relation/delegation.rb:68:in'method\u-missing'
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active\u model\u serializers-0.8.1/lib/active\u model/serializer.rb:99:in`block in attribute'
from(eval):3:在“快速属性”中
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:466:in“rescue in attributes”
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:454:in`attributes'
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:478:in`_serializable_hash'
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:360:in`serializable_hash'
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:344:in`as_json'
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activesupport-4.0.0/lib/active\u support/json/encoding.rb:50:in'block in encode'
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activesupport-4.0.0/lib/active\u-support/json/encoding.rb:81:“检查循环引用”
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activesupport-4.0.0/lib/active\u-support/json/encoding.rb:49:in'encode'
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activesupport-4.0.0/lib/active\u support/json/encoding.rb:34:in'encode'
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/activesupport-4.0.0/lib/active\u support/core\u ext/object/to\u json.rb:16:in`to\u json'
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:333:in`to_json'
来自(irb):1
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/railties-4.0.0/lib/rails/commands/console.rb:90:in'start'
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/railties-4.0.0/lib/rails/commands/console.rb:9:in'start'
来自/Users/nicholasshook/.rvm/gems/ruby-2.0.0-p247@pokerfund/gems/railties-4.0.0/lib/rails/commands.rb:64:in`'

我不想简单地呈现json:Funding.all,因为我希望通过angularjs应用程序将此json传递给rails应用程序中的其他对象。谢谢,

我不确定这是否是一个惯用的解决方案,但它应该可以工作:

Funding.all.map{|f| FundingSerializer.new(f)}.to_json

我想这就是你想要的:

ActiveModel::ArraySerializer.new(Funding.all, each_serializer: FundingSerializer).to_json

查看此示例。

看起来他们正在最新的ActiveModel::Serializers gem版本中再次调整此选项。您不再可以在ArraySerializer(不是ActiveModel::Serializer::ArraySerializer)上调用_json

这是我为了绕开它所做的

let(:resource)        { Funding.all }
let(:serializer)      { ActiveModel::Serializer::ArraySerializer.new(resource, each_serializer: FundingSerializer)
let(:serialization)   { ActiveModel::Serializer::Adapter.create(serializer) }
subject               { JSON.parse(serialization.to_json) }
调用subject将获得所需的json

下面是一些更多的资源,它们深入到测试设置中,以供进一步阅读:

测试版本为
=0.10.0
活动\u model\u序列化程序的响应我为RSpec做了以下简单的帮助:

module AMSHelper
  def ams_array_serializer(collection, options: {}, adapter: :json)
    serializer = ActiveModel::Serializer::ArraySerializer.new(collection)
    adapter_class = ActiveModel::Serializer::Adapter.adapter_class(adapter)
    adapter_class.new(serializer, options)
  end

  def ams_serializer(object, options: {}, adapter: :json)
    serializer = ActiveModel::Serializer.serializer_for(object).new(object)
    adapter_class = ActiveModel::Serializer::Adapter.adapter_class(adapter)

    adapter_class.new(serializer, options)
  end
end

RSpec.configure do |config|
  config.include AMSHelper, type: :request
end
因此,您可以简单地使用以下工具进行测试:

RSpec.describe "Posts", type: :request do
  describe "GET /" do
    it "returns http success" do
      get posts_path
      expect(response_body).to eq(ams_array_serializer(Post.all).to_json)
    end
  end
end

我希望这对其他人有用。

您也可以显式地提供集合序列化程序

render json: Funding.all, serializer: ActiveModel::ArraySerializer, each_serializer: FundingSerializer

现在您可以这样做(使用AMS v0.10.2):

编辑(2017年3月3日)
这种方法不再有效了。使用答案:

ActiveModelSerializers::SerializableResource.new(Funding.all).to_json

这在版本
0.10.2
中对我有效:


ActiveModelSerializers::SerializableSource.new(Funding.all,each_serializer:FundingSerializer)。若要_json

假设您有一个与资源名称(Bar)不匹配的序列化器类(Foo),我使用以下方法轻松序列化对象:

class BaseSerializer < ActiveModel::Serializer
  def self.collection_serialize(resources)
    ActiveModelSerializers::SerializableResource.new(resources, each_serializer: self)
  end
end

这确实有效,我只是认为会有一个类似ActiveModel::ArraySerializer.new的解决方案……基本上就是这个精确的实现。映射集合并返回一个序列化实例。在“活动\u模型\u序列化程序”>=0.10.0.1上无法正常工作,这正是我需要的。这应该在github上的AMS wiki上。这给了我
未初始化的常量ActiveModel::ArraySerializer
这不适用于“active\u model\u Serializer”gem>=0.10.0.:ActiveModel::ArraySerializer已移动到::ActiveModel::Serializer::ArraySerializer,类的结构已发生重大变化。@ZekeFast适用于在谷歌上搜索最新AMS master(截至2016年4月)并发现自己正在处理此问题的任何人,请记住,您需要改用ActiveModel::Serializer::CollectionSerializer,因为AMS团队很快就会弃用另一个类。ActiveModel::Serializer::CollectionSerializer.new(object.myrelation,each_Serializer:MySerializer)
ActiveModel::Serializer::CollectionSerializer.new(object.myrelation,Serializer:MySerializer)
对我有效(
忽略了每个_Serializer
选项)
ams\u序列化程序
正在工作,但
ams\u数组\u序列化程序
不工作。这是正确的答案,至少对于<0.10的版本是如此。您只需将每个_序列化程序作为一个选项传入即可。当我删除序列化程序时,它对我有效:ActiveModel::ArraySerializer
ActiveModelSerializer::SerializableResource
是当前的官方API,从版本开始,这个答案是正确的
ActiveModel::Serializer.serializer_for(Funding.all).to_json
ActiveModelSerializers::SerializableResource.new(Funding.all).to_json
class BaseSerializer < ActiveModel::Serializer
  def self.collection_serialize(resources)
    ActiveModelSerializers::SerializableResource.new(resources, each_serializer: self)
  end
end
class FooSerializer < BaseSerializer
  ...
end
bar = Bar.all
FooSerializer.collection_serialize(bar).to_json