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 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
- indices while still allowing to mix them with non-fulltext attributes. To
170
- improve queries even more, you can group attributes via aliases and specify a
171
- default field to search in, such that SearchCop must no longer search
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 an alias that consists of
203
- `author` and `title`. As we, in addition, specified `all` to be a fulltext
204
- attribute, SearchCop assumes there is a compound fulltext index present on
205
- `author` and `title`, such that the query is optimized accordingly. Finally, we
206
- specified `all` to be the default attribute to search in, such that
207
- SearchCop can ignore other attributes, like e.g. `stock`, as long as they
208
- are not specified within queries directly (like for `stock > 0`).
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
- scope instead. Assocations of associations can as well be referenced
343
- and used:
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 => :user
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 => {...}`, `gt => {...}`, `:gteq => {...}` and `:query => "..."`
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
 
@@ -1,3 +1,3 @@
1
1
  module SearchCop
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
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 ? instance_exec(&search_scopes[scope_name].reflection.scope) : eager_load(query_builder.associations)
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 query_builder.sql
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 klass_for(table)
59
- klass = query_info.scope.reflection.aliases[table]
60
- klass ||= table
58
+ def klass_for_association(name)
59
+ reflections = query_info.model.reflections
61
60
 
62
- query_info.model.reflections[klass.to_sym] ? query_info.model.reflections[klass.to_sym].klass : klass.classify.constantize
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(table)
66
- (query_info.scope.reflection.aliases[table] && table) || klass_for(table).table_name
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)
@@ -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.1
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-08-19 00:00:00.000000000 Z
12
+ date: 2014-10-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: treetop