Ruby on Rails 3 - to_json不包括所有属性

时间:2022-05-24 04:09:31

I'm using the to_json method on my model object that I created by doing something like:

我在我的模型对象上使用to_json方法,我通过执行以下操作来创建:

user = User.find(1)

user = User.find(1)

When I do user.to_json, a lot of attributes are missing, including user.id from the encoded JSON string. It appears that all of the attributes that I've added as attr_accessible from the User model are there, but none of the others. Perhaps that is what to_json is doing, but I think that adding id to attr_accessible is a no go.

当我执行user.to_json时,会丢失许多属性,包括编码的JSON字符串中的user.id。看来我从User模型中添加为attr_accessible的所有属性都存在,但没有其他属性。也许这就是to_json正在做的事情,但我认为在attr_accessible中添加id是不行的。

What is the right way of solving this problem?

解决这个问题的正确方法是什么?

UPDATE

UPDATE

This looks to be a specific issue with Devise. If I comment out the following from user.rb, everything works as expected:

这看起来是Devise的一个特定问题。如果我从user.rb注释掉以下内容,一切都按预期工作:

devise :rememberable, :trackable, :token_authenticatable, :omniauthable

设计:可记住的,:可跟踪的,:token_authenticatable,:omniauthable

5 个解决方案

#1


5  

I haven't checked but I believe Devise does that for you; it includes only certain attributes via attr_accessible.

我没有检查过,但我相信Devise会为你做这件事;它只包含attr_accessible的某些属性。

In any case the right way to solve this is to override the as_json method like so:

在任何情况下,解决此问题的正确方法是覆盖as_json方法,如下所示:

def as_json(options = nil)
  {
    my_attr: my_attr,
    etc: etc
  }
end

It's a simple hash and it's a really powerful method to generate JSON in AR, without messing with the to_json method.

这是一个简单的哈希,它是一个非常强大的方法,可以在AR中生成JSON,而不会弄乱to_json方法。

#2


2  

By default Devise overrides the serializable_hash method to expose only accessible attributes (so things like the encrypted_password doesn't get serialized by default on APIs).

默认情况下,Devise会覆盖serializable_hash方法以仅公开可访问的属性(因此,在APIs上默认情况下,encrypted_pa​​ssword不会被序列化)。

You could try to override this method and add the auth_token to the hash, something like this:

您可以尝试覆盖此方法并将auth_token添加到哈希,如下所示:

def serializable_hash(options = nil) super(options).merge("auth_token" => auth_token) end

def serializable_hash(options = nil)super(options).merge(“auth_token”=> auth_token)end

#3


2  

Devise indeed filters the attributes for you, as mentioned by kain. Nevertheless, I'd rather just append exactly what I need to instead of overriding Devise's logic.

正如凯恩所提到的,设计确实为你过滤了属性。然而,我宁愿只是追加我需要的东西而不是覆盖Devise的逻辑。

Instead, I'd rather do

相反,我宁愿这样做

def as_json(options={})
  json_res = super options
  json_res['locked_at'] = self.locked_at
  json_res['confirmed_at'] = self.confirmed_at
end

or whatever other attributes your user might have that you want to pass

或者您的用户可能拥有的任何其他属性

#4


2  

If you came here looking for Rails 4, like I did, here's some information that will help.

如果你像我一样来这里寻找Rails 4,这里有一些有用的信息。

As Alan David Garcia said above, Devise overrides serializable_hash. To force an override, you could do the following, for example, to return all attributes except password_digest when calling Model#as_json.

正如Alan David Garcia上面所说,Devise会覆盖serializable_hash。要强制覆盖,您可以执行以下操作,例如,在调用Model#as_json时返回除password_digest之外的所有属性。

def as_json(options = {})
  options[:force_except] ||= [:password_digest]
  super(options)
end

You can specify any desired model attributes to exclude in options[:force_except] instead of just :password_digest.

您可以在选项[:force_except]中指定要排除的任何所需模型属性,而不仅仅是:password_digest。

#5


0  

include something like this in your model class:

在你的模型类中包含这样的东西:

  attr_accessible :id, :email, :password, :password_confirmation, :remember_me

Initially the id wasn't included in json but after I added it to attr_accessible it worked!!

最初这个id没有包含在json中,但是在我将它添加到attr_accessible后它才起作用!!

#1


5  

I haven't checked but I believe Devise does that for you; it includes only certain attributes via attr_accessible.

我没有检查过,但我相信Devise会为你做这件事;它只包含attr_accessible的某些属性。

In any case the right way to solve this is to override the as_json method like so:

在任何情况下,解决此问题的正确方法是覆盖as_json方法,如下所示:

def as_json(options = nil)
  {
    my_attr: my_attr,
    etc: etc
  }
end

It's a simple hash and it's a really powerful method to generate JSON in AR, without messing with the to_json method.

这是一个简单的哈希,它是一个非常强大的方法,可以在AR中生成JSON,而不会弄乱to_json方法。

#2


2  

By default Devise overrides the serializable_hash method to expose only accessible attributes (so things like the encrypted_password doesn't get serialized by default on APIs).

默认情况下,Devise会覆盖serializable_hash方法以仅公开可访问的属性(因此,在APIs上默认情况下,encrypted_pa​​ssword不会被序列化)。

You could try to override this method and add the auth_token to the hash, something like this:

您可以尝试覆盖此方法并将auth_token添加到哈希,如下所示:

def serializable_hash(options = nil) super(options).merge("auth_token" => auth_token) end

def serializable_hash(options = nil)super(options).merge(“auth_token”=> auth_token)end

#3


2  

Devise indeed filters the attributes for you, as mentioned by kain. Nevertheless, I'd rather just append exactly what I need to instead of overriding Devise's logic.

正如凯恩所提到的,设计确实为你过滤了属性。然而,我宁愿只是追加我需要的东西而不是覆盖Devise的逻辑。

Instead, I'd rather do

相反,我宁愿这样做

def as_json(options={})
  json_res = super options
  json_res['locked_at'] = self.locked_at
  json_res['confirmed_at'] = self.confirmed_at
end

or whatever other attributes your user might have that you want to pass

或者您的用户可能拥有的任何其他属性

#4


2  

If you came here looking for Rails 4, like I did, here's some information that will help.

如果你像我一样来这里寻找Rails 4,这里有一些有用的信息。

As Alan David Garcia said above, Devise overrides serializable_hash. To force an override, you could do the following, for example, to return all attributes except password_digest when calling Model#as_json.

正如Alan David Garcia上面所说,Devise会覆盖serializable_hash。要强制覆盖,您可以执行以下操作,例如,在调用Model#as_json时返回除password_digest之外的所有属性。

def as_json(options = {})
  options[:force_except] ||= [:password_digest]
  super(options)
end

You can specify any desired model attributes to exclude in options[:force_except] instead of just :password_digest.

您可以在选项[:force_except]中指定要排除的任何所需模型属性,而不仅仅是:password_digest。

#5


0  

include something like this in your model class:

在你的模型类中包含这样的东西:

  attr_accessible :id, :email, :password, :password_confirmation, :remember_me

Initially the id wasn't included in json but after I added it to attr_accessible it worked!!

最初这个id没有包含在json中,但是在我将它添加到attr_accessible后它才起作用!!