How to search array through ransack gem?

巧了我就是萌 提交于 2019-11-30 16:48:35

I met the same problem as you do. I'm using Rails 5, and I need to search an array of roles in User table

It seems that you have already add postgres_ext gem in your gemfile, but it has some problems if you are using it in Rails 5 application.

So it is a choice for you to add a contain query in Arel Node by yourself instead of using postgres_ext gem

And if you are using other version of Rails, I think it works well too.

I have an User model, and an array attribute roles. What I want to do is to use ransack to search roles. It is the same condition like yours.

ransack can't search array. But PostgresSQL can search array like this:

User.where("roles @> ?", '{admin}').to_sql)

it produce the sql query like this:

SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND (roles @> '{admin}')

So what I want to do is to add a similar contains query in Arel Nodes

You can do it this way:

# app/config/initializers/arel.rb

require 'arel/nodes/binary'
require 'arel/predications'
require 'arel/visitors/postgresql'

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

Because you can custom ransack predicate, so add contains Ransack predicate like this:

# app/config/initializers/ransack.rb

Ransack.configure do |config|
  config.add_predicate 'contains',
    arel_predicate: 'contains',
    formatter: proc { |v| "{#{v}}" },
    validator: proc { |v| v.present? },
    type: :string
end

Done!

Now, you can search array:

User.ransack(roles_contains: 'admin')

The SQL query will be like this:

SELECT \"users\".* FROM \"users\" WHERE \"users\".\"deleted_at\" IS NULL AND (\"users\".\"roles\" @> '{[\"admin\"]}')

Yeah!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!