search_cop 1.0.9 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/test.yml +50 -0
  3. data/.rubocop.yml +134 -0
  4. data/CHANGELOG.md +29 -7
  5. data/Gemfile +4 -17
  6. data/README.md +69 -3
  7. data/Rakefile +0 -1
  8. data/docker-compose.yml +18 -0
  9. data/gemfiles/rails5.gemfile +13 -0
  10. data/gemfiles/rails6.gemfile +13 -0
  11. data/gemfiles/rails7.gemfile +13 -0
  12. data/lib/search_cop/grammar_parser.rb +3 -4
  13. data/lib/search_cop/hash_parser.rb +20 -18
  14. data/lib/search_cop/helpers.rb +15 -0
  15. data/lib/search_cop/query_builder.rb +3 -5
  16. data/lib/search_cop/query_info.rb +0 -2
  17. data/lib/search_cop/search_scope.rb +2 -4
  18. data/lib/search_cop/version.rb +1 -1
  19. data/lib/search_cop/visitors/mysql.rb +4 -2
  20. data/lib/search_cop/visitors/postgres.rb +5 -3
  21. data/lib/search_cop/visitors/visitor.rb +7 -5
  22. data/lib/search_cop/visitors.rb +0 -2
  23. data/lib/search_cop.rb +15 -13
  24. data/lib/search_cop_grammar/attributes.rb +53 -34
  25. data/lib/search_cop_grammar/nodes.rb +0 -2
  26. data/lib/search_cop_grammar.rb +13 -4
  27. data/lib/search_cop_grammar.treetop +6 -4
  28. data/search_cop.gemspec +9 -11
  29. data/test/and_test.rb +6 -8
  30. data/test/boolean_test.rb +7 -9
  31. data/test/database.yml +4 -1
  32. data/test/date_test.rb +38 -12
  33. data/test/datetime_test.rb +45 -12
  34. data/test/default_operator_test.rb +51 -0
  35. data/test/error_test.rb +2 -4
  36. data/test/float_test.rb +16 -11
  37. data/test/fulltext_test.rb +6 -8
  38. data/test/hash_test.rb +32 -34
  39. data/test/integer_test.rb +9 -11
  40. data/test/not_test.rb +6 -8
  41. data/test/or_test.rb +8 -10
  42. data/test/scope_test.rb +11 -13
  43. data/test/search_cop_test.rb +42 -36
  44. data/test/string_test.rb +67 -19
  45. data/test/test_helper.rb +28 -18
  46. data/test/visitor_test.rb +4 -6
  47. metadata +25 -42
  48. data/.travis.yml +0 -45
  49. data/Appraisals +0 -21
  50. data/gemfiles/3.2.gemfile +0 -25
  51. data/gemfiles/4.0.gemfile +0 -25
  52. data/gemfiles/4.1.gemfile +0 -25
  53. data/gemfiles/4.2.gemfile +0 -25
  54. data/gemfiles/5.0.gemfile +0 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ec8667b85e0e2df63ebb83e3d4af5319e52483b9
4
- data.tar.gz: 0a1fd1d2c76c9395ac50adc9e1139dbc58ea2cd5
2
+ SHA256:
3
+ metadata.gz: 07623ce75206a9b6b4455141697c09782649b05f1073ec27c965a7a4fdf2862a
4
+ data.tar.gz: 5adef700f6a6514d0d1de0b1f17958d03ecacc0a0f83df57de5aff480bc96da5
5
5
  SHA512:
