search_cop 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +38 -18
- data/lib/search_cop/version.rb +1 -1
- data/lib/search_cop.rb +3 -2
- data/lib/search_cop_grammar/attributes.rb +14 -6
- data/test/search_cop_test.rb +4 -0
- metadata +2 -2
data/README.md
CHANGED
@@ -165,11 +165,10 @@ Obviously, theses queries won't always return the same results as wildcard
|
|
165
165
|
fulltext indices will usually of course provide better performance.
|
166
166
|
|
167
167
|
Moreover, the query above is not yet perfect. To improve it even more,
|
168
|
-
SearchCop tries to optimize the queries to make optimal use of fulltext
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
within all fields:
|
168
|
+
SearchCop tries to optimize the queries to make optimal use of fulltext indices
|
169
|
+
while still allowing to mix them with non-fulltext attributes. To improve
|
170
|
+
queries even more, you can group attributes and specify a default field to
|
171
|
+
search in, such that SearchCop must no longer search within all fields:
|
173
172
|
|
174
173
|
```ruby
|
175
174
|
search_scope :search do
|
@@ -199,13 +198,14 @@ Book.search("Rowling OR Tolkien stock > 1")
|
|
199
198
|
# PostgreSQL: ... WHERE to_tsvector('simple', books.author || ' ' || books.title) @@ to_tsquery('simple', 'Rowling | Tokien') and books.stock > 1
|
200
199
|
```
|
201
200
|
|
202
|
-
What is happening here? Well, we specified `all` as
|
203
|
-
`author` and `title`. As we, in addition, specified
|
204
|
-
attribute, SearchCop assumes there is a compound
|
205
|
-
`author` and `title`, such that the query is
|
206
|
-
specified `all` to be the default attribute
|
207
|
-
SearchCop can ignore other attributes, like e.g.
|
208
|
-
are not specified within queries directly (like for
|
201
|
+
What is happening here? Well, we specified `all` as the name of an attribute
|
202
|
+
group that consists of `author` and `title`. As we, in addition, specified
|
203
|
+
`all` to be a fulltext attribute, SearchCop assumes there is a compound
|
204
|
+
fulltext index present on `author` and `title`, such that the query is
|
205
|
+
optimized accordingly. Finally, we specified `all` to be the default attribute
|
206
|
+
to search in, such that SearchCop can ignore other attributes, like e.g.
|
207
|
+
`stock`, as long as they are not specified within queries directly (like for
|
208
|
+
`stock > 0`).
|
209
209
|
|
210
210
|
Other queries will be optimized in a similar way, such that SearchCop
|
211
211
|
tries to minimize the fultext constraints within a query, namely `MATCH()
|
@@ -338,9 +338,29 @@ class Book < ActiveRecord::Base
|
|
338
338
|
end
|
339
339
|
```
|
340
340
|
|
341
|
-
SearchCop will then skip any association auto loading and will use the
|
342
|
-
|
343
|
-
and
|
341
|
+
SearchCop will then skip any association auto loading and will use the scope
|
342
|
+
instead. You can as well use `scope` together with `aliases` to perform
|
343
|
+
arbitrarily complex joins and search in the joined models/tables:
|
344
|
+
|
345
|
+
```ruby
|
346
|
+
class Book < ActiveRecord::Base
|
347
|
+
# ...
|
348
|
+
|
349
|
+
search_scope :search do
|
350
|
+
attributes :similar => ["similar_books.title", "similar_books.description"]
|
351
|
+
|
352
|
+
scope do
|
353
|
+
joins "left outer join books similar_books on ..."
|
354
|
+
end
|
355
|
+
|
356
|
+
aliases :similar_books => Book # Tell SearchCop how to map SQL aliases to models
|
357
|
+
end
|
358
|
+
|
359
|
+
# ...
|
360
|
+
end
|
361
|
+
```
|
362
|
+
|
363
|
+
Assocations of associations can as well be referenced and used:
|
344
364
|
|
345
365
|
```ruby
|
346
366
|
class Book < ActiveRecord::Base
|
@@ -363,7 +383,7 @@ SearchCop tries to infer a model's class name and SQL alias from the
|
|
363
383
|
specified attributes to autodetect datatype definitions, etc. This usually
|
364
384
|
works quite fine. In case you're using custom table names via `self.table_name
|
365
385
|
= ...` or if a model is associated multiple times, SearchCop however can't
|
366
|
-
infer the class and alias names, e.g.
|
386
|
+
infer the class and SQL alias names, e.g.
|
367
387
|
|
368
388
|
```ruby
|
369
389
|
class Book < ActiveRecord::Base
|
@@ -392,7 +412,7 @@ class Book < ActiveRecord::Base
|
|
392
412
|
search_scope :search do
|
393
413
|
# ...
|
394
414
|
|
395
|
-
aliases :users_books =>
|
415
|
+
aliases :users_books => User
|
396
416
|
end
|
397
417
|
|
398
418
|
# ...
|
@@ -410,7 +430,7 @@ operator regarding a single attribute.
|
|
410
430
|
|
411
431
|
Hash based queries support `:and => [...]` and `:or => [...]`, which take an array
|
412
432
|
of `:not => {...}`, `:matches => {...}`, `:eq => {...}`, `:not_eq => {...}`,
|
413
|
-
`:lt => {...}`, `:lteq => {...}`,
|
433
|
+
`:lt => {...}`, `:lteq => {...}`, `:gt => {...}`, `:gteq => {...}` and `:query => "..."`
|
414
434
|
arguments. Moreover, `:query => "..."` makes it possible to create sub-queries.
|
415
435
|
The other rules for query string queries apply to hash based queries as well.
|
416
436
|
|
data/lib/search_cop/version.rb
CHANGED
data/lib/search_cop.rb
CHANGED
@@ -60,9 +60,10 @@ module SearchCop
|
|
60
60
|
|
61
61
|
query_builder = QueryBuilder.new(self, query, search_scopes[scope_name])
|
62
62
|
|
63
|
-
scope = search_scopes[scope_name].reflection.scope
|
63
|
+
scope = instance_exec(&search_scopes[scope_name].reflection.scope) if search_scopes[scope_name].reflection.scope
|
64
|
+
scope ||= eager_load(query_builder.associations) if query_builder.associations.any?
|
64
65
|
|
65
|
-
scope.where
|
66
|
+
(scope || self).where(query_builder.sql)
|
66
67
|
end
|
67
68
|
end
|
68
69
|
end
|
@@ -55,15 +55,23 @@ module SearchCopGrammar
|
|
55
55
|
@attributes ||= query_info.scope.reflection.attributes[key].collect { |attribute_definition| attribute_for attribute_definition }
|
56
56
|
end
|
57
57
|
|
58
|
-
def
|
59
|
-
|
60
|
-
klass ||= table
|
58
|
+
def klass_for_association(name)
|
59
|
+
reflections = query_info.model.reflections
|
61
60
|
|
62
|
-
|
61
|
+
return reflections[name.to_sym].klass if reflections[name.to_sym]
|
62
|
+
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def klass_for(name)
|
67
|
+
mapped_name = query_info.scope.reflection.aliases[name]
|
68
|
+
mapped_name ||= name
|
69
|
+
|
70
|
+
klass_for_association(mapped_name) || mapped_name.classify.constantize
|
63
71
|
end
|
64
72
|
|
65
|
-
def alias_for(
|
66
|
-
(query_info.scope.reflection.aliases[
|
73
|
+
def alias_for(name)
|
74
|
+
(query_info.scope.reflection.aliases[name] && name) || klass_for(name).table_name
|
67
75
|
end
|
68
76
|
|
69
77
|
def attribute_for(attribute_definition)
|
data/test/search_cop_test.rb
CHANGED
@@ -127,5 +127,9 @@ class SearchCopTest < SearchCop::TestCase
|
|
127
127
|
assert_not_nil Product.search_reflection(:search)
|
128
128
|
assert_not_nil Product.search_reflection(:user_search)
|
129
129
|
end
|
130
|
+
|
131
|
+
def test_blank
|
132
|
+
assert_equal Product.all, Product.search("")
|
133
|
+
end
|
130
134
|
end
|
131
135
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: search_cop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-10-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: treetop
|