I'm building a JS app with a Rails backend and in order not to confuse snake and camel cases, I want to normalize it all by returning camelcase key names from the server. So user.last_name
would return user.lastName
when returned from the API.
How do I achieve this? Thanks!
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
The way I do it is using ActiveModelSerializer and the 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/
.
Next, 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 your obj
hash, but all attribute keys will be rendered in camelCase using the jsonapi standard.
Another option is the use the olive_branch gem. As described in this post, all you need to do is:
config.middleware.use OliveBranch::Middleware
in application.rb
.Then, add this header to requests from your client-side app:
'X-Key-Inflection': 'camel'
If you are using libs like axios, you can add this header to a constant along with other headers:
const HEADERS = {
...
'X-Key-Inflection': 'camel'
}
const request = axios.post(url, param, HEADERS)
This way you don't need to deep_transform
keys manually on the server side. Even deeply-nested json keys will be camelized. Example response from such request:
[
{
"id": 1,
"firstName": "Foo",
"lastName": "Bar",
"createdAt": ...,
"updatedAt": ...,
...
"cabinAssignments": [
{
"id": 1,
"cabinKeeperId": 1,
"userId": 1,
"houseId": 1,
...
}
]
}
]
You don't mention your Rails version, so for others who look for this, I'll mention that in Rails 5 the answer is to use #camelize
from ActiveSupport::Inflector
. In my case, I had to call it in a chain on an ActiveRecord
model (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 necessary depending on your application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With