6
- metadata.gz: ca9b2397fb9bd9b7e3b339f001c58b36c42be50f5a9314094735f6633bb75cb26a91b9e08120a10750653ae5067a82eda96d2a562cff31b92ea3aaa390487c51
7
- data.tar.gz: 6479e2365da9aa3ae8c9a9f6587c6f00a0f0c7d2546d05438dc4738eb810b5eed9a0d5ff432b91a1a9757486d99f795e86f556d55e379a4ce240ed21d89714de
6
+ metadata.gz: fbe73b6ec59b87263d9bfd7d4740618deab1dd7d4867dcb39a864e75db8614f08beed34518477791dd3d66f10ee8461a1282a3d81d35ee17b2a7de26d8c995cf
7
+ data.tar.gz: c131ea06253e994bc5550570708cc5dc973b5392ca208020de08c3384153492c0bc9820438fc0d32c596ec46f27c9982b445d98b80363a89764b6461a4a35706
@@ -0,0 +1,50 @@
1
+ name: test
2
+ on: [push, pull_request]
3
+ jobs:
4
+ build:
5
+ runs-on: ubuntu-latest
6
+ strategy:
7
+ fail-fast: false
8
+ matrix:
9
+ ruby: ["2.6", "2.7", "3.0", "3.1"]
10
+ rails: ["rails5", "rails6", "rails7"]
11
+ database: ["sqlite", "postgres", "mysql"]
12
+ exclude:
13
+ - ruby: "3.0"
14
+ rails: "rails5"
15
+ - ruby: "3.1"
16
+ rails: "rails5"
17
+ - ruby: "2.6"
18
+ rails: "rails7"
19
+ services:
20
+ postgres:
21
+ image: postgres
22
+ env:
23
+ POSTGRES_USER: search_cop
24
+ POSTGRES_PASSWORD: secret
25
+ POSTGRES_DB: search_cop
26
+ ports:
27
+ - 5432:5432
28
+ mysql:
29
+ image: mysql
30
+ env:
31
+ MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
32
+ MYSQL_ROOT_PASSWORD: ""
33
+ MYSQL_DATABASE: search_cop
34
+ ports:
35
+ - 3306:3306
36
+ steps:
37
+ - uses: actions/checkout@v1
38
+ - uses: ruby/setup-ruby@v1
39
+ with:
40
+ ruby-version: ${{ matrix.ruby }}
41
+ - name: test
42
+ env:
43
+ DATABASE: ${{ matrix.database }}
44
+ run: |
45
+ gem install bundler
46
+ bundle config set --local gemfile "gemfiles/${{ matrix.rails }}.gemfile"
47
+ bundle config set --local path "../vendor/bundle"
48
+ bundle install
49
+ bundle exec rake test
50
+ bundle exec rubocop
data/.rubocop.yml ADDED
@@ -0,0 +1,134 @@
1
+ AllCops:
2
+ NewCops: enable
3
+
4
+ Gemspec/RequireMFA:
5
+ Enabled: false
6
+
7
+ Style/FetchEnvVar:
8
+ Enabled: false
9
+
10
+ Gemspec/RequiredRubyVersion:
11
+ Enabled: false
12
+
13
+ Style/CaseLikeIf:
14
+ Enabled: false
15
+
16
+ Style/RedundantArgument:
17
+ Enabled: false
18
+
19
+ Lint/EmptyBlock:
20
+ Enabled: false
21
+
22
+ Layout/EmptyLineBetweenDefs:
23
+ Enabled: false
24
+
25
+ Style/FrozenStringLiteralComment:
26
+ Enabled: false
27
+
28
+ Lint/RedundantRequireStatement:
29
+ Enabled: false
30
+
31
+ Layout/ArgumentAlignment:
32
+ EnforcedStyle: with_fixed_indentation
33
+
34
+ Layout/FirstArrayElementIndentation:
35
+ EnforcedStyle: consistent
36
+
37
+ Style/PercentLiteralDelimiters:
38
+ Enabled: false
39
+
40
+ Style/SpecialGlobalVars:
41
+ EnforcedStyle: use_english_names
42
+
43
+ Security/Eval:
44
+ Enabled: false
45
+
46
+ Style/WordArray:
47
+ EnforcedStyle: brackets
48
+
49
+ Style/ClassAndModuleChildren:
50
+ Enabled: false
51
+
52
+ Style/TrivialAccessors:
53
+ Enabled: false
54
+
55
+ Style/Alias:
56
+ Enabled: false
57
+
58
+ Style/StringLiteralsInInterpolation:
59
+ EnforcedStyle: double_quotes
60
+
61
+ Metrics/ClassLength:
62
+ Enabled: false
63
+
64
+ Naming/MethodParameterName:
65
+ Enabled: false
66
+
67
+ Style/SymbolArray:
68
+ EnforcedStyle: brackets
69
+
70
+ Layout/RescueEnsureAlignment:
71
+ Enabled: false
72
+
73
+ Layout/LineLength:
74
+ Enabled: false
75
+
76
+ Metrics/MethodLength:
77
+ Enabled: false
78
+
79
+ Metrics/ModuleLength:
80
+ Enabled: false
81
+
82
+ Style/ZeroLengthPredicate:
83
+ Enabled: false
84
+
85
+ Metrics/PerceivedComplexity:
86
+ Enabled: false
87
+
88
+ Metrics/AbcSize:
89
+ Enabled: false
90
+
91
+ Metrics/CyclomaticComplexity:
92
+ Enabled: false
93
+
94
+ Metrics/BlockLength:
95
+ Enabled: false
96
+
97
+ Metrics/BlockNesting:
98
+ Enabled: false
99
+
100
+ Style/NumericPredicate:
101
+ Enabled: false
102
+
103
+ Naming/AccessorMethodName:
104
+ Enabled: false
105
+
106
+ Naming/MemoizedInstanceVariableName:
107
+ Enabled: false
108
+
109
+ Style/StringLiterals:
110
+ EnforcedStyle: double_quotes
111
+
112
+ Style/Documentation:
113
+ Enabled: false
114
+
115
+ Naming/ConstantName:
116
+ Enabled: false
117
+
118
+ Style/MutableConstant:
119
+ Enabled: false
120
+
121
+ Layout/MultilineMethodCallIndentation:
122
+ EnforcedStyle: indented
123
+
124
+ Layout/ParameterAlignment:
125
+ EnforcedStyle: with_fixed_indentation
126
+
127
+ Lint/UnusedMethodArgument:
128
+ Enabled: false
129
+
130
+ Style/IfUnlessModifier:
131
+ Enabled: false
132
+
133
+ Style/RedundantBegin:
134
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,14 +1,36 @@
1
1
 
