How do you initialize an ActiveModel::Serializer class with an ActiveRecord::Relation array?

shicholas picture shicholas · Jul 9, 2013 · Viewed 31.3k times · Source

I have a serializer

class FundingSerializer < ActiveModel::Serializer
  attributes :id, 

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

That initializes with the proper associations

FundingSerializer.new(Funding.first).to_json

yields

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

but,

FundingSerializer.new(Funding.all).to_json

gets this error.

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)>'

I do not want to simply render json: Funding.all because I would like to pass this json around to other objects in my rails application and with an angularjs app. Thanks,

Answer

John picture John · Jul 29, 2013

I think this is what you're looking for:

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

See this Thoughtbot blog post for an example.