search_cop 1.1.0 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +50 -0
  3. data/.rubocop.yml +134 -0
  4. data/CHANGELOG.md +23 -9
  5. data/Gemfile +4 -5
  6. data/README.md +11 -1
  7. data/Rakefile +0 -1
  8. data/docker-compose.yml +8 -1
  9. data/gemfiles/{5.1.gemfile → rails5.gemfile} +2 -2
  10. data/gemfiles/rails6.gemfile +13 -0
  11. data/gemfiles/rails7.gemfile +13 -0
  12. data/lib/search_cop/grammar_parser.rb +1 -3
  13. data/lib/search_cop/hash_parser.rb +19 -19
  14. data/lib/search_cop/helpers.rb +15 -0
  15. data/lib/search_cop/query_builder.rb +1 -3
  16. data/lib/search_cop/query_info.rb +0 -2
  17. data/lib/search_cop/search_scope.rb +3 -5
  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 +5 -3
  22. data/lib/search_cop/visitors.rb +0 -2
  23. data/lib/search_cop.rb +5 -23
  24. data/lib/search_cop_grammar/attributes.rb +45 -34
  25. data/lib/search_cop_grammar/nodes.rb +0 -2
  26. data/lib/search_cop_grammar.rb +1 -3
  27. data/search_cop.gemspec +8 -9
  28. data/test/and_test.rb +6 -8
  29. data/test/boolean_test.rb +7 -9
  30. data/test/database.yml +2 -1
  31. data/test/date_test.rb +14 -16
  32. data/test/datetime_test.rb +15 -17
  33. data/test/default_operator_test.rb +14 -10
  34. data/test/error_test.rb +2 -4
  35. data/test/float_test.rb +9 -11
  36. data/test/fulltext_test.rb +6 -8
  37. data/test/hash_test.rb +32 -34
  38. data/test/integer_test.rb +9 -11
  39. data/test/namespace_test.rb +23 -0
  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 +41 -34
  44. data/test/string_test.rb +67 -19
  45. data/test/test_helper.rb +34 -15
  46. data/test/visitor_test.rb +4 -6
  47. metadata +34 -35
  48. data/.travis.yml +0 -34
  49. data/gemfiles/4.2.gemfile +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf37a33f6c9998a09a09817fe5f14024947a1f83ed63682c066dcf35c385ac57
4
- data.tar.gz: 36df6f6110f2126240702636d93c0ed54322794ff5f558fa6dcb27484c3b2b28
3
+ metadata.gz: ebdc7756338ed85d56d22c0e350930651f3776f75bcf027f27a95a994b7e3955
4
+ data.tar.gz: 9f56f6e8b3fb01533ce3e938cd9fb32476970789baf6e6d9a0752e21c125f71d
5
5
  SHA512:
6
- metadata.gz: 4c5233ee11b096ec18e1a53f1e76a6dbb0880a99de9ac41ec836993f317612cf728d81a1332c3f7bfeb42766cb7e28e388061d85cabec8355e7c32e969468761
7
- data.tar.gz: f766262804751519e3566ea80af0358dba148540883d74b5947804e70876ae90555dcb539032f5e59ff1d64fb03b6b10e293e487842b47eeea31246c14a69024
6
+ metadata.gz: c570e77317b1b19d28edb11e9b8d3fe34c08d81f0ddf929efd043da51bda078c60139bc4f27c5e62c31c0fbd5a1b8e21245ec8aae03ebcc2b163d0f5e7570e22
7
+ data.tar.gz: 3d1b6708a2c114271ea733fd245f73ed5be1c577d2140d2a46107dd81a082e5ac9111a8e06151aa185b31c490af1d7f2feb5fd9b7527661b525faa4c48d724f9
@@ -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,15 +1,29 @@
1
1
 
2
2
  # Changelog
3
3
 
4
+ Version 1.2.2:
5
+
6
+ * Fix table name for namespaced models #70
7
+
8
+ Version 1.2.1:
9
+
10
+ * Fix use of `table_name` to work with inherited models
11
+ * Fix linter, add ruby 3 and rails 7 to ci pipeline
12
+
4
13
  Version 1.2.0:
