从ActiveRecord模型中获取特定属性

vas*_*fil 39 select authorization ruby-on-rails filter

假设我有一个User带属性的模型:id, :first_name, :last_name, and :email.在我的应用程序中,访客用户不应该看到User's email and last_name.如果我想要一个用户列表,我知道如何选择特定值,但我不知道如何获得特定用户的特定属性,如

User.find_by(id: 5).select(:id, :first_name).
Run Code Online (Sandbox Code Playgroud)

对此的一个解决方案是用户

User.find_by(id: 5).attributes.slice('id', 'first_name') 
Run Code Online (Sandbox Code Playgroud)

但后来我得到一个哈希而不是一个AR记录.我可以

User.select(:id, :first_name).find_by(id: 1) 
Run Code Online (Sandbox Code Playgroud)

但是我不知道应该过滤哪些过滤器,因为我需要先了解用户.

你可以帮帮我吗?

jos*_*ing 99

如果你想让一个数组不是一个活动的记录实例,那么Choco说会有效.如果需要活动记录实例,请执行以下操作:

User.where(id: 5).select(:id, :first_name).take 
Run Code Online (Sandbox Code Playgroud)

这里有更多信息.我不确定你知道多少,所以我会假设你知道的少而不是更多.

我假设你意识到你正在做的是方法链接 - 即,你正在调用一个方法,然后在第一个方法的结果上调用另一个方法.例如:

User.find_by(id: 5).attributes.slice('id', 'first_name')
Run Code Online (Sandbox Code Playgroud)

你在课堂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或者selecton 这样的方法时ActiveRecord::Relation,它会返回一个实例ActiveRecord::Relation,这意味着你有一个同一个类的实例,并且可以很好地链接该类的方法,例如:User.where(name: 'Fred').select(:id, :name).order('name ASC')

你的情况ActiveRecord::Relation会很聪明,不会打扰进入数据库,直到你把那个叫清楚地表明你想要的记录,现在的方法-如each,all,take,等

所以,我已经比这里计划的时间更长,所以我会结束.这是我第一次提到的代码,下面是一个细分的,大量评论的解释:

User.where(id: 5).select(:id, :first_name).take
Run Code Online (Sandbox Code Playgroud)

打破它:

my_relation = User.where(id: 5)
# The database will not have been hit yet - my_relation 
# is a query waiting to happen

my_second_relation = my_relation.select(:id, :first_name)
# The database has STILL not been hit.
# the relation now contains both the conditions 
# from the previous my_relation, and the new 'select'
# criteria we specified

my_user = my_second_relation.take
# OK, 'take' means we want the first record
# matching all our criteria,
# so my_second_relation will hit the database 
# to get it, and then return an Active Record 
# instance (ie, an instance of the User class)
Run Code Online (Sandbox Code Playgroud)

哇......我比预期的还要长.希望其中一些有用!

  • 我读过的ActiveRecord :: Relation最好的解释之一!谢谢!! (5认同)

小智 25

试试这个:

User.where(id: 5).pluck(:id, :first_name) 
Run Code Online (Sandbox Code Playgroud)

它返回包含id和first_name值的数组


tkh*_*ynh 7

这也将起作用

User.select(:id, :first_name).find(5)