ActiveModel serializers under namespace not working - ruby-on-rails

I have below serializer /serializers/api/club_serializer.rb:
class Api::ClubSerializer < ActiveModel::Serializer
cached
attributes :id, :name, :created_at
end
And below method under /controllers/api/clubs_controller.rb
module Api
class ClubsController < BaseController
include ActionController::ImplicitRender
include ActionController::MimeResponds
# GET /clubs
def index
#clubs = Club.all
render json: #clubs, serializer: ClubSerializer
end
This doesn't seem to be working properly as I remove name it still shows name with all fields.
How do I change it so it works?

The way you do this now:
render json: #clubs, namespace: Api
See: https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/rendering.md#namespace

why not:
render json: #clubs, each_serializer: ::Api::ClubSerializer

Related

How to use conditional attributes with jsonapi-serializers

I am working on a Ruby on Rails project with ruby-2.5.0 and Rails 5. i am working on api part, i have used jsonapi-serializers gem in my app. I want to add conditional attribute in serializer.
Controller:
class RolesController < ApplicationController
def index
roles = Role.where(application_id: #app_id)
render json: JSONAPI::Serializer.serialize(roles, is_collection: true)
end
end
Serializer:
class RoleSerializer
include JSONAPI::Serializer
TYPE = 'role'
attribute :id
attribute :name
attribute :application_id
attribute :application do
JSONAPI::Serializer.serialize(object.application)
end
end
Here application is a model which has_many roles and roles belongs to application. I want to add application details in some conditions. I also tried like:
Controller:
class RolesController < ApplicationController
def index
roles = Role.where(application_id: #app_id)
render json: JSONAPI::Serializer.serialize(roles, is_collection: true, params: params)
end
end
Serializer:
class RoleSerializer
include JSONAPI::Serializer
TYPE = 'role'
attribute :id
attribute :name
attribute :application_id
attribute :application do
JSONAPI::Serializer.serialize(object.application), if: #instance_options[:application] == true
end
end
But #instance_options is nil. Please help me how i can fix it. Thanks in advance.
In the jsonapi-serializers this is what is said about custom attributes:
'The block is evaluated within the serializer instance, so it has access to the object and context instance variables.'
So, in your controller you should use:
render json: JSONAPI::Serializer.serialize(roles, is_collection: true, context: { application: true })
And in your serializer you should use context[:application] instead of #instance_options

Getting Rails 5 app to return JSON API format

I'm trying to get my app to return in lowercase camelcase for eventual JSON API formatting.
I've installed gem 'active_model_serializers' and created a new initializer with the following code in it:
ActiveModelSerializers.config.adapter = :json_api
ActiveModelSerializers.config.key_transform = :camel_lower
Then I have a small API that returns json, as all of the best internet applications do:
class Api::V1::UsersController < API::V1::BaseController
def sky
#user = User.find_by_id(params[:user_id])
if #user
obj = {
sky: {
sectors: #user.sectors,
slots: #user.slots
}
}
render json: obj
else
raise "Unable to get Sky"
end
end
More on the API controller inheritance pattern: class API::V1::BaseController < ActionController::Base
The Problem
In my API response, things are still snake cased and I see this error in the console [active_model_serializers] Rendered ActiveModel::Serializer::Null but my research has led me to a dead end as to what to do.
Any suggestions would be very welcome. Thanks!
The problem is you're not calling an active record serializer in your controller, so those config settings aren't being picked up.
Solution:
Create a UserSerializer in "app/serializers/user_serializer.rb" that should look something like this:
class UserSerializer < ActiveModel::Serializer
attributes :id
has_many :sectors
has_many :slots
end
as well as similarly structured SectorSerializer and a SlotSerializer with all of the attributes you want from each (Here are the getting started docs and the general syntax docs for active record serializers)
Then in your controller:
class Api::V1::UsersController < API::V1::BaseController
def sky
#user = User.includes(:sectors, :slots).find_by_id(params[:user_id])
if #user
render json: #user
else
raise "Unable to get Sky"
end
end
end
Which will eager load :slots and :sectors with includes then calls your UserSerializer using your camel_case config options.
In your controller put respond_to :json
class Api::V1::UsersController < API::V1::BaseController
respond_to :json
and in the action put same that you have
def sky
...
render json: obj
...
end
and define in base controller
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }
From this pull request (*) it looks like you should be able to configure key_format = :lower_camel in your ActiveModel::Serializers config.
(*) https://github.com/rails-api/active_model_serializers/pull/534
i think it helps you. in my case i use gem 'active_model_serializers', '~> 0.10.5' which depends on case_transform (>= 0.2)
and in rails console i can do
CaseTransform.camel_lower(initially_serialized_output)
=> {:name=>"My Company", :jsonThings=>{:rating=>8, :aKey=>{:aSubkey=>{:anotherKey=>"value"}}}}
my research was by steps:
https://github.com/rails-api/active_model_serializers/pull/1993 => https://github.com/NullVoxPopuli/case_transform-rust-extensions
did you find this?

Rails API versioning, AMS doesn't use custom serializers

I'm working on a Rails application and I'm versioning the API.
Following RailsCast #350 I have this:
routes.rb
namespace :v1 do
#resources for version 1
end
namespace :v2 do
#resources for version 2
end
I use active_model_serializer and I have app/serializers/v1/ and .../v2/ with:
(for /v1)
module V1
class ResourceSerializer < ActiveModel::Serializer
attributes :id
end
end
(for /v2)
module V2
class ResourceSerializer < ActiveModel::Serializer
attributes :id, :data
end
end
But Rails doesn't call my custom serializer.
module V1
class ResourcesController < ApplicationController
def show
#resource = Resource.find(params[:id])
render json: #resource
end
end
end
OUTPUT for .../v1/resources/1
{"id":1,"name":"...","city":"...","created_at":"...","updated_at":"2..."}
instead of
{"id":1}
If I put render json: #resources, serializer: ResourceSerializer it retrieves undefined method 'read_attribute_for_serialization'
Any help would be appreciated. Thanks!
EDIT: Namespaces are valid!
I got this problem also, I have tried many solutions, but didn't work for me
the only solution that works is calling the serializer class directly:
render json: V1::ResourceSerializer.new(#resource)
If your problem only "undefined method 'read_attribute_for_serialization'", include ActiveModel::Serialization into your ActiveModel sub class
module V1
class ResourceSerializer < ActiveModel::Serializer
include ActiveModel::Serialization
attributes :id
end
end
I finally got a solution using each_serializer: V1::UserSerializer for collections and serializer: V2::UserSerializer for normal objects.
Thanks to all.

Active model serialization not working with api versioning

I have api with version system.
My controller
module Api;module V1
class PlansController < ApplicationController
def show
#plan = Plan.find(params[:id])
render json: #plan
end
end
end;end
I have folder serializers/api/v1 where i have plan_serializer.rb
module Api;module V1
class PlanSerializer < ActiveModel::Serializer
attributes :name, :amount, :days
end
end;end
But its not serializing json response automatically.
Please tell me what wrong am I doing ?
I also tried adding
class ApplicationController < ActionController::API
include ActionController::Serialization
but still its not working.
If I am doing
render json: #plan, serializer: V1::PlanSerializer
then it is working but I want it to work without adding serializer in every render.
Please tell me solution.
It may work if you override render.
class ApplicationController < ActionController::API
include ActionController::Serialization
DEFAULT_SERIALIZER= V1::PlanSerializer
def render options, &block
options[:serializer]= DEFAULT_SERIALIZER unless options[:serializer]
super options, &block
end
end

Using Jbuilder, Not able to get Json output instead of that showing error like undefined method `dump' for MultiJson:Module

Please find here is my controller and json file
//controller file
module Api
module V1
class CouponsController < ApplicationController
respond_to :json
def show
#coupon = Coupon.find(params[:id])
render "/coupons/show.json.jbuilder"
end
end
end
end
//show.json.jbuilder
json.extract! #coupon, :id, :category
Maybe you need to rewrite the head in controller like this:
module Api::V1::CouponsController < ApplicationController
Because your current write assumes that you have Api::V1::ApplicationController. And Api::V1::CouponsController is inherited from it, not from ApplicationController.

Resources