Reputation: 1540
I am using Active Model Serializers with my Rails 4 API, and I have been trying to figure out how to include the auth_token
attribute in my JSON response only when the user logs in at sessions#create
. I read the AMS documentation and tried most of the seeming solutions but none worked.
Couple things to point out:
:auth_token
is not in the UserSerializer
's attributes list.auth_token
is controller-specific, I can't do the conditional logic in the UserSerializer
unless there is a way to determine what controller was called in the Serializer. So no def include_auth_token? ... end
.Some of the things I've tried already:
class Api::V1::SessionsController < ApplicationController
if user = User.authenticate(params[:session][:email], params[:session][:password])
if user.active
user.generate_auth_token #=> Custom method
user.save
# Tried using the meta param
render :json => user, :meta => {:auth_token => user.auth_token}
# Tried using the include param both with 'auth_token' and 'user.auth_token'
render :json => user, include: 'user.auth_token'
end
end
end
Ideally, I would like to be able to use something along the lines of render :json => user, :include => :auth_token
to additionally include attributes not already defined in the UserSerializer
.
What is the proper way to conditionally include attributes from the controller with AMS?
Upvotes: 1
Views: 2219
Reputation: 538
After reading the documentation, looks like the include
will be available only in the v0.10.0 version. The correct docs from v0.9 are these: https://github.com/rails-api/active_model_serializers/tree/v0.9.0#attributes.
I've used the filter
method before, something like this should do the trick:
class Api::V1::SessionsController < ApplicationController
if user = User.authenticate(params[:session][:email], params[:session][:password])
if user.active
user.generate_auth_token
user.save
render :json => user, :meta => {:auth_token => user.auth_token}
end
end
end
class UserSerializer < ActiveModel::Serializer
attributes :id, :name, :auth_token
def filter(keys)
if meta && meta['auth_token']
keys
else
keys - [:auth_token]
end
end
end
Upvotes: 1
Reputation: 2378
Instead of relying on the render :json => user
call to serialize the user to a JSON payload, you can craft the payload yourself and have control over what is and what is not included.
user_payload = user.as_json
user_payload.merge!(:auth_token => user.auth_token) if include_auth_token?
render :json => user_payload
The as_json
method Returns a hash representing the model. You can then modify this hash before the JSON serializer turns it into proper JSON.
Upvotes: 0