背景
我在用着
> 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,阿米特?从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作为参考。
我的应用程序正在使用或 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 版本可能是正确的,原因我不明白)