postgres数组字段上的ActiveAdmin过滤器

kas*_*hif 7 ruby rubygems ruby-on-rails activeadmin ruby-on-rails-4

我在ActiveAdmin中添加了以下过滤器.

filter :roles, as: :select, collection Model::ROLES, multiple: true
Run Code Online (Sandbox Code Playgroud)

但是当我选择过滤器值来搜索角色时.它给了我以下错误

PG::InvalidTextRepresentation: ERROR:  malformed array literal: "teacher"LINE 1: ...ted" = $1 AND roles" IN('teacher
DETAIL:  Array value must start with "{" or dimension information.                                                             ^
Run Code Online (Sandbox Code Playgroud)

任何的想法 ?我们如何使用AA过滤器搜索/过滤ARRAY字段?我正在使用Rails 4.2.4,ruby 2.2.2p95

lea*_*ico 4

我想出了一个与这里略有不同(并受到启发)的解决方案:/sf/answers/3200960311/

我的涉及一些更改(并防止contains在其他情况下破坏运算符)。因此,您基本上将创建两个初始化程序文件:

这个是针对 Arel 的,为了支持@>给定表列的运算符(PG 中数组的包含运算符)。

# config/initializers/arel.rb

module Arel
  class Nodes::ContainsArray < Arel::Nodes::Binary
    def operator
      :"@>"
    end
  end

  class Visitors::PostgreSQL
    private

    def visit_Arel_Nodes_ContainsArray(o, collector)
      infix_value o, collector, ' @> '
    end
  end

  module Predications
    def contains(other)
      Nodes::ContainsArray.new self, Nodes.build_quoted(other, self)
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

另一个文件旨在创建一个新的 Ransack 谓词,但我也决定支持该:array类型(就谓词而言,Ransack 本身不支持该类型)。

# config/initializers/ransack.rb

module Ransack
  module Nodes
    class Value < Node
      alias_method :original_cast, :cast

      def cast(type)
        return Array(value) if type == :array
        original_cast(type)
      end
    end
  end
end

Ransack.configure do |config|
  config.add_predicate 'contains_array',
    arel_predicate: 'contains',
    formatter: proc { |v| "{#{v.join(',')}}" },
    validator: proc { |v| v.present? },
    type: :array
end
Run Code Online (Sandbox Code Playgroud)

并在其他方面使用它。您需要做的就是:

User.ransack(roles_contains_array: %i[admin manager])
Run Code Online (Sandbox Code Playgroud)

或者作为 ActiveAdmin 中的过滤器(这是我的情况):

ActiveAdmin.register User do
  # ...
  filter :roles_contains_array, as: :select, collection: User.roles_for_select
  # ...
end
Run Code Online (Sandbox Code Playgroud)

我希望它对你有用,就像它对我有用一样。;)