Active Model Serializer use no serializer - ruby-on-rails

At times I'd like to use no serializer for a model, and other times I do. I have tried to request nil serializer, but it seems that a serializer is used regardless.
class API::FinancialDashboardSerializer < ActiveModel::Serializer
attributes :id, :name, :weeks_remaining
has_many :check_ins, serializer: nil
end
In this instance I'd like to return the association without any serializer, but it still uses the CheckInSerializer anyway.
Is there a way around this?

I think you could just do:
class API::FinancialDashboardSerializer < ActiveModel::Serializer
attributes :check_ins, :id, :name, :weeks_remaining
end
Or if that doesn't work:
class API::FinancialDashboardSerializer < ActiveModel::Serializer
attributes :check_ins, :id, :name, :weeks_remaining
def check_ins
object.check_ins.map(&:as_json)
end
end

Related

How to pass parameters Active Model Serializer to another Serializer?

having a problem with sending parameters.
I have user_serializer and book_serializer and I want to send user_id to book_serializer inside user_serializer. Like this:
class UserSerializer < ActiveModel::Serializer
attributes :id
has_many :books, serializer: BookSerializer, your_option_name: object.id
end
and then BookSerializer
class BookSerializer < ActiveModel::Serializer
attributes :id, :test
def test
#instance_options[:your_option_name]
end
end
but it's not working, getting null.
are there any ideas? great thanks.
The arguments that you passed into has_many ... is actually used to create a HasManyReflection object which only accepts some very specific values and it also does not pass its argument any further.
The correct way to pass custom argument to nested serializers is through the build_association method or directly like below:
class UserSerializer < ActiveModel::Serializer
attributes :id, books
def books
ActiveModel::SerializableResource.new(object.books, each_serializer: BookSerializer, your_option_name: object.id)
end
end

Apply filter to ActiveModel Serializer attributes to change the key

I have a serializer for my rest API. Currently, it looks like:
class TestSerializer < ActiveModel::Serializer
attributes :id, :name, :field_one__c, :field_two__c
end
I'm wondering if there are any ways to filter all the fields to have the __c removed when serializing, if there is a way to apply logic to ALL fields.
The case is I have a lot of fields with __c on the end, and I'd like to remove them all with a minimal amount of code on the serializer level.
Yes you can customize an attribute name in the serializer using the :key option:
attribute :field_one__c, key: :field_one
attribute :field_two__c, key: :field_two
You can also make any attribute conditional using :if or :unless options.
Doc: https://github.com/rails-api/active_model_serializers/blob/v0.10.6/docs/general/serializers.md#attribute
Update:
For your special case, you can hack this by defining the attributes class method before the attributes list:
class TestSerializer < ActiveModel::Serializer
class << self
def attributes(*attrs)
attrs.each do |attr|
options = {}
options[:key] = attr.to_s[0..-4].to_sym if attr.to_s.end_with?('__c')
attribute(attr, options)
end
end
end
attributes :id, :name, :field_one__c, :field_two__c
end
If you have multiple serializer classes with the same requirement of filtering lots of attributes, you can apply the DRY principle in your solution by creating another serializer class which will inherit from ActiveModel::Serializer. Put the above class method definition inside this new serializer and inherit all the serializers from this new one which have list of attributes with __c.
class KeyFilterSerializer < ActiveModel::Serializer
class << self
def attributes(*attrs)
attrs.each do |attr|
options = {}
options[:key] = attr.to_s[0..-4].to_sym if attr.to_s.end_with?('__c')
attribute(attr, options)
end
end
end
end
class TestSerializer < KeyFilterSerializer
attributes :id, :name, :field_one__c, :field_two__c
end
class AnotherTestSerializer < KeyFilterSerializer
attributes :id, :name, :field_one__c, :field_two__c
end

Rails 4 + serialization: Nested models not showing

I am using the Active Model Serialization Gem to pull info for my API and my nested models are not working properly.
I have the following:
class API::ClientSerializer < ActiveModel::Serializer
attributes :name, :address
has_many :check_ins
end
class API::CheckInSerializer < ActiveModel::Serializer
attributes :id, :employee, :created_at, :type_of_weighin, :user_id
has_one :weigh_in
end
and while the check_ins show when I pull a client. The weigh_in is never included in the check_in. Is there something else I need to do?

how to optionally include / delete values in an Active Model Serializer 0.10 class

I have the folowing ASM 0.10 :
class UserMicroSerializer < ActiveModel::Serializer
attributes :id, :name, :is_friend
def is_friend
#instance_options[:is_friend]
end
end
but would also like to support not having the is_friend attribute.
I have tried various things like:
class UserMicroSerializer < ActiveModel::Serializer
attributes :id, :name
if #instance_options[:is_friend]
attributes :is_friend
end
def is_friend
#instance_options[:is_friend]
end
end
but get error msg:
NoMethodError: undefined method `[]' for nil:NilClass
How would I make the #instane_options conditionally include is_friend?
If you can conditionally use a different serializer in the controller then you may be able to do this
class SimpleUserMicroSerializer < ActiveModel::Serializer
attributes :id, :name
end
By subclassing the simple serializer, you don't have much code overlap
class UserMicroSerializer < SimpleUserMicroSerializer
attributes :is_friend
def is_friend
#instance_options[:is_friend]
end
end
You can also send { scope: 'is_friend' } from controller and then check it into serializer.
class UserMicroSerializer < ActiveModel::Serializer
attributes :id, :name, :is_friend
def filter(keys)
keys.delete :is_friend if scope and scope[:is_friend]
super(keys)
end
end

Passing options to ActiveModel serializer

When using the serializer from the controller I can pass extra options to it like so
render json: user, some_option: 'foobar
Then I can reference some_option within the serializer as
serialization_options[:some_option]
But, if I call the serializer directly as
MySerializer.new(user, some_option: 'foobar')
I cannot get the extra options since serialization_options is an empty object.
For v0.9
You may call the following:
MySerializer.new(user).as_json({some_option: 'foobar'})
If you are doing that inside another serializer and you need to pass the scope and the current serialization_options as well, you can do this:
class MyParentSerializer
has_one :user
def user
MySerializer.new(object.user, { scope: scope }).as_json(serialization_options.merge({ some_option: 'foobar' }))
end
end
ActiveModel::Serializer's API has not really been consistent, in v0.9, however if you upgrade to v0.10, you could use the instance_options method to access the additional params. However, I'd be curious to learn how the objects were parsed in v0.9, though
Here is how you can pass parameters (options) from the parent serializer and show or hide attributes based on these parameters in the child serializer.
Parent serializer:
class LocationSharesSerializer < ActiveModel::Serializer
attributes :id, :locations, :show_title, :show_address
def locations
ActiveModelSerializers::SerializableResource.new(object.locations, {
each_serializer: PublicLocationSerializer,
params: {
show_title: object.show_title
},
})
end
end
Child serializer
class PublicLocationSerializer < ActiveModel::Serializer
attributes :id, :latitude, :longitude, :title, :directions, :description, :address, :tags, :created_at, :updated_at, :photos
def title
object.title if #instance_options[:params][:show_title]
end
end

Resources