2
2
  # Changelog
3
3
 
4
+ Version 1.2.1:
5
+
6
+ * Fix use of `table_name` to work with inherited models
7
+ * Fix linter, add ruby 3 and rails 7 to ci pipeline
8
+
9
+ Version 1.2.0:
10
+
11
+ * Added support for disabling the right wildcard
12
+ * Fixed escaping of wildcard chars (`_`, `%`)
13
+
14
+ Version 1.1.0:
15
+
16
+ * Adds customizable default operator to concatenate conditions (#49)
17
+ * Make the postgis adapter use the postgres extensions
18
+
19
+ Version 1.0.9:
20
+
21
+ * Use `[:blank:]` instead of `\s` for space (#46)
22
+ * Updated `SearchCop::Visitors::Visitor` to check the connection's `adapter_name` when extending. (#47)
23
+ * Fix for negative numeric values
24
+ * allow searching for relative dates, like hours, days, weeks, months or years ago
25
+
4
26
  Version 1.0.8:
5
27
 
6
28
  * No longer add search scope methods globally #34
7
29
 
8
30
  Version 1.0.7:
9
31
 
10
- * Bugfix regarding NOT queries in fulltext mode #32
11
- * Safely handle NULL values for match queries
32
+ * Bugfix regarding `NOT` queries in fulltext mode #32
33
+ * Safely handle `NULL` values for match queries
12
34
  * Added coalesce option
13
35
 
14
36
  Version 1.0.6:
@@ -46,7 +68,7 @@ Version 1.0.0:
46
68
 
47
69
  Version 0.0.5:
48
70
 
49
- * Supporting :default => false
71
+ * Supporting `:default => false`
50
72
  * Datetime/Date greater operator fix
51
73
  * Use reflection to find associated models
52
74
  * Providing reflection
@@ -55,16 +77,16 @@ Version 0.0.4:
55
77
 
56
78
  * Fixed date attributes
57
79
  * Fail softly for mixed datatype attributes
58
- * Support custom table, class and alias names via attr_searchable_alias
80
+ * Support custom table, class and alias names via `attr_searchable_alias`
59
81
 
60
82
  Version 0.0.3:
61
83
 
62
- * belongs_to association fixes
84
+ * `belongs_to` association fixes
63
85
 
64
86
  Version 0.0.2:
65
87
 
66
88
  * Arel abstraction layer added
67
- * count() queries resulting in "Cannot visit AttrSearchableGrammar::Nodes..." fixed
89
+ * `count()` queries resulting in "Cannot visit AttrSearchableGrammar::Nodes..." fixed
68
90
  * Better error messages
69
- * Model#unsafe_search added
91
+ * `Model#unsafe_search` added
70
92
 
data/Gemfile CHANGED
@@ -1,23 +1,10 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in search_cop.gemspec
4
4
  gemspec
5
5
 
6
- platforms :jruby do
7
- gem 'activerecord-jdbcmysql-adapter'
8
- gem 'activerecord-jdbcsqlite3-adapter'
9
- gem 'activerecord-jdbcpostgresql-adapter'
10
- end
11
-
12
6
  platforms :ruby do
13
- gem 'sqlite3'
14
- gem 'mysql2'
15
- gem 'pg'
7
+ gem "mysql2"
8
+ gem "pg"
9
+ gem "sqlite3"
16
10
  end
17
-
18
- platforms :rbx do
19
- gem 'racc'
20
- gem 'rubysl', '~> 2.0'
21
- gem 'psych'
22
- end
23
-
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  # SearchCop
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/mrkamel/search_cop.png?branch=master)](http://travis-ci.org/mrkamel/search_cop)
3
+ [![Build Status](https://github.com/mrkamel/search_cop/workflows/test/badge.svg?branch=master)](https://github.com/mrkamel/search_cop/actions?query=workflow%3Atest)
4
4
  [![Code Climate](https://codeclimate.com/github/mrkamel/search_cop.png)](https://codeclimate.com/github/mrkamel/search_cop)
5
- [![Dependency Status](https://gemnasium.com/mrkamel/search_cop.png?travis)](https://gemnasium.com/mrkamel/search_cop)
6
5
  [![Gem Version](https://badge.fury.io/rb/search_cop.svg)](http://badge.fury.io/rb/search_cop)
7
6
 
8
7
  ![search_cop](https://raw.githubusercontent.com/mrkamel/search_cop_logo/master/search_cop.png)
@@ -118,6 +117,24 @@ or post-process the search results in every possible way:
118
117
  Book.where(available: true).search("Harry Potter").order("books.id desc").paginate(page: params[:page])
119
118
  ```
120
119
 
120
+ ## Security
121
+
122
+ When you pass a query string to SearchCop, it gets parsed, analyzed and mapped
123
+ to finally build up an SQL query. To be more precise, when SearchCop parses the
124
+ query, it creates objects (nodes), which represent the query expressions (And-,
125
+ Or-, Not-, String-, Date-, etc Nodes). To build the SQL query, SearchCop uses
126
+ the concept of visitors like e.g. used in
127
+ [Arel](https://github.com/rails/arel), such that, for every node there must be
128
+ a [visitor](https://github.com/mrkamel/search_cop/blob/master/lib/search_cop/visitors/visitor.rb),
129
+ which transforms the node to SQL. When there is no visitor, an exception is
130
+ raised when the query builder tries to "visit" the node. The visitors are
131
+ responsible for sanitizing the user supplied input. This is primilarly done via
132
+ quoting (string-, table-name-, column-quoting, etc). SearchCop is using the
133
+ methods provided by the ActiveRecord connection adapter for sanitizing/quoting
134
+ to prevent SQL injection. While we can never be 100% safe from security issues,
135
+ SearchCop takes security issues seriously. Please report responsibly via
136
+ security at flakks dot com in case you find any security related issues.
137
+
121
138
  ## Fulltext index capabilities
122
139
 
123
140
  By default, i.e. if you don't tell SearchCop about your fulltext indices,
@@ -283,7 +300,7 @@ For more details about PostgreSQL fulltext indices visit
283
300
 
284
301
  In case you expose non-fulltext attributes to search queries (price, stock,
285
302
  etc.), the respective queries, like `Book.search("stock > 0")`, will profit
286
- from from the usual non-fulltext indices. Thus, you should add a usual index on
303
+ from the usual non-fulltext indices. Thus, you should add a usual index on
287
304
  every column you expose to search queries plus a fulltext index for every
288
305
  fulltext attribute.
289
306
 
@@ -312,6 +329,51 @@ User.search("admin")
312
329
  # ... WHERE users.username LIKE 'admin%'
313
330
  ```
314
331
 
332
+ Similarly, you can disable the right wildcard as well:
333
+
334
+ ```ruby
335
+ search_scope :search do
336
+ attributes :username
337
+
338
+ options :username, right_wildcard: false
339
+ end
340
+ ```
341
+
342
+ ## Default operator
343
+
344
+ When you define multiple fields on a search scope, SearcCop will use
345
+ by default the AND operator to concatenate the conditions, e.g:
346
+
347
+ ```ruby
348
+ class User < ActiveRecord::Base
349
+ include SearchCop
350
+
351
+ search_scope :search do
352
+ attributes :username, :fullname
353
+ end
354
+
355
+ # ...
356
+ end
357
+ ```
358
+
359
+ So a search like `User.search("something")` will generate a query
360
+ with the following conditions:
361
+
362
+ ```sql
363
+ ... WHERE username LIKE '%something%' AND fullname LIKE '%something%'
364
+ ```
365
+
366
+ However, there are cases where using AND as the default operator is not desired,
367
+ so SearchCop allows you to override it and use OR as the default operator instead.
368
+ A query like `User.search("something", default_operator: :or)` will
369
+ generate the query using OR to concatenate the conditions
370
+
371
+ ```sql
372
+ ... WHERE username LIKE '%something%' OR fullname LIKE '%something%'
373
+ ```
374
+
375
+ Finally, please note that you can apply it to fulltext indices/queries as well.
376
+
315
377
  ## Associations
316
378
 
317
379
  If you specify searchable attributes from another model, like
@@ -454,6 +516,10 @@ SearchCop also provides the ability to define custom operators by defining a
454
516
  search. This is useful when you want to use database operators that are not
455
517
  supported by SearchCop.
456
518
 
519
+ Please note, when using generators, you are responsible for sanitizing/quoting
520
+ the values (see example below). Otherwise your generator will allow SQL
521
+ injection. Thus, please only use generators if you know what you're doing.
522
+
457
523
  For example, if you wanted to perform a `LIKE` query where a book title starts
458
524
  with a string, you can define the search scope like so:
459
525
 
data/Rakefile CHANGED
@@ -6,4 +6,3 @@ Rake::TestTask.new(:test) do |t|
6
6
  t.pattern = "test/**/*_test.rb"
7
7
  t.verbose = true
8
8
  end
9
-
@@ -0,0 +1,18 @@
1
+
2
+ version: '2'
3
+ services:
4
+ mysql:
5
+ image: percona:5.7
6
+ environment:
7
+ - MYSQL_ALLOW_EMPTY_PASSWORD=yes
8
+ - MYSQL_ROOT_PASSWORD=
9
+ ports:
10
+ - 3306:3306
11
+ postgres:
12
+ image: postgres:9.6.6
13
+ environment:
14
+ POSTGRES_DB: search_cop
15
+ POSTGRES_USER: search_cop
16
+ POSTGRES_PASSWORD: secret
17
+ ports:
18
+ - 5432:5432
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.1"
6
+
7
+ platforms :ruby do
8
+ gem "mysql2"
9
+ gem "pg"
10
+ gem "sqlite3"
11
+ end
12
+
13
+ gemspec path: "../"
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 6.0"
6
+
7
+ platforms :ruby do
8
+ gem "mysql2"
9
+ gem "pg"
10
+ gem "sqlite3"
11
+ end
12
+
13
+ gemspec path: "../"
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 7.0"
6
+
7
+ platforms :ruby do
8
+ gem "mysql2"
9
+ gem "pg"
10
+ gem "sqlite3"
11
+ end
12
+
13
+ gemspec path: "../"
@@ -1,8 +1,7 @@
1
-
2
1
  require "search_cop_grammar"
3
2
  require "treetop"
4
3
 
5
- Treetop.load File.expand_path("../../search_cop_grammar.treetop", __FILE__)
4
+ Treetop.load File.expand_path("../search_cop_grammar.treetop", __dir__)
6
5
 
7
6
  module SearchCop
8
7
  class GrammarParser
@@ -12,11 +11,11 @@ module SearchCop
12
11
  @query_info = query_info
13
12
  end
14
13
 
15
- def parse(string)
14
+ def parse(string, query_options)
16
15
  node = SearchCopGrammarParser.new.parse(string) || raise(ParseError)
17
16
  node.query_info = query_info
17
+ node.query_options = query_options
18
18
  node.evaluate
19
19
  end
20
20
  end
21
21
  end
22
-
@@ -1,4 +1,3 @@
1
-
2
1
  class SearchCop::HashParser
3
2
  attr_reader :query_info
4
3
 
@@ -6,23 +5,25 @@ class SearchCop::HashParser
6
5
  @query_info = query_info
7
6
  end
8
7
 
9
- def parse(hash)
8
+ def parse(hash, query_options = {})
9
+ default_operator = SearchCop::Helpers.sanitize_default_operator(query_options)
10
+
10
11
  res = hash.collect do |key, value|
11
12
  case key
12
- when :and
13
- value.collect { |val| parse val }.inject(:and)
14
- when :or
15
- value.collect { |val| parse val }.inject(:or)
16
- when :not
17
- parse(value).not
18
- when :query
19
- SearchCop::Parser.parse value, query_info
20
- else
21
- parse_attribute key, value
13
+ when :and
14
+ value.collect { |val| parse val }.inject(:and)
15
+ when :or
16
+ value.collect { |val| parse val }.inject(:or)
17
+ when :not
18
+ parse(value).not
19
+ when :query
20
+ SearchCop::Parser.parse(value, query_info)
21
+ else
22
+ parse_attribute(key, value)
22
23
  end
23
24
  end
24
25
 
25
- res.inject :and
26
+ res.inject(default_operator)
26
27
  end
27
28
 
28
29
  private
@@ -33,14 +34,15 @@ class SearchCop::HashParser
33
34
  if value.is_a?(Hash)
34
35
  raise(SearchCop::ParseError, "Unknown operator #{value.keys.first}") unless collection.valid_operator?(value.keys.first)
35
36
 
36
- if generator = collection.generator_for(value.keys.first)
37
- collection.generator generator, value.values.first
37
+ generator = collection.generator_for(value.keys.first)
38
+
39
+ if generator
40
+ collection.generator(generator, value.values.first)
38
41
  else
39
- collection.send value.keys.first, value.values.first.to_s
42
+ collection.send(value.keys.first, value.values.first.to_s)
40
43
  end
41
44
  else
42
- collection.send :matches, value.to_s
45
+ collection.send(:matches, value.to_s)
43
46
  end
44
47
  end
45
48
  end
46
-
@@ -0,0 +1,15 @@
1
+ module SearchCop
2
+ module Helpers
3
+ def self.sanitize_default_operator(query_options)
4
+ return "and" unless query_options.key?(:default_operator)
5
+
6
+ default_operator = query_options[:default_operator].to_s.downcase
7
+
8
+ unless ["and", "or"].include?(default_operator)
9
+ raise(SearchCop::UnknownDefaultOperator, "Unknown default operator value #{default_operator}")
10
+ end
11
+
12
+ default_operator
13
+ end
14
+ end
15
+ end
@@ -1,19 +1,18 @@
1
-
2
1
  module SearchCop
3
2
  class QueryBuilder
4
3
  attr_accessor :query_info, :scope, :sql
5
4
 
6
- def initialize(model, query, scope)
5
+ def initialize(model, query, scope, query_options)
7
6
  self.scope = scope
8
7
  self.query_info = QueryInfo.new(model, scope)
9
8
 
10
- arel = SearchCop::Parser.parse(query, query_info).optimize!
9
+ arel = SearchCop::Parser.parse(query, query_info, query_options).optimize!
11
10
 
12
11
  self.sql = SearchCop::Visitors::Visitor.new(model.connection).visit(arel)
13
12
  end
14
13
 
15
14
  def associations
16
- all_associations - [query_info.model.name.tableize.to_sym]
15
+ all_associations - [query_info.model.table_name.to_sym]
17
16
  end
18
17
 
19
18
  private
@@ -32,4 +31,3 @@ module SearchCop
32
31
  end
33
32
  end
34
33
  end
35
-
@@ -1,4 +1,3 @@
1
-
2
1
  module SearchCop
3
2
  class QueryInfo
4
3
  attr_accessor :model, :scope, :references
@@ -10,4 +9,3 @@ module SearchCop
10
9
  end
11
10
  end
12
11
  end
13
-
@@ -1,4 +1,3 @@
1
-
2
1
  module SearchCop
3
2
  class Reflection
4
3
  attr_accessor :attributes, :options, :aliases, :scope, :generators
@@ -11,11 +10,11 @@ module SearchCop
11
10
  end
12
11
 
13
12
  def default_attributes
14
- keys = options.select { |key, value| value[:default] == true }.keys
13
+ keys = options.select { |_key, value| value[:default] == true }.keys
15
14
  keys = attributes.keys.reject { |key| options[key] && options[key][:default] == false } if keys.empty?
16
15
  keys = keys.to_set
17
16
 
18
- attributes.select { |key, value| keys.include? key }
17
+ attributes.select { |key, _value| keys.include? key }
19
18
  end
20
19
  end
21
20
 
@@ -64,4 +63,3 @@ module SearchCop
64
63
  end
65
64
  end
66
65
  end
67
-
@@ -1,3 +1,3 @@
1
1
  module SearchCop
2
- VERSION = "1.0.9"
2
+ VERSION = "1.2.1"
3
3
  end
@@ -1,7 +1,8 @@
1
-
2
1
  module SearchCop
3
2
  module Visitors
4
3
  module Mysql
4
+ # rubocop:disable Naming/MethodName
5
+
5
6
  class FulltextQuery < Visitor
6
7
  def visit_SearchCopGrammar_Nodes_MatchesFulltextNot(node)
7
8
  node.right.split(/[\s+'"<>()~-]+/).collect { |word| "-#{word}" }.join(" ")
@@ -38,6 +39,7 @@ module SearchCop
38
39
  "MATCH(#{visit node.collection}) AGAINST(#{visit FulltextQuery.new(connection).visit(node.node)} IN BOOLEAN MODE)"
39
40
  end
40
41
  end
42
+
43
+ # rubocop:enable Naming/MethodName
41
44
  end
42
45
  end
43
-