mincer 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|