mincer 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mincer/base.rb +4 -4
- data/lib/mincer/processors/helpers.rb +1 -0
- data/lib/mincer/processors/pg_search/sanitizer.rb +16 -4
- data/lib/mincer/processors/pg_search/search_engines/base.rb +5 -0
- data/lib/mincer/processors/pg_search/search_engines/fulltext.rb +2 -2
- data/lib/mincer/version.rb +1 -1
- data/mincer.gemspec +1 -1
- data/spec/lib/mincer/processors/pg_search/search_engines/array_spec.rb +6 -6
- data/spec/lib/mincer/processors/pg_search/search_engines/fulltext_spec.rb +2 -2
- data/spec/lib/mincer/processors/pg_search/search_engines/trigram_spec.rb +2 -2
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c74759caf1e6c25531831b8826956f646100c748
|
4
|
+
data.tar.gz: 9aeaeef5b0179d8a5ac4abf8eaedd685babab45b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5a0292afa6da4666085e69d7300aa8c1767a7a622d8152c52586384529dc5d14390008b967bd2f39774636b60e0deb6156f3a50e63db6f77341d916f561f165
|
7
|
+
data.tar.gz: f9a42a835a506a4d36894f4ac8d42c232fd31672e09479080b1f2f0aa2316fd6a899448d80b813b0e3336c7038384809893e66fa0882cd8a06ab73fbb22fb099
|
data/lib/mincer/base.rb
CHANGED
@@ -27,10 +27,10 @@ module Mincer
|
|
27
27
|
# Allows enumerable methods to be called directly on object
|
28
28
|
def each(&block)
|
29
29
|
@collection ||= if @relation.is_a?(ActiveRecord::Relation)
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
@relation.to_a
|
31
|
+
else
|
32
|
+
@relation.all
|
33
|
+
end
|
34
34
|
@collection.each(&block)
|
35
35
|
end
|
36
36
|
|
@@ -3,6 +3,7 @@ module Mincer
|
|
3
3
|
module Helpers
|
4
4
|
|
5
5
|
def join_expressions(expressions, join_with)
|
6
|
+
return expressions.first if expressions.size < 2
|
6
7
|
case join_with
|
7
8
|
when :and then Arel::Nodes::And.new(expressions)
|
8
9
|
when :or then expressions.inject { |accumulator, expression| Arel::Nodes::Or.new(accumulator, expression) }
|
@@ -15,7 +15,11 @@ module Mincer
|
|
15
15
|
|
16
16
|
def sanitize_string(options = {})
|
17
17
|
if sanitizers.empty?
|
18
|
-
|
18
|
+
if defined?(Arel::Nodes::Quoted)
|
19
|
+
return self.class.quote(@term)
|
20
|
+
elsif options[:quote]
|
21
|
+
return Mincer.connection.quote(@term)
|
22
|
+
end
|
19
23
|
end
|
20
24
|
@sanitized_string ||= sanitize(@term)
|
21
25
|
end
|
@@ -40,21 +44,29 @@ module Mincer
|
|
40
44
|
end
|
41
45
|
|
42
46
|
def self.ignore_case(term)
|
43
|
-
Arel::Nodes::NamedFunction.new('lower', [term])
|
47
|
+
Arel::Nodes::NamedFunction.new('lower', [quote(term)])
|
44
48
|
end
|
45
49
|
|
46
50
|
def self.ignore_accent(term)
|
47
|
-
Arel::Nodes::NamedFunction.new('unaccent', [term])
|
51
|
+
Arel::Nodes::NamedFunction.new('unaccent', [quote(term)])
|
48
52
|
end
|
49
53
|
|
50
54
|
def self.coalesce(term, val = '')
|
51
55
|
if Mincer.pg_extension_installed?(:unaccent)
|
52
|
-
Arel::Nodes::NamedFunction.new('coalesce', [term, val])
|
56
|
+
Arel::Nodes::NamedFunction.new('coalesce', [quote(term), quote(val)])
|
53
57
|
else
|
54
58
|
term
|
55
59
|
end
|
56
60
|
end
|
57
61
|
|
62
|
+
def self.quote(string)
|
63
|
+
if defined?(Arel::Nodes::Quoted) && !string.is_a?(Arel::Nodes::Quoted) && !string.is_a?(Arel::Nodes::NamedFunction)
|
64
|
+
Arel::Nodes::Quoted.new(string)
|
65
|
+
else
|
66
|
+
string
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
58
70
|
end
|
59
71
|
end
|
60
72
|
end
|
@@ -12,6 +12,7 @@ module Mincer
|
|
12
12
|
def arel_group(sql_string = nil)
|
13
13
|
sql_string = yield if block_given?
|
14
14
|
arel_query = sql_string.is_a?(String) ? Arel.sql(sql_string) : sql_string
|
15
|
+
return arel_query if arel_query.is_a?(Arel::Nodes::Grouping)
|
15
16
|
Arel::Nodes::Grouping.new(arel_query)
|
16
17
|
end
|
17
18
|
|
@@ -50,6 +51,10 @@ module Mincer
|
|
50
51
|
nil
|
51
52
|
end
|
52
53
|
|
54
|
+
def quote(string)
|
55
|
+
Mincer::Processors::PgSearch::Sanitizer.quote(string)
|
56
|
+
end
|
57
|
+
|
53
58
|
end
|
54
59
|
end
|
55
60
|
end
|
@@ -47,14 +47,14 @@ module Mincer
|
|
47
47
|
# sanitizers += [:coalesce] if (search_statement.columns.size > 1)
|
48
48
|
documents = search_statement.columns.map do |search_column|
|
49
49
|
sanitized_term = sanitize_column(search_column, sanitizers)
|
50
|
-
ts_vector = Arel::Nodes::NamedFunction.new('to_tsvector', [search_statement.dictionary, sanitized_term])
|
50
|
+
ts_vector = Arel::Nodes::NamedFunction.new('to_tsvector', [quote(search_statement.dictionary), sanitized_term])
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
54
|
def ts_query_for(search_statement)
|
55
55
|
terms_delimiter = search_statement.options[:any_word] ? '|' : '&'
|
56
56
|
tsquery_sql = Arel.sql(search_statement.terms.map { |term| sanitize_string_quoted(term, search_statement.sanitizers(:query)).to_sql }.join(" || ' #{terms_delimiter} ' || "))
|
57
|
-
Arel::Nodes::NamedFunction.new('to_tsquery', [search_statement.dictionary, tsquery_sql])
|
57
|
+
Arel::Nodes::NamedFunction.new('to_tsquery', [quote(search_statement.dictionary), tsquery_sql])
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
data/lib/mincer/version.rb
CHANGED
data/mincer.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_dependency 'activerecord', '
|
21
|
+
spec.add_dependency 'activerecord', '= 4.2'
|
22
22
|
|
23
23
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
24
24
|
spec.add_development_dependency 'rake'
|
@@ -31,38 +31,38 @@ describe ::Mincer::PgSearch::SearchEngines::Array do
|
|
31
31
|
it 'generates search condition with one column, one term and no options' do
|
32
32
|
search_statement1 = search_statement_class.new(['"records"."text"'], engines: [:array])
|
33
33
|
search_engine = search_engine_class.new({ pattern: 'search' }, [search_statement1])
|
34
|
-
search_engine.conditions.to_sql.should == %{((
|
34
|
+
search_engine.conditions.to_sql.should == %{(("records"."text"::text[]) @> ARRAY['search'])}
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'generates search condition with two columns, one term and no options' do
|
38
38
|
search_statement1 = search_statement_class.new(['"records"."text"', '"records"."text2"'], engines: [:array])
|
39
39
|
search_engine = search_engine_class.new({ pattern: 'search' }, [search_statement1])
|
40
|
-
search_engine.conditions.to_sql.should == %{((
|
40
|
+
search_engine.conditions.to_sql.should == %{(("records"."text"::text[] || "records"."text2"::text[]) @> ARRAY['search'])}
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'generates search condition with two columns, two terms and no options' do
|
44
44
|
search_statement1 = search_statement_class.new(['"records"."text"', '"records"."text2"'], engines: [:array])
|
45
45
|
search_engine = search_engine_class.new({ pattern: 'search word' }, [search_statement1])
|
46
|
-
search_engine.conditions.to_sql.should == %{((
|
46
|
+
search_engine.conditions.to_sql.should == %{(("records"."text"::text[] || "records"."text2"::text[]) @> ARRAY['search','word'])}
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'generates search condition with two columns, two terms and option "ignore_accent" set to true ' do
|
50
50
|
search_statement1 = search_statement_class.new(['"records"."text"', '"records"."text2"'], engines: [:array], ignore_accent: true)
|
51
51
|
search_engine = search_engine_class.new({ pattern: 'search word' }, [search_statement1])
|
52
|
-
search_engine.conditions.to_sql.should == %{((
|
52
|
+
search_engine.conditions.to_sql.should == %{(("records"."text"::text[] || "records"."text2"::text[]) @> ARRAY[unaccent('search'),unaccent('word')])}
|
53
53
|
end
|
54
54
|
|
55
55
|
#TODO: sanitizer can not be set on array columns since we ned to unpack an reconstruct those arrays. Find a solution
|
56
56
|
it 'generates search condition with two columns, two terms and option "any_word" set to true ' do
|
57
57
|
search_statement1 = search_statement_class.new(['"records"."text"', '"records"."text2"'], engines: [:array], any_word: true)
|
58
58
|
search_engine = search_engine_class.new({ pattern: 'search word' }, [search_statement1])
|
59
|
-
search_engine.conditions.to_sql.should == %{((
|
59
|
+
search_engine.conditions.to_sql.should == %{(("records"."text"::text[] || "records"."text2"::text[]) && ARRAY['search','word'])}
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'generates search condition with two columns, two terms and option "ignore_accent" and "ignore_case" set to true ' do
|
63
63
|
search_statement1 = search_statement_class.new(['"records"."text"', '"records"."text2"'], engines: [:array], ignore_accent: true, ignore_case: true)
|
64
64
|
search_engine = search_engine_class.new({ pattern: 'search word' }, [search_statement1])
|
65
|
-
search_engine.conditions.to_sql.should == %{((
|
65
|
+
search_engine.conditions.to_sql.should == %{(("records"."text"::text[] || "records"."text2"::text[]) @> ARRAY[unaccent(lower('search')),unaccent(lower('word'))])}
|
66
66
|
end
|
67
67
|
|
68
68
|
it 'generates search condition with one column, one term, two statements and no options' do
|
@@ -33,7 +33,7 @@ describe ::Mincer::PgSearch::SearchEngines::Fulltext do
|
|
33
33
|
it 'generates search condition with one column, one term and no options without columns wrapped with coalesce' do
|
34
34
|
search_statement1 = search_statement_class.new(['"records"."text"'], engines: [:fulltext])
|
35
35
|
search_engine = search_engine_class.new({ pattern: 'search' }, [search_statement1])
|
36
|
-
search_engine.conditions.to_sql.should == %{(
|
36
|
+
search_engine.conditions.to_sql.should == %{(to_tsvector('simple', "records"."text") @@ to_tsquery('simple', 'search'))}
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -86,7 +86,7 @@ describe ::Mincer::PgSearch::SearchEngines::Fulltext do
|
|
86
86
|
it 'generates search condition with one column, one term and option "dictionary" set to :english' do
|
87
87
|
search_statement1 = search_statement_class.new(['"records"."text"'], engines: [:fulltext], dictionary: :english)
|
88
88
|
search_engine = search_engine_class.new({ pattern: 'search' }, [search_statement1])
|
89
|
-
search_engine.conditions.to_sql.should == %{(
|
89
|
+
search_engine.conditions.to_sql.should == %{(to_tsvector('english', "records"."text") @@ to_tsquery('english', 'search'))}
|
90
90
|
end
|
91
91
|
|
92
92
|
it 'generates search condition with two search statements one column, one term and no options' do
|
@@ -31,13 +31,13 @@ describe ::Mincer::PgSearch::SearchEngines::Trigram do
|
|
31
31
|
it 'generates search condition with one column, one term and no options' do
|
32
32
|
search_statement1 = search_statement_class.new(['"records"."text"'], engines: [:trigram])
|
33
33
|
search_engine = search_engine_class.new({ pattern: 'search' }, [search_statement1])
|
34
|
-
search_engine.conditions.to_sql.should == %{(
|
34
|
+
search_engine.conditions.to_sql.should == %{("records"."text" % 'search')}
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'generates search condition with one column, one term and "threshold" option set to 0.5' do
|
38
38
|
search_statement1 = search_statement_class.new(['"records"."text"'], engines: [:trigram], threshold: 0.5)
|
39
39
|
search_engine = search_engine_class.new({ pattern: 'search' }, [search_statement1])
|
40
|
-
search_engine.conditions.to_sql.should == %{(
|
40
|
+
search_engine.conditions.to_sql.should == %{(similarity("records"."text", 'search') >= 0.5)}
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'generates search condition with two columns, one term and no options' do
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mincer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Krasinsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '4.
|
19
|
+
version: '4.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '4.
|
26
|
+
version: '4.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|