ruby-on-rails 按活动记录上的计算值过滤

mwyxok5s  于 2023-04-22  发布在  Ruby
关注(0)|答案(1)|浏览(119)

我是Rails新手,我有一个场景,用户可以对用户表应用几个不同的过滤器。我为每个过滤器创建了scopes,并根据过滤器是否存在将它们应用到我的查询中,如:

scope :with_age, ->(age) {
    where({age: age})
  }

  scope :with_country, ->(country_id) {
    includes(:country).where({country: {id: country_id} })
  }

现在的问题是product希望能够通过计算属性进行过滤。例如,假设他们希望通过用户生成(无论什么)进行过滤。因此我需要类似以下查询的内容:

SELECT *
FROM 
(
    SELECT *, CASE
        WHEN u2.age < 10 THEN 'Z'
        WHEN u2.age >= 10 AND u2.age <20 THEN 'MILENIALS'
        ELSE 'WHATEVER'
    END as generation
    FROM users u2
    -- here I want to apply another filters that were passed to not calculate this for the whole table
) as u1
WHERE generation = :generation_filtered

现在,有没有一种方法可以使用ActiveRecord方法来构建这个查询,这样我就可以使用我预先构建的作用域了?
谢谢!

编辑

我上面给出的例子并没有反映我实际需要的东西。很抱歉。假设用户实际上有一个基于他问了多少问题和他回答了多少回复的分数。这两个信息都存储在用户列中。所以我 * 实际 * 需要的查询应该是这样的:

SELECT *
FROM 
(
    SELECT *, CASE
        WHEN u2.questions < u2.answers THEN 'TEACHER'
        WHEN u2.questions = u2.answers THEN 'NEUTRAL'
        WHEN u2.questions > u2.answers THEN 'APPRENTICE'
    END as user_score
    FROM users u2
    -- here I want to apply another filters that were passed to not calculate this for the whole table
) as u1
WHERE user_score = :score
yfjy0ee7

yfjy0ee71#

我将通过定义每一代的年龄范围来解决这个问题,然后在范围中选择特定的年龄范围:

GENERATIONS = { 'Z' => (..10), 'MILLENNIALS' => (11...20), 'WHATEVER' => (20..) }

scope :by_generation, ->(generation) { where(age: GENERATIONS[generation]) }

然后可以像这样使用:

MyModel.by_generation('Z')

当然,这个作用域可以像这样链接:

MyModel.by_generation('Z').with_country('BR')

更新

您更新的问题中的问题可以使用相同的模式解决:

SCORE_CONDITIONS = {
  'TEACHER'    => 'users.questions < users.answers',
  'NEUTRAL'    => 'users.questions = users.answers',
  'APPRENTICE' => 'users.questions > users.answers'
}

scope by_score, ->(score) { where(SCORE_CONDITIONS[score]) }

可以这样称呼

User.by_score('TEACHER')

相关问题