Graham S.
Graham S.

Reputation: 1540

Active Model Serializer - How do I include an attribute conditionally? Rails

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:

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

Answers (3)

Van_Paitin
Van_Paitin

Reputation: 4238

You can define attributes conditionally. See here.

Upvotes: 0

tegon
tegon

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

yez
yez

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

Related Questions