serializers rails new custom as_json active ruby-on-rails-4 active-model-serializers

ruby on rails 4 - rails - ¿Cómo se inicializa una clase ActiveModel:: Serializer con una matriz ActiveRecord:: Relation?



rails serializer nested (8)

Ahora puede hacer eso de esta manera (usando AMS v0.10.2):

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

EDITAR (03.03.2017)
Este método ya no funciona. Use aNoble''s respuesta aNoble''s :

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

Tengo un serializador

class FundingSerializer < ActiveModel::Serializer attributes :id, has_one :user has_one :tournament embed :ids, include: true end

Eso se inicializa con las asociaciones apropiadas

FundingSerializer.new(Funding.first).to_json

rendimientos

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

pero,

FundingSerializer.new(Funding.all).to_json

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

No quiero simplemente renderizar json: Funding.all porque me gustaría pasar este json a otros objetos en mi aplicación de rieles y con una aplicación angularjs. Gracias,


Creo que esto es lo que estás buscando:

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

Vea este blog de Thoughtbot para un ejemplo.


Esto funcionó para mí en la versión 0.10.2 :

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


No estoy seguro de si esta es una solución idiomática, pero debería funcionar:

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


Parece que están ajustando esto de nuevo en la versión más reciente de ActiveModel :: Serializers gem. Ya no puede llamar a_json en el ArraySerializer (que no es ActiveModel :: Serializer :: ArraySerializer).

Esto es lo que hice para evitarlo.

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

Llamar a un sujeto le dará el json que está buscando.

Aquí hay un par de recursos más que se sumergen en la configuración de prueba para seguir leyendo: http://eclips3.net/2015/01/24/testing-active-model-serializer-with-rspec/ https://robots.thoughtbot.com/validating-json-schemas-with-an-rspec-matcher


Probando la respuesta para active_model_serializers con la versión >= 0.10.0 He hecho este sencillo ayudante para 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

Entonces puedes simplemente probar con:

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

Espero que esto pueda ser útil para alguien.


Supongamos que tiene una clase de serializador (Foo) que no coincide con el nombre de su recurso (Barra). Utilizo el siguiente enfoque para serializar objetos fácilmente:

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

deje que el serializador Foo herede BaseSerializer:

class FooSerializer < BaseSerializer ... end

use FooSerializer en el controlador o fuera de este:

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


También puede proporcionar explícitamente el serializador de colecciones.

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