ruby-on-rails 查询结果为`Model::ActiveRecord_Relation`,如何调用ActiveRecord方法(例如在哪里?

hyrbngr7  于 2023-06-25  发布在  Ruby
关注(0)|答案(1)|浏览(158)

我很难理解为什么我不能在看起来像是ActiveRecord查询的结果上调用.where
我将深入了解SQL,创建用于匹配的虚拟列。我们有两种型号:OrganizationSubscription。我的查询获取具有订阅的组织如下:

def orgs_with_plans
  subquery = Subscription.select("DISTINCT ON (organization_id) *")
    .order(:organization_id, created_at: :desc)

  Organization
    .joins("LEFT JOIN (#{subquery.to_sql}) AS subscription_data ON organizations.id = subscription_data.organization_id")
    .select("
      organizations.*,
      (CASE
        WHEN subscription_data.id IS NULL THEN
          (CASE
            WHEN organizations.trial_end_date > CURRENT_DATE THEN 'trial'
            ELSE 'expired'
          END)
        ELSE subscription_data.plan_name
      END) AS plan_name
    ")
end

我可以成功地得到plan_name,当我调用以下命令:

orgs_with_plans.each do |org|
  puts "orgname: #{org.name}, plan name: #{org.plan_name}"
end

此外,orgs_with_plans.to_sql的输出sql在我的数据库中按预期运行。
如果我尝试调用orgs_with_plans.where('plan_name = ?', 'trial'),我会遇到一个错误:

ActiveRecord::StatementInvalid:
  PG::SyntaxError: ERROR:  syntax error at or near "AS"
  LINE 10:         END) AS plan_name

为什么当我使用count时,这种语法无效,但在其他情况下却完全正常?

lhcgjxsq

lhcgjxsq1#

无法直接调用ActiveRecord方法(如. count)对orgs_with_plans查询结果的原因是,orgs_with_plans不是记录数组,而是ActiveRecord_Relation的示例。但是,您仍然可以通过将其转换为数组或在查询的末尾链接所需的方法来对其应用ActiveRecord方法。
要获取具有特定计划名称的组织的计数,您可以按如下方式修改查询:

orgs_with_plans.where(plan_name: 'trial').count

这将在查询中添加一个条件,以筛选计划名称为“trial”的组织,然后返回计数。
关于使用. where('plan_name =?',' trial '),问题在于生成的SQL语句的语法。在LEFT JOIN子句中使用的子查询有一个名为plan_name的别名列,这导致了错误。要解决此问题,可以修改查询以在WHERE子句中使用列索引而不是别名:

orgs_with_plans.where('CASE WHEN subscription_data.id IS NULL THEN (CASE WHEN organizations.trial_end_date > CURRENT_DATE THEN ? ELSE ? END) ELSE subscription_data.plan_name END = ?', 'trial', 'expired', 'trial')

在这个修改后的查询中,CASE语句在WHERE子句中重复,而占位符?分别用于传递值'trial'、'expired'和'trial'。
请记住根据您的特定用例调整占位符和值。
通过进行这些修改,您应该能够使用. count方法并将附加条件应用于orgs_with_plans查询结果。

相关问题