Join Rails 5.2中作用域中的连接与Rails 5.1有何不同?

Join Rails 5.2中作用域中的连接与Rails 5.1有何不同?,join,activerecord,ruby-on-rails-5.2,Join,Activerecord,Ruby On Rails 5.2,在我将rails从5.1升级到5.2之后,我开始出现以下错误: NoMethodError: undefined method `expr' for nil:NilClass from /gems_path/activerecord-5.2.0/lib/active_record/associations/join_dependency/join_association.rb:47:in `block in join_constraints' from /gems_path/active

在我将rails从5.1升级到5.2之后,我开始出现以下错误:

NoMethodError: undefined method `expr' for nil:NilClass
  from /gems_path/activerecord-5.2.0/lib/active_record/associations/join_dependency/join_association.rb:47:in `block in join_constraints'
  from /gems_path/activerecord-5.2.0/lib/active_record/associations/join_dependency/join_association.rb:33:in `reverse_each'
  from /gems_path/activerecord-5.2.0/lib/active_record/associations/join_dependency/join_association.rb:33:in `join_constraints'
  from /gems_path/activerecord-5.2.0/lib/active_record/associations/join_dependency.rb:167:in `make_constraints'
  from /gems_path/activerecord-5.2.0/lib/active_record/associations/join_dependency.rb:177:in `make_join_constraints'
  from /gems_path/activerecord-5.2.0/lib/active_record/associations/join_dependency.rb:104:in `block in join_constraints'
  from /gems_path/activerecord-5.2.0/lib/active_record/associations/join_dependency.rb:103:in `each'
  from /gems_path/activerecord-5.2.0/lib/active_record/associations/join_dependency.rb:103:in `flat_map'
  from /gems_path/activerecord-5.2.0/lib/active_record/associations/join_dependency.rb:103:in `join_constraints'
  from /gems_path/activerecord-5.2.0/lib/active_record/relation/query_methods.rb:1026:in `build_join_query'
  from /gems_path/activerecord-5.2.0/lib/active_record/relation/query_methods.rb:1008:in `build_joins'
  from /gems_path/activerecord-5.2.0/lib/active_record/relation/query_methods.rb:928:in `build_arel'
  from /gems_path/activerecord-5.2.0/lib/active_record/relation/query_methods.rb:903:in `arel'
  from /gems_path/activerecord-5.2.0/lib/active_record/relation.rb:554:in `block in exec_queries'
  from /gems_path/activerecord-5.2.0/lib/active_record/relation.rb:578:in `skip_query_cache_if_necessary'
  from /gems_path/activerecord-5.2.0/lib/active_record/relation.rb:542:in `exec_queries'
  from /gems_path/activerecord-5.2.0/lib/active_record/relation.rb:414:in `load'
  from /gems_path/activerecord-5.2.0/lib/active_record/relation.rb:200:in `records'
  from /gems_path/activerecord-5.2.0/lib/active_record/relation/delegation.rb:41:in `[]'
导致错误的代码如下所示:

class Post
  has_many :comments

  has_one :last_comment, -> {
    joins("LEFT JOIN posts on posts.id = comments.post_id")
    .where("
      comments.id = (
        SELECT MAX(comments.id) FROM comments
        WHERE comments.post_id = posts.id
      )"
    )
  }, class_name: "Comment"

  scope :with_last_comment, -> { joins(:last_comment) }
end
class Post < ApplicationRecord
  has_many :comments, dependent: :destroy

  has_one :last_comment, -> {
    joins(:post)                               # <--- Note this change
    .where("
      comments.id = (
        SELECT MAX(comments.id) FROM comments
        WHERE comments.post_id = posts.id
      )"
    )
  }, class_name: "Comment"

  scope :with_last_comment, -> { joins(:last_comment) }
end
我创建了一个包含完整代码的程序,它有助于重现bug。下载
issue_with_joins_in_scopes_in_rails_5_3.rb
到您的电脑,并使用

ruby issue_with_joins_in_scopes_in_rails_5_3.rb
您可以查看更多详细信息

Rails 5.2和5.1中的连接有什么区别,导致代码
Post.with_last_comment
在Rails 5.2中出错而失败


如何更改帖子模型中的
last\u comment
关联和
与\u last\u comment
范围,使其在Rails 5.2中工作?

发布关于如何为帖子集合预加载last comment的部分解决方案

首先,您需要有以下
last_comment
关联:

class Post < ApplicationRecord
  has_many :comments, dependent: :destroy

  has_one :last_comment, -> { order(id: :desc) }, class_name: "Comment"
end
此解决方案的问题在于,当我使用
联接时,它会忽略关联范围并生成以下SQL查询:

Post.joins(:last_comment)

Post Load (0.2ms)  SELECT  "posts".* FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" LIMIT ?  [["LIMIT", 11]]
我可以通过以下方式更改原始的
last_comment
关联来解决此问题:

class Post
  has_many :comments

  has_one :last_comment, -> {
    joins("LEFT JOIN posts on posts.id = comments.post_id")
    .where("
      comments.id = (
        SELECT MAX(comments.id) FROM comments
        WHERE comments.post_id = posts.id
      )"
    )
  }, class_name: "Comment"

  scope :with_last_comment, -> { joins(:last_comment) }
end
class Post < ApplicationRecord
  has_many :comments, dependent: :destroy

  has_one :last_comment, -> {
    joins(:post)                               # <--- Note this change
    .where("
      comments.id = (
        SELECT MAX(comments.id) FROM comments
        WHERE comments.post_id = posts.id
      )"
    )
  }, class_name: "Comment"

  scope :with_last_comment, -> { joins(:last_comment) }
end
关于Rails 5.2中的连接与Rails 5.1中的连接如何不同的问题仍然悬而未决