search_cop 1.0.1 → 1.0.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/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
|