Rails ActiveRecord Arels:不支持的参数类型:String。而是构造一个Arel节点

时间:2016-12-20 15:57:26

标签: sql ruby-on-rails ruby activerecord generate-series

我正在使用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

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

2 个答案:

答案 0 :(得分:5)

您的上一个参数应为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') 

答案 1 :(得分:3)

您可以使用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时那样记住包含和手动转义引号。