Reputation: 26658
How do I customize the JSON output on creation of a devise User?
### User.rb ###
class User < ActiveRecord::Base
devise :database_authenticatable,
:registerable, ...
...
end
### Routes.rb ###
...
devise_for :users, :controllers => {:registrations => "registrations"}
...
I've got some extra fields in my User table that are secret, but they get returned in the JSON response when I do a User creation via JSON like this:
$ curl -H "Content-Type: application/json" -d '{"user" : {"username":"someone","email":"[email protected]","password":"awesomepass"}}' -X POST http://localhost:3000/users.json
which returns:
{"user":{"secret_field_1":"some value","secret_field_2":"some value","created_at":"2013-07-25T21:24:50-05:00","email":"[email protected]","first_name":null,"id":3226,"last_name":null,"updated_at":"2013-07-25T21:24:50-05:00","username":"someone"}}
I'd like to hide those secret fields, but don't know how to customize the JSON response.
I've tried a standard ActiveRecord serializer:
class UserSerializer < ActiveModel::Serializer
attributes :id, :created_at, :updated_at, :email, :first_name, :last_name, :username
end
to no avail, I'm guessing because of Devise.
Upvotes: 8
Views: 7628
Reputation: 26
I just had the same problem, below is how I resolved it, very simple.
All these passed in active_model_serializers (0.9.5)
Override Devise registration method, and in your customize action:
def registration
//Some process, and you get a @user when registration is successful.
render :json => UserSerializer.new(@user)
end
If you want to pass some parameters to your customized Serializer(token for example), you can pass it in your action:
render :json => UserSerializer.new(@user).as_json({auth_token: your_token})
And in your serializer, just use:
class UserSerializer < ActiveModel::Serializer
attributes :id, :name, :avatar_url, :auth_token
def auth_token
serialization_options[:auth_token]
end
end
Upvotes: 0
Reputation: 1408
I recently ran into this and overriding respond_with
didn't fix the issue. I ended up overriding to_json
in user.rb like so:
def to_json(arg)
UserSerializer.new(self).to_json
end
Not sure what the extra arg is, but that seems to be required by one of the devise mixins.
I'm using the following:
Upvotes: 3
Reputation: 1911
Just a guess, but it sounds like rails is not finding your serializer and is using to_json()
. Did you define active_model_serializer()
in your model?
Upvotes: 0
Reputation: 929
I just ran into the same issue. I haven't pinpointed exactly why but it looks like respond_with
in Devise's SessionsController (tested on Devise 3.0 and active_model_serializers 0.8.1) doesn't trigger the ActiveModel::Serializer
.
So I overrode respond_with
in my controller:
class SessionsController < Devise::SessionsController
def respond_with(resource, opts = {})
render json: resource # Triggers the appropriate serializer
end
end
It is, however, working in my RegistrationsController with respond_with
. There I needed to do the following:
class RegistrationsController < Devise::RegistrationsController
respond_to :json
end
Upvotes: 12
Reputation: 167
Depending on what you are doing with that JSON, you simply have to remove attributes you don't want from your serializer.
For example :
class UserSerializer < ActiveModel::Serializer
attributes :id, :email, :username
end
I presume that, in your case, you just want to do that.
But you also have the possibility to include an attribute on a specific condition :
class PostSerializer < ActiveModel::Serializer
attributes :id, :title, :body, :author
def include_author?
current_user.admin?
end
end
And finally you can override the attributes method to return the hash you need :
class PersonSerializer < ActiveModel::Serializer
attributes :first_name, :last_name
def attributes
hash = super
if current_user.admin?
hash["ssn"] = object.ssn
hash["secret"] = object.mothers_maiden_name
end
hash
end
end
See README of ActiveModel::Serializers
for more informations.
Upvotes: -1