Hi,
is there a way to specify something like this:
render json: {projects: @projects, each_serializer: ProjectSerializer, clients: clients, each_serializer: ProjectSerializer}, status: :ok
This is not currently possible. Two workarounds:
ProjectsAndClients), and serialize that (being careful of the few gotchas of serializing POROs)projects and clients, and serialize that (the array serializer will select the right serializer for each object), and split it into two arrays on the client sideEdit: for 1. you could actually just define a serializer, and specify it manually in your render call.
Thanks, for the second option, if i have multiple serializers for projects and clients, how can i specify the right one?
Not sure this is possible under the current circumstances. @joaomdmoura @bf4?
If I were you, I would go with 1. and do something along the lines of:
class ProjectsAndClientsSerializer < ActiveModel::Serializer
has_many :projects, serializer: MyFancyProjectSerializer
has_many :clients, serializer: MyFancyClientSerializer
end
or build a custom CollectionSerializer, if you want to stick with 2.
If you decide to stick with 2. you could modify ArraySerializer to make it suit your needs (that is requiring a specific adapter for each record depending on whether it is a client or a project).
if i go with the first option, do i need to create an ActiveRecord?
if i use render json: {projects: @projects, clients: clients}, serializer: ClientsAndProjectsSerializer i get error "undefined method projects for Hash<..."
No, you do not need ActiveRecord for 1., although there are currently a few gotchas for serializing PORO models (search in the issues, you should define some methods like read_attribute_for_serialization(attr).
You should encapsulate it in a Model like:
class ProjectsAndClients < ActiveModel::Model
attr_accessor :projects, :clients
def initialize(projects, clients)
@projects = projects
@clients = clients
end
end
then do
render json: ProjectsAndClients.new(projects, clients), serializer: ClientsAndProjectsSerializer
Edit: in that case you probably don't need the read_attribute_for_serialization method, and it should pretty much work out of the box.
oh, great! Thanks a lot man!
I'm not at a computer now so I can't be as precise as I'd like.
It sounds like either you'd like to treat a specific collection as a single resource
Or you'd like to customize an adapter for a specific collection
If the former, this should be in the docs, and it's certainly in the lint but
class PostOffice
include ActiveModel::Model
include ActiveModel::Serialization
attr_accessor :post, :office
end
class PostOfficeSerializer < AM::S
has_one :post, serializer: PostSerializer
has_one :office, serializer: OfficeSerializer
end
render json: PostOffice.new(post: post, office: office
(No need I don't think to specify each_serializer: PostOfficeSerializer
The idiomatic way to use a custom collection serializer would be (in 0.10)
render json: [post, office], serializer: PostOfficeSerializer
Where
class PostOfficeSerializer < AM::ArraySerializer
def serializable_hash(options = nil)
result = super
# something, maybe even don't call super
end
end
Or maybe an adapter
class SpecialAdapter < AM::S::Adapter::Json
# something
end
AM::S.config.adapter = SpecialAdapter
If you want it as the default
Otherwise you'd need to namespace it like the other adapters (for now) and pass in adapter: special
Hope that helps
Me on mah phone and achy fingers
Whatever works plz help us improve the docs if you can and submit a PR!
You could try something like this.
render json: {
projects: ActiveModelSerializers::SerializableResource.new(projects, each_serializer: ProjectSerializer),
clients: ActiveModelSerializers::SerializableResource.new(clients, each_serializer: ClientSerializer),
}, status: :ok
Used this, then the scope is present in the serializer like current_user:
foo = OpenStruct.new(projects: projects, clients: clients)
render json: foo, adapter: :attributes, serializer: ProjectsClientsSerializer
...
class ProjectsClientsSerializer < ActiveModel::Serializer
type ''
has_many :projects
has_many :clients
def read_attribute_for_serialization(attr)
object[attr.to_s]
end
end
Most helpful comment
You could try something like this.