How to return JSON from Rails with keyword names in stone
I am building a JS application with a Rails backend and in order not to confuse the snake and camel cases, I want to normalize the whole thing by returning the key names on the camcorder from the server. Thus, it user.last_name
returns user.lastName
when returned from the API.
How can I achieve this? Thank you!
Edit: added controller code
class Api::V1::UsersController < API::V1::BaseController
# authorize_resource
respond_to :json, only: [:index]
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
end
source to share
The way I do it is using ActiveModelSerializer and json_api adapter:
In your Gemfile add:
gem 'active_model_serializers'
Create a new file /config/initializers/ams.rb
containing:
ActiveModelSerializers.config.adapter = :json_api
ActiveModelSerializers.config.key_transform = :camel_lower
Your controller action should look like this:
class ApiController < ApplicationController
def sky
@user = User.find_by_id(params[:user_id])
if @user
render json: @user, serializer: UserSkySerializer
else
raise "Unable to get Sky"
end
end
end
Now you need to create a serializer. First create a new directory app/serializers/
.
Then create a new serializer app/serializers/user_sky_serializer.rb
containing:
class UserSkySerializer < ActiveModel::Serializer
attributes :sectors, :slots
end
The result will be similar to what you describe in the hash obj
, but all the attribute keys will be mapped to camelCase using jsonapi .
source to share
You didn't mention your version of Rails, so for others looking for this, I mentioned that in Rails 5 the answer is to use #camelize
from ActiveSupport::Inflector
. In my case, I had to chain it on the model ActiveRecord
( t
below):
def index
trucks = AvailableTruck.all.map do |t|
t.as_json(only: AvailableTruck.exposed)
.deep_transform_keys(&:camelize).deep_transform_values(&:upcase)
end
render json: trucks
end
#deep_transform_keys
may or may not be needed depending on your application.
source to share
You can achieve this with the help of ruby method method_missing
.
Create a file similar to the one concerns/method_missing_extension.rb
and put the following code in it.
module MethodMissingExtension
def method_missing(method_name, args = {})
if self.class.column_names.include? method_name.to_s.underscore
send method_name.to_s.underscore.to_sym
else
super
end
end
end
Include this module in every model for example include MethodMissingExtension
.
Now that you do user.firstName
, it comes back user.first_name
.
source to share