在创建用户帐户时自定义设计用户JSON响应

时间:2013-07-26 02:47:40

标签: ruby-on-rails json activerecord devise

如何在创建设备用户时自定义JSON输出?

### User.rb ###
class User < ActiveRecord::Base
  devise :database_authenticatable,
         :registerable, ...
  ...
end

### Routes.rb ###
...
devise_for :users, :controllers => {:registrations => "registrations"}
...

我的User表中有一些额外的字段是秘密的,但当我通过JSON进行用户创建时,它们会在JSON响应中返回:

$ curl -H "Content-Type: application/json" -d '{"user" : {"username":"someone","email":"someone@somewhere.com","password":"awesomepass"}}' -X POST http://localhost:3000/users.json

返回:

{"user":{"secret_field_1":"some value","secret_field_2":"some value","created_at":"2013-07-25T21:24:50-05:00","email":"someone@somewhere.com","first_name":null,"id":3226,"last_name":null,"updated_at":"2013-07-25T21:24:50-05:00","username":"someone"}}

我想隐藏这些秘密字段,但不知道如何自定义JSON响应。

我尝试过标准的ActiveRecord序列化程序:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :created_at, :updated_at, :email, :first_name, :last_name, :username
end

无济于事,我因为设计而猜测。

5 个答案:

答案 0 :(得分:9)

我刚遇到同样的问题。我没有确切地指出原因,但在Devise的SessionsController中看起来像respond_with(在Devise 3.0和active_model_serializers 0.8.1上测试)不会触发ActiveModel::Serializer

所以我在我的控制器中覆盖了respond_with

class SessionsController < Devise::SessionsController

  def respond_with(resource, opts = {})
    render json: resource # Triggers the appropriate serializer
  end

end

然而,它在我的RegistrationsController中使用respond_with。我需要做以下事情:

class RegistrationsController < Devise::RegistrationsController

  respond_to :json
end

答案 1 :(得分:3)

我最近碰到了这个问题,并且覆盖respond_with没有解决问题。我最终在user.rb中覆盖了to_json,如下所示:

def to_json(arg)
  UserSerializer.new(self).to_json
end

不确定额外的arg是什么,但其中一个设计mixin似乎需要它。

我正在使用以下内容:

  • Rails 4.2.0
  • Devise 3.4.1

答案 2 :(得分:0)

只是一个猜测,但听起来像rails没有找到你的序列化器并使用to_json()。您是否在模型中定义了active_model_serializer()

答案 3 :(得分:0)

我遇到了同样的问题,下面就是我如何解决它,非常简单。

所有这些都传递到active_model_serializers (0.9.5)

覆盖设计注册方法,并在自定义操作中:

def registration
  //Some process, and you get a @user when registration is successful.

  render :json => UserSerializer.new(@user)
end

如果您想将一些参数传递给自定义的Serializer(例如令牌),您可以在操作中传递它:

render :json => UserSerializer.new(@user).as_json({auth_token: your_token})

在您的序列化程序中,只需使用:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :name, :avatar_url, :auth_token

  def auth_token
    serialization_options[:auth_token]
  end
end

答案 4 :(得分:-1)

根据您使用该JSON所做的操作,您只需删除序列化程序中不需要的属性。

例如:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :email, :username
end

我认为,在你的情况下,你只想这样做。

但您也可以在特定条件中包含属性:

class PostSerializer < ActiveModel::Serializer
  attributes :id, :title, :body, :author

  def include_author?
    current_user.admin?
  end
end

最后,您可以覆盖attributes方法以返回所需的哈希:

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

有关更多信息,请参阅ActiveModel::Serializers的{​​{3}}。