SQL 语句在 PGAdmin 中有效,但在转换为 Arel 后在应用程序中无效

SQL statement works in PGAdmin, but not in app after transposing to Arel

我在 PGAdmin 中写了这个 sql 语句,它按预期提取数据。

SELECT Sum(timerecords.manual_input_hours)           AS hours,
       To_date(timerecords.time_start, 'YYYY-MM-DD') AS date,
       tasks.title,
       timerecords.client_id
FROM   timerecords
       INNER JOIN tasks
               ON tasks.id = timerecords.task_id
WHERE  timerecords.client_id = '15'
GROUP  BY To_date(timerecords.time_start, 'YYYY-MM-DD'),
          timerecords.task_id,
          timerecords.client_id,
          tasks.title
ORDER  BY date DESC 

我然后运行 sql 语句 scuttle.io 到 t运行sform 到 Arel

Timerecord.select(
  [
    Arel::Nodes::NamedFunction.new(
      'SUM', [Timerecord.arel_table[:manual_input_hours]]
    ).as('hours'), Arel::Nodes::NamedFunction.new(
      'TO_DATE', [Timerecord.arel_table[:time_start], 'YYYY-MM-DD']
    ).as('date'), Task.arel_table[:title], Timerecord.arel_table[:client_id]
  ]
).where(Timerecord.arel_table[:client_id].eq('15')).joins(
  Timerecord.arel_table.join(Task.arel_table).on(
    Task.arel_table[:id].eq(Timerecord.arel_table[:task_id])
  ).join_sources
).order(:date).reverse_order.group(
  Arel::Nodes::NamedFunction.new(
    'TO_DATE', [Timerecord.arel_table[:time_start], 'YYYY-MM-DD']
  ), Timerecord.arel_table[:task_id], Timerecord.arel_table[:client_id], Task.arel_table[:title]
)

当我调用@tasks.each.do(在那一行)时,我得到了这个错误,但没有其他信息。

Arel::Visitors::UnsupportedVisitError in Agency::Clientmanagement#show
Unsupported argument type: String. Construct an Arel node instead.

我从研究中尝试了一些项目.. 而不是 to_date,我尝试了 to_char。我还将开发数据库从 sqllite3 更改为 postgresql 以匹配生产服务器。

您必须使用 Arel::Nodes.build_quoted 来转换您的日期格式。

尝试

Timerecord.select(
  [
    Arel::Nodes::NamedFunction.new(
      'SUM', [Timerecord.arel_table[:manual_input_hours]]
    ).as('hours'), 
    Arel::Nodes::NamedFunction.new('TO_DATE',
     [Timerecord.arel_table[:time_start], Arel::Nodes.build_quoted('YYYY-MM-DD')]
    ).as('date'), 
    Task.arel_table[:title], 
    Timerecord.arel_table[:client_id]
  ]
).where(Timerecord.arel_table[:client_id].eq('15')).joins(
  Timerecord.arel_table.join(Task.arel_table).on(
    Task.arel_table[:id].eq(Timerecord.arel_table[:task_id])
  ).join_sources
).order(:date).reverse_order.group(
 :date, 
 Timerecord.arel_table[:task_id], 
 Timerecord.arel_table[:client_id], 
 Task.arel_table[:title]
)

生成的代码非常复杂,因为它使用 Arel 来处理使用 ActiveRecord 查询接口很容易做到的事情:

tbl = Timerecord.arel_table
date_fn = Arel::Nodes::NamedFunction.new(
  'TO_DATE', [tbl[:time_start], Arel::Nodes.build_quoted('YYYY-MM-DD')]
)

Timerecord.select(
  tbl[:manual_input_hours].sum.as('hours'), # you don't need to define the function
  date_fn.as('date'), 
  Task.arel_table[:title].as('title')
  :client_id
)  
  .where(client_id: '15')
  .joins(:tasks)
  .order(date: :desc)
  .group(
     :date, :task_id, :client_id, :title
  )