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
Related
I am completely new to RubyOnRails so please be careful for even simplest mistakes I could have done. I developed a simple app that displayes some data from a .csv file. Here my code:
class UsersController < ApplicationController
def index
#users = getUsers
end
private def getUsers
invoker = ProviderInvoker.new(UserProvider.new("app/data/user_data.csv"))
invoker.getData
end
end
My app displaying the data as I wanted. No problem so far but I want to create and use an internal API for providing data so I am changing my UsersController into this:
require "net/http"
class UsersController < ApplicationController
def index
uri = URI("http://localhost:3000/api/users")
response = Net::HTTP.get(uri)
#users = JSON.parse(response)
end
end
and created another UsersController under app/controllers/api
class Api::UsersController < ApplicationController
def index
invoker = ProviderInvoker.new(UserProvider.new("app/data/user_data.csv"))
data = invoker.getData
render json: data
end
end
And lastly I created a serializer under app/serializers:
class UsersSerializer < ActiveModel::Serializer
attributes :id, :first_name, :last_name, :email, :user_name
end
When I go to my index page I get an error like
No serializer found for resource: #< User:0x07aaebb0 #id="1", #first_name="Susan", #last_name="Gomez", #email="sgomez0#cpanel. net", #user_name="sgomez0">
Obviously there is something wrong with my serializer but I can't manage to find what.
It is a good practice to put serializer under Api module also, so you won't be confused which serializer you use.
As a try you may set serializer manually in controller, like this:
def index
invoker = ProviderInvoker.new(UserProvider.new("app/data/user_data.csv"))
data = invoker.getData
render json: data, each_serializer: UsersSerializer, adapter: :json
end
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?
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.
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
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.