假设我有User
模型,其属性为:id, :first_name, :last_name, and :email
。在我的应用程序中,访客用户不应该看到User's email and last_name
。如果我想要一个用户列表但我不知道如何获得特定用户的特定属性,我知道如何选择特定值,如
User.find_by(id: 5).select(:id, :first_name).
一个解决方案是用户
User.find_by(id: 5).attributes.slice('id', 'first_name')
然后我得到哈希而不是AR记录。我能做到
User.select(:id, :first_name).find_by(id: 1)
但是我不知道应该过滤哪些过滤器,因为我需要先了解用户。
你能帮帮我吗?
答案 0 :(得分:83)
如果你想让一个数组不是一个活动的记录实例,Choco说会有什么用。如果需要活动记录实例,请执行以下操作:
User.where(id: 5).select(:id, :first_name).take
这里有更多信息。我不知道你做了多少/不知道多少,所以我假设你知道的更少而不是更多。
我假设你意识到你在上面做的是方法链接 - 也就是说,你正在调用一个方法,然后在第一个方法的结果上调用另一个方法。例如:
User.find_by(id: 5).attributes.slice('id', 'first_name')
您正在find_by_id
课程中调用User
方法。该方法将返回User
类的实例(即活动记录实例)。该实例有一个名为attributes
的方法,您可以调用它。 attributes
方法返回Hash
类的实例,表示前一个活动记录实例中的字段。 Hash
有一个slice
方法,您可以依次调用它。 slice
方法返回Hash
的另一个实例,其中包含您指定的字段子集。
所以,要明确的概念是,当你链接方法时,你并没有在同一个东西上调用每个后续方法 - 你在它的返回值上调用它。链中的先前方法。
好的,这样就可以了:
所有find
方法都用于查询数据库并返回Active Record模型的单个实例,或者包含多个Active Record模型实例的普通ruby数组。
许多其他方法 - select
,where
等不会立即命中数据库,也不会返回活动记录实例。它们都返回ActiveRecord::Relation
的实例。 ActiveRecord::Relation
有点像符合某些条件的潜在记录组 - 您可以为其添加额外条件。它就像一个等待发生的数据库查询,或者一个可能已经发生过或者可能没有发生过的数据库查询。
当您在where
上调用类似order
,select
或ActiveRecord::Relation
的方法时,它会返回ActiveRecord::Relation
的实例,这意味着您&#39 ;有一个同一个类的实例,可以很好地链接该类的方法,例如:User.where(name: 'Fred').select(:id, :name).order('name ASC')
ActiveRecord::Relation
的实例非常聪明,在您调用一个明确表示您现在需要记录的方法之前,不会打扰数据库,例如each
,{{ 1}},all
等
所以,我已经比这里计划的时间更长,所以我将结束。这是我第一次提到的代码,下面有一个细分的,大量评论的解释:
take
打破它:
User.where(id: 5).select(:id, :first_name).take
哇...我比预期的还要长。希望其中一些有用!
答案 1 :(得分:23)
试试这个:
User.where(id: 5).pluck(:id, :first_name)
它返回包含id和first_name值的数组
答案 2 :(得分:4)
这也适用
User.select(:id, :first_name).find(5)
答案 3 :(得分:0)
具有这样的要求,但需要更通用的东西,即只从模型中收集方法名称和值的列表(包括属性)。因此,我将此方法添加到了模型中:
def attributes_from_keys(*keys)
keys.inject({}) do |hash_to_return, key|
hash_to_return.merge(key => send(key))
end
end
然后,使用以下方法调用此方法:
MyModel.find(1).attributes_from_keys(:id, :name, :age)
返回
{id: 1, name: 'Lawrence', age: 23}