我正在使用
> ruby -v
ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-darwin12.0]
> rails -v
Rails 4.0.2
通常情况下,
> [1,2,3,4,5].find_all{|x| x == 4}.count
和
> [1,2,3,4,5].count{|x| x == 4}
给出相同的值:
=> 1
......一切都很好。
但是在我的应用中,出了点问题。当我输入一个断点(使用pry)时,我注意到我的不一致:
(不要过分担心这里的特定数据结构)
> Meme.find(24).punches.count{|punch| punch.new_to_user?(User.find(14))}
=> 6
鉴于:
> Meme.find(24).punches.find_all{|punch| punch.new_to_user?(User.find(14))}.count
=> 0
6!= 0,amirite?从http://ruby-doc.org/core-2.1.0/Enumerable.html文档中可以看出,ruby 2.1.0应该完全相同地处理这两种情况。
当我查看这些命令执行的内容时,很明显.count {}并没有真正评估其块内的代码:
> Meme.find(24).punches.count{|punch| punch.new_to_user?(User.find(14))}
CACHE (0.0ms) SELECT "memes".* FROM "memes" WHERE "memes"."id" = $1 LIMIT 1 [["id", 24]]
CACHE (0.0ms) SELECT COUNT(*) FROM "punches" WHERE "punches"."meme_id" = $1 [["meme_id", 24]]
=> 6
与(我认为)find_all的正确行为相反:
> Meme.find(24).punches.find_all{|punch| punch.new_to_user?(User.find(14))}.count
CACHE (0.0ms) SELECT "memes".* FROM "memes" WHERE "memes"."id" = $1 LIMIT 1 [["id", 24]]
CACHE (0.0ms) SELECT "punches".* FROM "punches" WHERE "punches"."meme_id" = $1 [["meme_id", 24]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 14]]
CACHE (0.2ms) SELECT "votes".* FROM "votes" INNER JOIN "vote_decisions" ON "votes"."vote_decision_id" = "vote_decisions"."id" WHERE "vote_decisions"."user_id" = $1 AND "votes"."punch_id" = 531 [["user_id", 14]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 14]]
CACHE (0.0ms) SELECT "votes".* FROM "votes" INNER JOIN "vote_decisions" ON "votes"."vote_decision_id" = "vote_decisions"."id" WHERE "vote_decisions"."user_id" = $1 AND "votes"."punch_id" = 532 [["user_id", 14]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 14]]
CACHE (0.0ms) SELECT "votes".* FROM "votes" INNER JOIN "vote_decisions" ON "votes"."vote_decision_id" = "vote_decisions"."id" WHERE "vote_decisions"."user_id" = $1 AND "votes"."punch_id" = 533 [["user_id", 14]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 14]]
CACHE (0.0ms) SELECT "votes".* FROM "votes" INNER JOIN "vote_decisions" ON "votes"."vote_decision_id" = "vote_decisions"."id" WHERE "vote_decisions"."user_id" = $1 AND "votes"."punch_id" = 534 [["user_id", 14]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 14]]
CACHE (0.0ms) SELECT "votes".* FROM "votes" INNER JOIN "vote_decisions" ON "votes"."vote_decision_id" = "vote_decisions"."id" WHERE "vote_decisions"."user_id" = $1 AND "votes"."punch_id" = 535 [["user_id", 14]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 14]]
CACHE (0.0ms) SELECT "votes".* FROM "votes" INNER JOIN "vote_decisions" ON "votes"."vote_decision_id" = "vote_decisions"."id" WHERE "vote_decisions"."user_id" = $1 AND "votes"."punch_id" = 536 [["user_id", 14]]
=> 0
我使用的ruby或rails版本是否不支持使用count {block}?我一直在使用ruby 2.1.0 doc http://ruby-doc.org/core-2.1.0/Enumerable.html作为参考。
我的app正在使用的版本,或pry正在使用的版本,与我期望的2.1.0 / 4.0.2不同? FWIW,在我的Gemfile中我有
source 'https://rubygems.org'
ruby "2.1.0"
gem 'rails', '4.0.2'
缓存?我根本不明白这一点。
编辑:
澄清一下,new_to_user?与其他ActiveRecords做了一些工作。这就是为什么我说find_all行为似乎是正确的。 count {}似乎正在运行一个简单的SQL COUNT命令,这对我来说是错误的(但可能是正确的ruby版本,原因我不明白)
答案 0 :(得分:3)
Meme.find(24).punches
不会返回数组。它返回一个ActiveRecord::Relation
,它通常表现得像一个数组,但它有一些不同的属性。
当您在关系上调用#count
时,会执行ActiveRecord
association #count
方法,而不是可枚举#count
。这意味着Meme.find(24).punches.count
应该是SQL计数并返回meme的打孔数,而不管块(在这种情况下被忽略)。
如果您想获得相同的结果,首先需要将关联转换为Array
。
Meme.find(24).punches.to_a.count{|punch| punch.new_to_user?(User.find(14))}
答案 1 :(得分:1)
find_all
与来自ActiveRecord的find_all
的方法不同。