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