dusen 0.5.1 → 0.5.2
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.
- data/lib/dusen/parser.rb +4 -4
- data/lib/dusen/syntax.rb +18 -7
- data/lib/dusen/version.rb +1 -1
- data/spec/rails-3.0/Gemfile.lock +1 -1
- data/spec/rails-3.2/Gemfile.lock +1 -1
- data/spec/shared/app_root/app/models/user/with_fulltext.rb +6 -0
- data/spec/shared/app_root/app/models/user/without_fulltext.rb +7 -0
- data/spec/shared/spec/dusen/active_record/base_ext_spec.rb +12 -6
- metadata +69 -44
- checksums.yaml +0 -7
data/lib/dusen/parser.rb
CHANGED
@@ -5,7 +5,7 @@ module Dusen
|
|
5
5
|
|
6
6
|
WESTERNISH_WORD_CHARACTER = '\\w\\-\\.;@_ÄÖÜäöüß' # this is wrong on so many levels
|
7
7
|
TEXT_QUERY = /(?:(\-)?"([^"]+)"|(\-)?([#{WESTERNISH_WORD_CHARACTER}]+))/
|
8
|
-
FIELD_QUERY = /(\w+)\:#{TEXT_QUERY}/
|
8
|
+
FIELD_QUERY = /(\-)?(\w+)\:#{TEXT_QUERY}/
|
9
9
|
|
10
10
|
def self.parse(query_string)
|
11
11
|
query_string = query_string.dup # we are going to delete substrings in-place
|
@@ -26,9 +26,9 @@ module Dusen
|
|
26
26
|
|
27
27
|
def self.extract_field_query_tokens(query_string, query)
|
28
28
|
while query_string.sub!(FIELD_QUERY, '')
|
29
|
-
field = $
|
30
|
-
value = "#{$
|
31
|
-
exclude = "#{$
|
29
|
+
field = $2
|
30
|
+
value = "#{$4}#{$6}"
|
31
|
+
exclude = "#{$1}" == "-"
|
32
32
|
options = { :field => field, :value => value, :exclude => exclude }
|
33
33
|
query << Token.new(options)
|
34
34
|
end
|
data/lib/dusen/syntax.rb
CHANGED
@@ -64,20 +64,31 @@ module Dusen
|
|
64
64
|
def build_exclude_scope(root_scope, exclude_query)
|
65
65
|
root_scope_without_conditions = root_scope.except(:where)
|
66
66
|
exclude_scope = find_parsed_query(root_scope_without_conditions, exclude_query)
|
67
|
-
exclude_scope_conditions = exclude_scope.where_values
|
67
|
+
exclude_scope_conditions = concatenate_where_values(exclude_scope.where_values)
|
68
68
|
if exclude_scope_conditions.present?
|
69
|
-
# where_values.reduce(:and) returns a string if only one where_value given
|
70
|
-
# and a Arel::Node for more than one where_value
|
71
|
-
unless exclude_scope_conditions.is_a?(String)
|
72
|
-
exclude_scope_conditions = exclude_scope_conditions.to_sql
|
73
|
-
end
|
74
69
|
inverted_sql = "NOT COALESCE (" + exclude_scope_conditions + ",0)"
|
75
70
|
exclude_scope.except(:where).where(inverted_sql)
|
76
71
|
else
|
77
|
-
# we cannot build an inverted scope
|
72
|
+
# we cannot build an inverted scope without where-conditions
|
78
73
|
root_scope
|
79
74
|
end
|
80
75
|
end
|
81
76
|
|
77
|
+
def concatenate_where_values(where_values)
|
78
|
+
if where_values.any?
|
79
|
+
if where_values[0].is_a?(String)
|
80
|
+
first = where_values.shift
|
81
|
+
where = where_values.reduce(first) do |result, value|
|
82
|
+
result << " AND " << value
|
83
|
+
end
|
84
|
+
where
|
85
|
+
else
|
86
|
+
# where_values are AREL-Nodes
|
87
|
+
where = where_values.reduce(:and)
|
88
|
+
where.to_sql
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
82
93
|
end
|
83
94
|
end
|
data/lib/dusen/version.rb
CHANGED
data/spec/rails-3.0/Gemfile.lock
CHANGED
data/spec/rails-3.2/Gemfile.lock
CHANGED
@@ -23,6 +23,12 @@ module User
|
|
23
23
|
scope.scoped(:conditions => { :role => role })
|
24
24
|
end
|
25
25
|
|
26
|
+
search_by :name_and_city_regex do |scope, regex|
|
27
|
+
#Example for regexes that need to be and'ed together by syntax#build_exclude_scope
|
28
|
+
first = scope.where("users_with_fulltext.name REGEXP ?", regex)
|
29
|
+
second = scope.where("users_with_fulltext.city REGEXP ?", regex)
|
30
|
+
first.merge(second)
|
31
|
+
end
|
26
32
|
end
|
27
33
|
|
28
34
|
search_text do
|
@@ -27,6 +27,13 @@ module User
|
|
27
27
|
scope.scoped(:conditions => { :role => role })
|
28
28
|
end
|
29
29
|
|
30
|
+
search_by :name_and_city_regex do |scope, regex|
|
31
|
+
#Example for regexes that need to be and'ed together by syntax#build_exclude_scope
|
32
|
+
first = scope.where("users_without_fulltext.name REGEXP ?", regex)
|
33
|
+
second = scope.where("users_without_fulltext.city REGEXP ?", regex)
|
34
|
+
first.merge(second)
|
35
|
+
end
|
36
|
+
|
30
37
|
end
|
31
38
|
|
32
39
|
end
|
@@ -98,7 +98,7 @@ shared_examples_for 'model with search syntax' do
|
|
98
98
|
match = subject.create!(:name => 'Abraham', :city => 'Foohausen')
|
99
99
|
no_match = subject.create!(:name => 'Abraham', :city => 'Barhausen')
|
100
100
|
no_match2 = subject.create!(:name => 'Absolutly no match')
|
101
|
-
subject.search('Abraham city
|
101
|
+
subject.search('Abraham -city:Barhausen').to_a.should == [match]
|
102
102
|
end
|
103
103
|
|
104
104
|
it 'should work if the query only contains excluded words' do
|
@@ -116,7 +116,7 @@ shared_examples_for 'model with search syntax' do
|
|
116
116
|
it 'should work if the query only contains excluded qualified fields' do
|
117
117
|
match = subject.create!(:name => 'Abraham', :city => 'Foohausen')
|
118
118
|
no_match = subject.create!(:name => 'Abraham', :city => 'Barhausen')
|
119
|
-
subject.search('city
|
119
|
+
subject.search('-city:Barhausen').to_a.should == [match]
|
120
120
|
end
|
121
121
|
|
122
122
|
it 'respects an existing scope chain when there are only excluded tokens (bugfix)' do
|
@@ -132,12 +132,18 @@ shared_examples_for 'model with search syntax' do
|
|
132
132
|
subject.search('Sunny -Power').to_a.should == [match]
|
133
133
|
end
|
134
134
|
|
135
|
-
it 'should work if search_by contains a join' do
|
135
|
+
it 'should work if search_by contains a join (bugfix)' do
|
136
136
|
category1 = Recipe::Category.create!(:name => 'Rice')
|
137
|
-
category2= Recipe::Category.create!(:name => 'Barbecue')
|
137
|
+
category2 = Recipe::Category.create!(:name => 'Barbecue')
|
138
138
|
match = Recipe.create!(:name => 'Martini Chicken', :category => category1)
|
139
139
|
no_match = Recipe.create!(:name => 'Barbecue Chicken', :category => category2)
|
140
|
-
Recipe.search('category
|
140
|
+
Recipe.search('Chicken -category:Barbecue').to_a.should == [match]
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should work when search_by uses SQL-Regexes which need to be "and"ed together by syntax#build_exclude_scope (bugfix)' do
|
144
|
+
match = subject.create!(:name => 'Sunny Flower', :city => "Flower")
|
145
|
+
no_match = subject.create!(:name => 'Sunny Power', :city => "Power")
|
146
|
+
subject.search('-name_and_city_regex:Power').to_a.should == [match]
|
141
147
|
end
|
142
148
|
|
143
149
|
end
|
@@ -166,7 +172,7 @@ shared_examples_for 'model with search syntax' do
|
|
166
172
|
end
|
167
173
|
|
168
174
|
it 'should be callable multiple times, appending additional syntax' do
|
169
|
-
subject.search_syntax.fields.keys.should =~ ['text', 'email', 'city', 'role']
|
175
|
+
subject.search_syntax.fields.keys.should =~ ['text', 'email', 'city', 'role', 'name_and_city_regex']
|
170
176
|
end
|
171
177
|
|
172
178
|
end
|
metadata
CHANGED
@@ -1,52 +1,66 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: dusen
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 5
|
9
|
+
- 2
|
10
|
+
version: 0.5.2
|
5
11
|
platform: ruby
|
6
|
-
authors:
|
12
|
+
authors:
|
7
13
|
- Henning Koch
|
8
14
|
autorequire:
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
17
|
+
|
18
|
+
date: 2015-04-02 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
14
22
|
name: activerecord
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '3.0'
|
20
|
-
type: :runtime
|
21
23
|
prerelease: false
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '3.0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: edge_rider
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
31
27
|
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 0
|
33
|
+
version: "3.0"
|
34
34
|
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: edge_rider
|
35
38
|
prerelease: false
|
36
|
-
|
37
|
-
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
38
42
|
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 29
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
- 2
|
48
|
+
- 5
|
40
49
|
version: 0.2.5
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: *id002
|
41
52
|
description: Comprehensive full text search for ActiveRecord and MySQL
|
42
53
|
email: henning.koch@makandra.de
|
43
54
|
executables: []
|
55
|
+
|
44
56
|
extensions: []
|
57
|
+
|
45
58
|
extra_rdoc_files: []
|
46
|
-
|
47
|
-
|
48
|
-
-
|
49
|
-
-
|
59
|
+
|
60
|
+
files:
|
61
|
+
- .gitignore
|
62
|
+
- .ruby-version
|
63
|
+
- .travis.yml
|
50
64
|
- LICENSE
|
51
65
|
- README.md
|
52
66
|
- Rakefile
|
@@ -124,28 +138,39 @@ files:
|
|
124
138
|
- spec/shared/spec/dusen/parser_spec.rb
|
125
139
|
- spec/shared/spec/dusen/query_spec.rb
|
126
140
|
- spec/shared/spec/dusen/util_spec.rb
|
141
|
+
has_rdoc: true
|
127
142
|
homepage: https://github.com/makandra/dusen
|
128
|
-
licenses:
|
143
|
+
licenses:
|
129
144
|
- MIT
|
130
|
-
metadata: {}
|
131
145
|
post_install_message:
|
132
146
|
rdoc_options: []
|
133
|
-
|
147
|
+
|
148
|
+
require_paths:
|
134
149
|
- lib
|
135
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
-
|
150
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
151
|
+
none: false
|
152
|
+
requirements:
|
137
153
|
- - ">="
|
138
|
-
- !ruby/object:Gem::Version
|
139
|
-
|
140
|
-
|
141
|
-
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
hash: 3
|
156
|
+
segments:
|
157
|
+
- 0
|
158
|
+
version: "0"
|
159
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
|
+
none: false
|
161
|
+
requirements:
|
142
162
|
- - ">="
|
143
|
-
- !ruby/object:Gem::Version
|
144
|
-
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
hash: 3
|
165
|
+
segments:
|
166
|
+
- 0
|
167
|
+
version: "0"
|
145
168
|
requirements: []
|
169
|
+
|
146
170
|
rubyforge_project:
|
147
|
-
rubygems_version:
|
171
|
+
rubygems_version: 1.3.9.5
|
148
172
|
signing_key:
|
149
|
-
specification_version:
|
173
|
+
specification_version: 3
|
150
174
|
summary: Comprehensive full text search for ActiveRecord and MySQL
|
151
175
|
test_files: []
|
176
|
+
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 28383a66956bb8c3378bb0033387475fca743a53
|
4
|
-
data.tar.gz: 4b5dc66350c2c31cd070307a54b60296f8ed8dee
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 76ead2fcf071262ae45ea9d710c51150a668d6639752fa6750c4fa7908a11cd562eddb166be657d11d72dfe21009dcb8bcb16740ea29d39c2662cc871efc9936
|
7
|
-
data.tar.gz: a93bc1087afd7ddb94fc955dc0f0323d1fb8c581503c7659615b5738158fe70779eead5cf958ef3c5a7bea69b46f7e15a20278a3ff68652333c531d4683c12fd
|