【问题标题】:rails ActiveRecord can you merge scopes that have joins within them?rails ActiveRecord 你可以合并其中有连接的范围吗?
【发布时间】:2016-12-01 14:28:59
【问题描述】:

我想将单个表连接到具有特定范围的另一个表。

我尝试过的操作不起作用,但使用子选择的版本可以正常工作。

MyModelbelongs_toUser 类(其中has_oneMyModel),并且用户类的范围涉及到其他表的连接。

我想做的是:

# doesn't work, gives user that is not inside the merged scope
MyModel.joins(:user).merge(User.has_accounts)

这会生成以下 SQL,我认为应该做我想做的事:

SELECT DISTINCT "my_model".* FROM
"my_model" INNER JOIN "users" ON "users"."id" = 
"my_model"."user_id" LEFT OUTER JOIN "logins" ON 
"logins"."user_id" = "users"."id" LEFT OUTER JOIN "logins" 
"logins_users_join" ON "logins_users_join"."user_id" = "users"."id" 
LEFT OUTER JOIN "accounts" ON "accounts"."login_id" = 
"logins_users_join"."id"

用户范围“has_accounts”内部有一些连接:

scope :has_accounts, -> { joins(:logins).joins(:accounts).distinct }

我可以使用这样的子选择正确编写查询:

# works does not give my_model that has a user associated that is not in the scope
MyModel.where(user_id: User.has_accounts.select(:id))

模型的相关部分如下:

class MyModel
  belongs_to :user
end

class User
  has_one :my_model
  has_many :logins
  has_many :accounts, through: :logins
  scope :has_accounts, -> { joins(:logins).joins(:accounts).distinct }
end

class Login
  belongs_to :user
  has_many :accounts
end

class Account
  belongs_to :login
end

我的 joinmerge 做错了什么,导致它没有给出正确的结果?

任何人都可以看到生成的SQL 中的内容,这意味着结果中存在没有关联帐户的用户吗?

【问题讨论】:

  • has_accounts 更改为scope :has_accounts, -> { joins(:logins).joins(:accounts).group('users.id') 会使MyModel.joins(:user).merge(User.has_accounts) 产生预期结果吗?
  • @AndreyDeineko 不,它似乎没有。它还更改了依赖于范围的现有查询的语义。不过感谢您的建议。
  • 请用用户登录名和帐户之间的关联编辑问题(我假设用户有一个帐户有多个登录名?)
  • @AndreyDeineko 当然,我会将它们添加到问题中。实际上是相反的,一个用户有多个登录,每个登录可以有多个帐户。
  • 你不需要has_accounts 中的joins - joins(:logins).distinct 应该足够了 - .joins(:accounts) 是多余的(因为through 关联)。

标签: ruby-on-rails ruby activerecord


【解决方案1】:

在深入研究了一段时间后,它似乎是 activerecord 中的一个错误。本期提到:

https://github.com/rails/rails/issues/16140

并且暗示这是由于此 PR 造成的错误:

https://github.com/rails/rails/pull/26195

该错误导致在将带有联接的某些内容合并到另一个查询中时生成外部联接,而不是内部联接

【讨论】:

    猜你喜欢
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 2013-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-27
    • 1970-01-01
    相关资源
    最近更新 更多