【问题标题】:How to combine two activerecord relations如何组合两个活动记录关系
【发布时间】:2021-02-22 12:56:59
【问题描述】:

我有模型UserUser 有列provider

提供者可以是googlefacebooknil

我想创建范围,它将输出所有用户,除了提供者 google 和比 some time 更早的用户。

我尝试使用两个范围:

scope :not_google_authorised, -> { where(provider: [nil, 'facebook']) }
scope :newest_google, -> { where(provider: 'google').where("created_at < ?", Time.now)}
...
users = User.not_google_authorised
users << User.newest_google

它得到了正确的结果,但它改变了users 的类。 我需要users 将是活动记录关系,而不是数组。 我试过了:

users = User.not_google_authorised
users.merge(User.newest_google)
#or
users.or(User.newest_google)

但这对我不起作用。

我怎样才能结合这 2 个作用域,所以 users 将是 activerecord 关系,或者我怎样才能写一个作用域而不是他们的?

我使用 ruby​​ v3.3.7 和 rails v4.1

【问题讨论】:

  • 您可以尝试在 where 中组合查询。 User.where("provider IN (?) OR (provider = ? AND created_at &gt; ?)", [nil, 'facebook'], 'google', Time.now)这只是一个草稿,但希望能有所帮助:D

标签: ruby-on-rails rails-activerecord


【解决方案1】:

ActiveRecord::QueryMethods#or 在 Rails 5 之前不存在。

此外,当前稳定的 ruby​​ 版本是 3.0.0,这意味着您不能使用 3.3.7,因为它还不存在(并且可能永远不会存在)。

merge 将使用AND(交集)合并。

所以最好的办法是使用原始 SQL where 或 Arel 之类的:

where(
  User.arel_table[:provider].eq(nil).or(
    User.arel_table[:provider].eq('facebook')
  ).or(
    User.arel_table[:provider].eq('google').and(
      User.arel_table[:created_at].lt(Time.now)
    )
  )
)

这应该会导致:

SELECT 
  "users".*
FROM 
  "users" 
WHERE 
  ("users"."provider" IS NULL OR "users"."provider" = 'facebook')
   OR ( "users"."provider" = 'google' AND "users"."created_at" < [SOME TIME]

【讨论】:

    【解决方案2】:

    一种方法是这样做,不是超级优化但可以完成工作。

    not_google_auth_ids = User.not_google_authorized.ids
    newest_ids = User.newest_google.ids
    ids = not_google_auth_ids + newest_ids
    
    users = User.where(id: ids)
    

    【讨论】:

      【解决方案3】:

      我们可以这样在一个范围内正确:

      范围 :not_authorised, -> { where("(provider = ? and created_at

      【讨论】:

      • != 在这里不起作用,因为它不会显示 NULL 值。 NULL 不具有可比性,因此它既不等于“google”也不等于“google”(NULL 甚至不等于 NULL
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多