2013-07-09 21 views
45

我有一個串行如何使用ActiveRecord :: Relation數組初始化ActiveModel :: Serializer類?

class FundingSerializer < ActiveModel::Serializer 
    attributes :id, 

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

與適當的關聯

FundingSerializer.new(Funding.first).to_json 

初始化產生

"{\"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}}" 

但是,

FundingSerializer.new(Funding.all).to_json 

得到此電子郵件RROR。

undefined method `read_attribute_for_serialization' for #<ActiveRecord::Relation::ActiveRecord_Relation_Funding:0x007f998910a250> 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/activerecord-4.0.0/lib/active_record/relation/delegation.rb:121:in `method_missing' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/activerecord-4.0.0/lib/active_record/relation/delegation.rb:68:in `method_missing' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/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/[email protected]/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:466:in `rescue in attributes' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:454:in `attributes' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:478:in `_serializable_hash' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:360:in `serializable_hash' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/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[email protected]/gems/activesupport-4.0.0/lib/active_support/json/encoding.rb:50:in `block in encode' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/activesupport-4.0.0/lib/active_support/json/encoding.rb:81:in `check_for_circular_references' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/activesupport-4.0.0/lib/active_support/json/encoding.rb:49:in `encode' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/activesupport-4.0.0/lib/active_support/json/encoding.rb:34:in `encode' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/activesupport-4.0.0/lib/active_support/core_ext/object/to_json.rb:16:in `to_json' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/active_model_serializers-0.8.1/lib/active_model/serializer.rb:333:in `to_json' 
    from (irb):1 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/railties-4.0.0/lib/rails/commands/console.rb:90:in `start' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/railties-4.0.0/lib/rails/commands/console.rb:9:in `start' 
    from /Users/nicholasshook/.rvm/gems/[email protected]/gems/railties-4.0.0/lib/rails/commands.rb:64:in `<top (required)>' 

我不想簡單地渲染JSON:Funding.all因爲我想各地通過這個JSON的其他對象在我的Rails應用程序,並與angularjs應用。謝謝,

+0

雖然,[SandOnTeeth的答案](http://stackoverflow.com/a/39318636/1836143)可能會奏效,這不是官方的API 。請參閱[文檔](https://github.com/rails-api/active_model_serializers/blob/master/docs/howto/outside_controller_use.md#using-activemodelserializers-outside-of-a-controller)。 –

回答

5

現在你可以做,以這種方式(使用AMS v0.10.2):

ActiveModel::Serializer.serializer_for(Funding.all).to_json 

EDIT(2017年3月3日)
這種方法是行不通的了。使用aNoble's答案:

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

謝謝,更新了答案是這個! – shicholas

+2

從版本'0.10.2' [aNoble](http://stackoverflow.com/a/39606516/1836143)提供了正確的答案。此外,檢查出[文件](https://github.com/rails-api/active_model_serializers/blob/master/docs/howto/outside_controller_use.md#using-activemodelserializers-outside-of-a-controller)的話題。 –

+0

我使用AMS 0.10.2,ActiveModel :: Serializer.serializer_for(Leaderboard.all).to_json,如果即使有幾十個Leaderboard記錄,也總是返回「{}」 –

26

我不知道這是否是一個地道的解決方案,但它應該工作:

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

沒有工作,我只是認爲會有解決方案沿着ActiveModel :: ArraySerializer.new ... – shicholas

+1

[ActiveModel :: ArraySerializer]的底層(https://github.com/rails-api/active_model_serializers /blob/master/lib/active_model/serializer/array_serializer.rb)基本上就是這個確切的實現。映射集合並返回一個序列化的實例。 –

+3

在「active_model_serializers」> = 0.10.0時無法正常工作。 –

170

我認爲這是你在找什麼:

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

見本Thoughtbot blog post爲例。

+4

我希望這可能會被投票100次。謝謝! –

+0

很高興幫助! – John

+0

真棒,正是我所需要的。這應該在github上的AMS維基上。 –

5

看起來他們正在對最新的ActiveModel :: Serializers gem版本進行調整。您不再可以在ArraySerializer(不是ActiveModel :: Serializer :: ArraySerializer)上調用to_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) } 

調用主題將爲您帶來你之後的json。

這裏有一對夫婦更多的資源,其潛入測試設置進一步閱讀: http://eclips3.net/2015/01/24/testing-active-model-serializer-with-rspec/ https://robots.thoughtbot.com/validating-json-schemas-with-an-rspec-matcher

3

測試爲active_model_serializers的響應與>= 0.10.0版本我做這個簡單的幫手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 

因此,你可以簡單地用測試

我希望這可能對某人有用。

+0

'ams_serializer'正在工作,但'ams_array_serializer'不工作。 http://stackoverflow.com/questions/36278413/serialize-an-array-of-models-using-active-model-serializers – vipin8169

6

您也可以明確提供集合序列化器。

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

這是正確的答案,至少對於版本<0.10。您可以只傳入each_serializer作爲選項。 – quainjn

+0

它適用於我當我刪除序列化程序:ActiveModel :: ArraySerializer –

2

0.10.2版本爲我工作:

ActiveModelSerializers::SerializableResource.new(Funding.all, each_serializer: FundingSerializer).to_json

+1

'ActiveModelSerializers :: SerializableResource'是當前的官方API,這個答案是正確的,從版本'0.10.2'開始。 –

0

假設你有一個序列化器類(美孚)不匹配您的資源名稱(酒吧),我用下面的方法輕鬆序列化對象:

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

讓富串行繼承BaseSerializer:

class FooSerializer < BaseSerializer 
    ... 
end 

使用器FooSerializer在控制器或外部:

bar = Bar.all 
FooSerializer.collection_serialize(bar).to_json