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

ric*_*ock 7 ruby ruby-on-rails rails-postgresql ransack ruby-on-rails-4

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

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

PG::InvalidColumnReference: ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

谢谢!

小智 5

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

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

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

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

我已经做了拉取请求来更新Ransack的自述文件.


Ere*_*CAY 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
Run Code Online (Sandbox Code Playgroud)