5
14
 
15
+ * Added support for disabling the right wildcard
16
+ * Fixed escaping of wildcard chars (`_`, `%`)
17
+
18
+ Version 1.1.0:
19
+
6
20
  * Adds customizable default operator to concatenate conditions (#49)
7
21
  * Make the postgis adapter use the postgres extensions
8
22
 
9
23
  Version 1.0.9:
10
24
 
11
- * Use [:blank:] instead of \s for space (#46)
12
- * Updated SearchCop::Visitors::Visitor to check the connection's adapter_name when extending. (#47)
25
+ * Use `[:blank:]` instead of `\s` for space (#46)
26
+ * Updated `SearchCop::Visitors::Visitor` to check the connection's `adapter_name` when extending. (#47)
13
27
  * Fix for negative numeric values
14
28
  * allow searching for relative dates, like hours, days, weeks, months or years ago
15
29
 
@@ -19,8 +33,8 @@ Version 1.0.8:
19
33
 
20
34
  Version 1.0.7:
21
35
 
22
- * Bugfix regarding NOT queries in fulltext mode #32
23
- * Safely handle NULL values for match queries
36
+ * Bugfix regarding `NOT` queries in fulltext mode #32
37
+ * Safely handle `NULL` values for match queries
24
38
  * Added coalesce option
25
39
 
26
40
  Version 1.0.6:
@@ -58,7 +72,7 @@ Version 1.0.0:
58
72
 
59
73
  Version 0.0.5:
60
74
 
61
- * Supporting :default => false
75
+ * Supporting `:default => false`
62
76
  * Datetime/Date greater operator fix
63
77
  * Use reflection to find associated models
64
78
  * Providing reflection
@@ -67,16 +81,16 @@ Version 0.0.4:
67
81
 
68
82
  * Fixed date attributes
69
83
  * Fail softly for mixed datatype attributes
70
- * Support custom table, class and alias names via attr_searchable_alias
84
+ * Support custom table, class and alias names via `attr_searchable_alias`
71
85
 
72
86
  Version 0.0.3:
73
87
 
74
- * belongs_to association fixes
88
+ * `belongs_to` association fixes
75
89
 
76
90
  Version 0.0.2:
77
91
 
78
92
  * Arel abstraction layer added
79
- * count() queries resulting in "Cannot visit AttrSearchableGrammar::Nodes..." fixed
93
+ * `count()` queries resulting in "Cannot visit AttrSearchableGrammar::Nodes..." fixed
80
94
  * Better error messages
81
- * Model#unsafe_search added
95
+ * `Model#unsafe_search` added
82
96
 
data/Gemfile CHANGED
@@ -1,11 +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
6
  platforms :ruby do
7
- gem 'sqlite3'
8
- gem 'mysql2'
9
- gem 'pg'
7
+ gem "mysql2"
8
+ gem "pg"
9
+ gem "sqlite3"
10
10
  end
11
-
data/README.md CHANGED
@@ -1,6 +1,6 @@
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
5
  [![Gem Version](https://badge.fury.io/rb/search_cop.svg)](http://badge.fury.io/rb/search_cop)
6
6
 
@@ -329,6 +329,16 @@ User.search("admin")
329
329
  # ... WHERE users.username LIKE 'admin%'
330
330
  ```
331
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
+
332
342
  ## Default operator
333
343
 
334
344
  When you define multiple fields on a search scope, SearcCop will use
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
-
data/docker-compose.yml CHANGED
@@ -8,4 +8,11 @@ services:
8
8
  - MYSQL_ROOT_PASSWORD=
9
9
  ports:
10
10
  - 3306:3306
11
-
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
@@ -5,9 +5,9 @@ source "https://rubygems.org"
5
5
  gem "activerecord", "~> 5.1"
6
6
 
7
7
  platforms :ruby do
8
- gem "sqlite3"
9
8
  gem "mysql2"
10
9
  gem "pg"
10
+ gem "sqlite3"
11
11
  end
12
12
 
13
- gemspec :path => "../"
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
@@ -20,4 +19,3 @@ module SearchCop
20
19
  end
21
20
  end
22
21
  end
23
-
@@ -1,4 +1,3 @@
1
-
2
1
  class SearchCop::HashParser
3
2
  attr_reader :query_info
4
3
 
@@ -6,25 +5,25 @@ class SearchCop::HashParser
6
5
  @query_info = query_info
7
6
  end
8
7
 
9
- def parse(hash)
10
- default_operator = SearchCop::Helpers.sanitize_default_operator(hash, true)
8
+ def parse(hash, query_options = {})
9
+ default_operator = SearchCop::Helpers.sanitize_default_operator(query_options)
11
10
 
12
11
  res = hash.collect do |key, value|
13
12
  case key
14
- when :and
15
- value.collect { |val| parse val }.inject(:and)
16
- when :or
17
- value.collect { |val| parse val }.inject(:or)
18
- when :not
19
- parse(value).not
20
- when :query
21
- SearchCop::Parser.parse value, query_info
22
- else
23
- 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)
24
23
  end
25
24
  end
26
25
 
27
- res.inject default_operator
26
+ res.inject(default_operator)
28
27
  end
29
28
 
30
29
  private
@@ -35,14 +34,15 @@ class SearchCop::HashParser
35
34
  if value.is_a?(Hash)
36
35
  raise(SearchCop::ParseError, "Unknown operator #{value.keys.first}") unless collection.valid_operator?(value.keys.first)
37
36
 
38
- if generator = collection.generator_for(value.keys.first)
39
- 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)
40
41
  else
41
- collection.send value.keys.first, value.values.first.to_s
42
+ collection.send(value.keys.first, value.values.first.to_s)
42
43
  end
43
44
  else
44
- collection.send :matches, value.to_s
45
+ collection.send(:matches, value.to_s)
45
46
  end
46
47
  end
47
48
  end
48
-
@@ -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,4 +1,3 @@
1
-
2
1
  module SearchCop
3
2
  class QueryBuilder
4
3
  attr_accessor :query_info, :scope, :sql
@@ -13,7 +12,7 @@ module SearchCop
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
 
@@ -56,7 +55,7 @@ module SearchCop
56
55
  def attributes_hash(hash)
57
56
  hash.each do |key, value|
58
57
  reflection.attributes[key.to_s] = Array(value).collect do |column|
59
- table, attribute = column.to_s =~ /\./ ? column.to_s.split(".") : [model.name.tableize, column]
58
+ table, attribute = column.to_s =~ /\./ ? column.to_s.split(".") : [model.table_name, column]
60
59
 
61
60
  "#{table}.#{attribute}"
62
61
  end
@@ -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.1.0"
2
+ VERSION = "1.2.2"
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
-
@@ -1,7 +1,8 @@
1
-
2
1
  module SearchCop
3
2
  module Visitors
4
3
  module Postgres
4
+ # rubocop:disable Naming/MethodName
5
+
5
6
  class FulltextQuery < Visitor
6
7
  def visit_SearchCopGrammar_Nodes_MatchesFulltextNot(node)
7
8
  "!'#{node.right.gsub(/[\s&|!:'"]+/, " ")}'"
@@ -21,7 +22,7 @@ module SearchCop
21
22
  end
22
23
 
23
24
  def visit_SearchCopGrammar_Nodes_Matches(node)
24
- "(#{visit node.left} IS NOT NULL AND #{visit node.left} ILIKE #{visit node.right})"
25
+ "(#{visit node.left} IS NOT NULL AND #{visit node.left} ILIKE #{visit node.right} ESCAPE #{visit "\\"})"
25
26
  end
26
27
 
27
28
  def visit_SearchCopGrammar_Attributes_Collection(node)
@@ -41,7 +42,8 @@ module SearchCop
41
42
 
42
43
  "to_tsvector(#{visit dictionary}, #{visit node.collection}) @@ to_tsquery(#{visit dictionary}, #{visit FulltextQuery.new(connection).visit(node.node)})"
43
44
  end
45
+
46
+ # rubocop:enable Naming/MethodName
44
47
  end
45
48
  end
46
49
  end
47
-
@@ -1,7 +1,8 @@
1
-
2
1
  module SearchCop
3
2
  module Visitors
4
3
  class Visitor
4
+ # rubocop:disable Naming/MethodName
5
+
5
6
  attr_accessor :connection
6
7
 
7
8
  def initialize(connection)
@@ -48,7 +49,7 @@ module SearchCop
48
49
  end
49
50
 
50
51
  def visit_SearchCopGrammar_Nodes_Matches(node)
51
- "(#{visit node.left} IS NOT NULL AND #{visit node.left} LIKE #{visit node.right})"
52
+ "(#{visit node.left} IS NOT NULL AND #{visit node.left} LIKE #{visit node.right} ESCAPE #{visit "\\"})"
52
53
  end
53
54
 
54
55
  def visit_SearchCopGrammar_Nodes_Not(node)
@@ -95,7 +96,8 @@ module SearchCop
95
96
  alias :visit_Fixnum :quote
96
97
  alias :visit_Symbol :quote
97
98
  alias :visit_Integer :quote
99
+
100
+ # rubocop:enable Naming/MethodName
98
101
  end
99
102
  end
100
103
  end
101
-
@@ -1,5 +1,3 @@
1
-
2
1
  require "search_cop/visitors/visitor"
3
2
  require "search_cop/visitors/mysql"
4
3
  require "search_cop/visitors/postgres"
5
-
data/lib/search_cop.rb CHANGED
@@ -1,5 +1,5 @@
1
-
2
1
  require "search_cop/version"
2
+ require "search_cop/helpers"
3
3
  require "search_cop/search_scope"
4
4
  require "search_cop/query_info"
5
5
  require "search_cop/query_builder"
@@ -23,7 +23,7 @@ module SearchCop
23
23
  module Parser
24
24
  def self.parse(query, query_info, query_options = {})
25
25
  if query.is_a?(Hash)
26
- SearchCop::HashParser.new(query_info).parse(query)
26
+ SearchCop::HashParser.new(query_info).parse(query, query_options)
27
27
  else
28
28
  SearchCop::GrammarParser.new(query_info).parse(query, query_options)
29
29
  end
@@ -44,8 +44,8 @@ module SearchCop
44
44
  search_scopes[name] = SearchScope.new(name, self)
45
45
  search_scopes[name].instance_exec(&block)
46
46
 
47
- self.send(:define_singleton_method, name) { |query, query_options={}| search_cop query, name, query_options }
48
- self.send(:define_singleton_method, "unsafe_#{name}") { |query, query_options={}| unsafe_search_cop query, name, query_options }
47
+ send(:define_singleton_method, name) { |query, query_options = {}| search_cop(query, name, query_options) }
48
+ send(:define_singleton_method, "unsafe_#{name}") { |query, query_options = {}| unsafe_search_cop(query, name, query_options) }
49
49
  end
50
50
 
51
51
  def search_reflection(scope_name)
@@ -53,7 +53,7 @@ module SearchCop
53
53
  end
54
54
 
55
55
  def search_cop(query, scope_name, query_options)
56
- unsafe_search_cop query, scope_name, query_options
56
+ unsafe_search_cop(query, scope_name, query_options)
57
57
  rescue SearchCop::RuntimeError
58
58
  respond_to?(:none) ? none : where("1 = 0")
59
59
  end
@@ -69,22 +69,4 @@ module SearchCop
69
69
  (scope || self).where(query_builder.sql)
70
70
  end
71
71
  end
72
-
73
- module Helpers
74
- def self.sanitize_default_operator(hash, delete_hash_option=false)
75
- default_operator = :and
76
- if hash.member?(:default_operator)
77
- unless [:and, :or].include?(hash[:default_operator])
78
- raise(SearchCop::UnknownDefaultOperator, "Unknown default operator value #{hash[:default_operator]}")
79
- end
80
-
81
- default_operator = hash[:default_operator]
82
- end
83
-
84
- hash.delete(:default_operator) if delete_hash_option
85
-
86
- default_operator
87
- end
88
- end
89
72
  end
90
-