sql - ActiveRecord 的意外行为包括

标签 sql ruby-on-rails ruby ruby-on-rails-4 rails-activerecord

我正在使用 AR includes在对象 UserBuilding 之间执行 LEFT OUTER JOIN 的方法,其中 User 可能有也可能没有 Building 关联:

users = User.includes(:building).references(:buildings)

因为我正在使用 references ,任何关联的 Building 对象都将被预先加载。

我的期望是我随后能够遍历用户列表,并检查用户是否有与其关联的建筑物而不会触发额外的查询,但实际上每当我尝试访问建筑物属性时我都会看到对于没有建筑物的用户,AR 会进行另一个 SQL 调用以尝试检索该建筑物(尽管在后续尝试中它只会返回 nil)。

这些查询显然是多余的,因为关联会在初始连接期间加载,并且似乎违背了使用包含/引用进行预加载的全部目的,因为现在我看到 N 倍的查询数量等于空关联的数量。

users.each do | user |

  # This will trigger a new query when building is not present: 
  # SELECT  "buildings".* FROM "buildings" WHERE "buildings"."address" = $1 LIMIT 1  [["address", "123 my street"]]
  if user.building
    puts 'User has building'
  else
    puts 'User has no building' 
  end

end

用户类:

class User < ActiveRecord::Base
  belongs_to :building, foreign_key: 'residence_id'
end

有没有办法在不触发额外查询的情况下检查用户建筑关联的存在?


ON RAILS 4.2.0/POSTGRES


更新:

感谢@BoraMa 整理这个 test .看起来我们在最近的 Rails 版本中有不同的行为:

输出(RAILS 4.2.0):

User 1 has building
User 2 has building
User 3 has no building
D, [2016-05-26T11:48:38.147316 #11910] DEBUG -- :   Building Load (0.2ms)  SELECT  "buildings".* FROM "buildings" WHERE "buildings"."id" = $1 LIMIT 1  [["id", 123]]
User 4 has no building

输出(RAILS 4.2.6)

User 1 has building
User 2 has building
User 3 has no building
User 4 has no building

输出(RAILS 5.0.0)

User 1 has building
User 2 has building
User 3 has no building
User 4 has no building

外卖:

  • 此问题仅限于“悬挂外键(即 residence_id 列不为零,但没有相应的建筑对象)” (感谢@FrederickCheung)
  • 从 Rails 4.2.6 开始,该问题已得到解决

最佳答案

听起来你被 bug 咬了在 Active Record 中,这是在 rails 4.2.3 中修复的。

在列为 nil 的情况下,Active Record 已经知道它甚至不需要尝试加载关联的对象。其余案例是受此错误影响的案例

关于sql - ActiveRecord 的意外行为包括,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37400586/

相关文章:

ruby-on-rails - 新的 LinkedIn 权限 : accessing past positions and educations using rails LinkedIn gem

ruby - 什么是 -@ 和 +@ 导致 String 的 NoMethodError

sql - 将数据从一个数据库传输到另一个数据库

ruby-on-rails - 带有文本和子元素的 Assert_select

php - 我应该在 PDO 对象中返回什么来生成可靠的代码?

html - 更改从 f.label 生成的自动文本

ruby - 如果系统调用返回错误,则使 rake 任务失败

ruby-on-rails - 是否可以从 Thor 脚本中调用 Git 或其他命令行工具?

php - PDO/SQL Select * from function 显示没有结果

php - 链接并发送表单值到mysql数据库?