Rails 这算特性还是算 Bug?

hjleochen · 2015年07月10日 · 最后由 zhang_soledad 回复于 2015年07月12日 · 1997 次阅读
class User < ActiveRecord::Base

  def self.test_by_conditions(id)
    User.where(id:id).to_sql
    #......
  end

  def self.test_by_id(id)
    User.find(id).to_sql
    #......
  end

end
User.where(id:1).to_sql
#SELECT "users".* FROM "users" WHERE "users"."id" = 1

User.where(id:1).test_by_conditions(2)
#SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."id" = 2

User.where(id:1).test_by_id(2)
#User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? AND "users"."id" = ? LIMIT 1  [["id", 1], ["id", 2]]
#ActiveRecord::RecordNotFound: Couldn't find User with 'id'=2 [WHERE "users"."id" = ?]

应该是 Arel 继承了前面的条件,似乎是到同一个 arel.scrope 里面去了,应该算是个 Bug 吧。

为什么要这么写…… User.where() 返回的是 Relation 吧……?

首先不要在 method 里面再写 User 了,这样比较丑,直接 where, find 就可以了。

第三个测试找不到记录,完全符合预期。你的命令是要在 id 为 1 的数据里面找到 id 为 2 的记录,当然找不到。

多个串接命令下的 SQL 合并成一个是 feature, 而且是必须的。要是一个个分开,那就费事了 :)

#1 楼 @msg7086 #2 楼 @billy

上面的代码只是为了方便说明举例写的,方法里面还有 #...... 表示更多逻辑哦。

实际代码中当然不是有意要这么写,但是 在 class methods(scope)里面调用的关于当前 model 的方法 (Relation) 中均会包含 scope 之前的 where 条件。

当然是特性了!

如果不需要的之前的 scope 的话,要使用 User.unscoped

照你的思路 自动覆盖掉前面的 scope 还能用?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号