2016-07-16 304 views
1

我正在使用ransack gem在rails應用程序中進行搜索。我需要在User表中搜索email_ids的數組。如何通過ransack gem搜索數組?

參考在洗劫this問題,我遵循的步驟,並已將此添加到初始化文件夾ransack.rb

Ransack.configure do |config| 
    { 
    contained_within_array: :contained_within, 
    contained_within_or_equals_array: :contained_within_or_equals, 
    contains_array: :contains, 
    contains_or_equals_array: :contains_or_equals, 
    overlap_array: :overlap 
    }.each do |rp, ap| 
    config.add_predicate rp, arel_predicate: ap, wants_array: true 
    end 
end 

在軌控制檯,如果我這樣做:

a = User.search(email_contains_array: ['[email protected]']) 

它產生sql像這樣:

"SELECT \"users\".* FROM \"users\" WHERE \"users\".\"deleted_at\" IS NULL AND (\"users\".\"email\" >> '---\n- [email protected]\n')" 

並給出e RROR這樣的:

User Load (1.8ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND ("users"."email" >> '--- 
- [email protected] 
') 
ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR: operator does not exist: character varying >> unknown 
LINE 1: ...RE "users"."deleted_at" IS NULL AND ("users"."email" >> '--- 
                  ^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. 
: SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND ("users"."email" >> '--- 
- [email protected] 
') 

預期的那樣,這個查詢:

SELECT "users".* FROM "users" WHERE ("users"."roles" @> '{"3","4"}') 

什麼是錯的我在幹嘛?

回答

0

我遇到了和你一樣的問題。我使用Rails 5,我需要尋找的roles陣列,User

看來,你已經在你的Gemfile添加postgres_ext gem,但如果你是在Rails的5應用程序中使用它有一些問題。

所以這是一個選擇,爲你自己添加在阿雷爾節點上contain查詢,而不是使用postgres_ext gem

如果你正在使用Rails的其他版本,我覺得它工作得很好了。

我有一個User模型,以及一個數組屬性roles。我想要做的是使用ransack來搜索roles。這與你的情況一樣。

ransack無法搜索數組。 但PostgresSQL可以搜索陣列像這樣:

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

它產生的SQL查詢是這樣的:

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

所以我想要做的就是添加一個類似中包含查詢在Arel Nodes

您可以做到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 

因爲你可以自定義洗劫謂語, 所以加contains洗劫謂詞像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 

完成!現在

,你可以搜索數組:

User.ransack(roles_contains: 'admin') 

的SQL查詢將是這樣的:

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

呀!