2016-07-16 4 views
1

난 레일 응용 프로그램에서 검색을 위해 ransack gem을 사용하고 있습니다. 테이블에서 email_ids의 배열을 검색해야합니다. 습격에서 this 문제 참조ransack gem을 통해 배열을 검색하는 방법은 무엇입니까?

, 전 단계를 수행하고이 같은 않으면 레일 콘솔에서 초기화 폴더 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')" 

이 같은 rror : 잘못된 내가 뭘한다

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

: 예상

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] 
') 

이 쿼리입니까?

답변

0

나는 당신과 같은 문제를 만났습니다. 나는 레일 (5) 사용하고, 나는 User 테이블

roles의 배열을 검색해야 이미 gemfile에 postgres_ext gem을 추가 할 것 같다,하지만 당신은 레일 5 응용 프로그램에서 사용하는 경우 몇 가지 문제가있다. 당신은 자신에 의해 Arel 노드에서 contain 쿼리를 추가하는 대신 postgres_ext gem

를 사용하여 그리고 당신은 레일의 다른 버전을 사용하는 경우, 내가 너무 잘 작동 생각하는

그래서 그것은 선택이 될 것입니다.

나는 User 모델이고 배열 속성은 roles입니다. 내가 원하는 것은 ransack을 사용하여 roles을 검색하는 것입니다. 너와 같은 조건이야.

ransack 배열을 검색 할 수 없습니다. 그러나 PostgresSQL은 다음과 같이 배열을 검색 할 수 있습니다 Arel Nodes

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

그래서 내가하고 싶은 것은 비슷한 추가하는 쿼리가 포함되어

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

가이 같은 SQL 쿼리를 생성

할 수 있습니다 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 
01 사용자 정의 술어를 더듬다 수 있기 때문에 23,516,

, 그래서 this 같은 contains 더듬다 술어를 추가

# 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\"]}') 

그래!