Rails ActiveRecord Arels:不支持的参数类型:字符串。改为构造一个 Arel 节点

Posted

技术标签:

【中文标题】Rails ActiveRecord Arels:不支持的参数类型:字符串。改为构造一个 Arel 节点【英文标题】:Rails ActiveRecord Arels: Unsupported argument type: String. Construct an Arel node instead 【发布时间】:2017-05-05 21:49:01 【问题描述】:

我使用Arels 来创建查询。在这个查询中,我使用generate_series 函数。这是我的代码:

    def generate_series
      Arel::Nodes::NamedFunction.new('GENERATE_SERIES', [start_date, end_day, '1 day'])
    end

def start_date
      Arel::Nodes::SqlLiteral.new(<<-SQL
         CASE WHEN DATE_PART('hour', NOW() AT TIME ZONE 'ICT') < #Time.now - 3days THEN (CURRENT_DATE - INTERVAL '14 days') ELSE (CURRENT_DATE - INTERVAL '13 days') END
      SQL
      )
    end

    def end_date
      Arel::Nodes::SqlLiteral.new(<<-SQL
         CASE WHEN DATE_PART('hour', NOW() AT TIME ZONE 'ICT') < #Time.now THEN (CURRENT_DATE - INTERVAL '1 day') ELSE CURRENT_DATE END
      SQL
      )
    end

当我尝试通过generate_series.to_sql 进行测试时。我遇到异常:

Arel::Visitors::UnsupportedVisitError:不支持的参数类型: 细绳。而是构建一个 Arel 节点。

我尝试缩短我的测试代码:

def generate_series
      Arel::Nodes::NamedFunction.new('GENERATE_SERIES', ['19/11/2012', '20/11/2012', '1 day'])
 end

问题是一样的。请告诉我如何解决这个问题。

【问题讨论】:

【参考方案1】:

您可以使用Arel::Nodes.build_quoted 来引用文字:

def generate_series
      Arel::Nodes::NamedFunction.new('GENERATE_SERIES', 
             [start_date, end_date, Arel::Nodes.build_quoted('1 day')]
      )
end

这样做的好处是您不必像使用 Arel::Nodes::SqlLiteral 那样记住包含和手动转义引号。

【讨论】:

【参考方案2】:

您的最后一个参数应该是Arel::Nodes。所以你应该将1 day 包装成Arel::Nodes:SqlLiteral。这是更新的代码:

def generate_series
      Arel::Nodes::NamedFunction.new('GENERATE_SERIES', 
             [start_date, end_date, Arel::Nodes::SqlLiteral.new('\'1 day\'')]
      )
end

请注意,您还必须将 1 day 包含在(单)引号内,即:'1 day'。因为如果你不这样做,生成的查询将是:

GENERATE_SERIES(start, stop, 1 day) 

但真正的查询应该是:

GENERATE_SERIES(start, stop, '1 day') 

【讨论】:

以上是关于Rails ActiveRecord Arels:不支持的参数类型:字符串。改为构造一个 Arel 节点的主要内容,如果未能解决你的问题,请参考以下文章

禁用 Rails 4 的 ActiveRecord

Rails 3 包括翻译 globalize3 activerecord

脱离Rails单独使用ActiveRecord的几点需知

没有Rails的ActiveRecord

Rails/Arel:选择所有记录作为 ActiveRecord::Relation

为啥 Rails 5 使用 ApplicationRecord 而不是 ActiveRecord::Base?