Ransack,Postgres - 从关联表中对列进行排序,使用distinct:true

时间:2013-11-03 01:38:16

标签: ruby-on-rails ruby ruby-on-rails-4 rails-postgresql ransack

我有一个使用Ransack gem的应用程序,我将它从Mysql转换为Postgres。

在sort列来自关联表并且distinct选项设置为true的实例中,Postgres会抛出此错误:

PG::InvalidColumnReference: ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list

Ransack github页面说,在这种情况下,“你是靠自己。”

什么是最好的 - 任何! - 处理这种情况的策略?

q = Contact.includes(:contact_type).search
q.sorts = ['contact_type_name asc']
q.result(distinct: true)
PG::InvalidColumnReference: ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list

谢谢!

2 个答案:

答案 0 :(得分:5)

有一种更简单的方法可以解决这个问题。使用ActiveRecord连接查询或选择查询以添加所需的列,例如:

q = Contact.search
q.sorts = ['contact_type_name asc']
q.result(distinct: true).
  includes(:contact_type).
  joins(:contact_type)

或者,如果您只想选择几列,则可以执行以下操作:

q = Contact.search
q.sorts = ['contact_type_name asc']
q.result(distinct: true).
  select('contacts.*, contact_type.name')

我已经完成了pull request来更新Ransack的自述文件。

答案 1 :(得分:3)

我刚刚面临同样的问题,并且对单列排序有用的快速而又脏的修复方法是添加初始化程序,如下所示。这个猴子补丁将缺少的排序列添加到select语句中。

module Ransack
  module Adapters
    module ActiveRecord
      class Context < ::Ransack::Context
        def evaluate(search, opts = {})
          viz = Visitor.new
          relation = @object.where(viz.accept(search.base))
          if search.sorts.any?
            _vaccept = viz.accept(search.sorts)
            table  = _vaccept.first.expr.relation.name
            column = _vaccept.first.expr.name
            relation = relation.except(:order).reorder(_vaccept).select("#{@default_table.name}.*, #{table}.#{column}")
          end
          opts[:distinct] ? relation.distinct : relation
        end
      end
    end
  end
end