search_cop 1.1.0 → 1.2.0

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +42 -0
  3. data/.rubocop.yml +128 -0
  4. data/CHANGELOG.md +14 -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/lib/search_cop.rb +5 -23
  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 +0 -2
  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.rb +0 -2
  20. data/lib/search_cop/visitors/mysql.rb +4 -2
  21. data/lib/search_cop/visitors/postgres.rb +5 -3
  22. data/lib/search_cop/visitors/visitor.rb +5 -3
  23. data/lib/search_cop_grammar.rb +1 -3
  24. data/lib/search_cop_grammar/attributes.rb +45 -34
  25. data/lib/search_cop_grammar/nodes.rb +0 -2
  26. data/search_cop.gemspec +8 -8
  27. data/test/and_test.rb +6 -8
  28. data/test/boolean_test.rb +7 -9
  29. data/test/database.yml +2 -1
  30. data/test/date_test.rb +14 -16
  31. data/test/datetime_test.rb +15 -17
  32. data/test/default_operator_test.rb +14 -10
  33. data/test/error_test.rb +2 -4
  34. data/test/float_test.rb +9 -11
  35. data/test/fulltext_test.rb +6 -8
  36. data/test/hash_test.rb +32 -34
  37. data/test/integer_test.rb +9 -11
  38. data/test/not_test.rb +6 -8
  39. data/test/or_test.rb +8 -10
  40. data/test/scope_test.rb +11 -13
  41. data/test/search_cop_test.rb +32 -34
  42. data/test/string_test.rb +67 -19
  43. data/test/test_helper.rb +13 -15
  44. data/test/visitor_test.rb +4 -6
  45. metadata +28 -13
  46. data/.travis.yml +0 -34
  47. 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: 8cb7e91b305057b2ea3df0c96643f8cd2cc726583f2362db9d576ef128826a75
4
+ data.tar.gz: 419ee38ec698795d478f7749486e63b533c9cc497057aa820b5627b343cbdeb4
5
5
  SHA512:
6
- metadata.gz: 4c5233ee11b096ec18e1a53f1e76a6dbb0880a99de9ac41ec836993f317612cf728d81a1332c3f7bfeb42766cb7e28e388061d85cabec8355e7c32e969468761
7
- data.tar.gz: f766262804751519e3566ea80af0358dba148540883d74b5947804e70876ae90555dcb539032f5e59ff1d64fb03b6b10e293e487842b47eeea31246c14a69024
6
+ metadata.gz: 19b765a13b9a21a5b798b60618253729b4a8c1279babe47644d5c030b93b09c87706138ab11cd5bfd9daee757d8d04bff95fc1bc3ce50c5f6f7399aaaabc09d1
7
+ data.tar.gz: a65e72e3d6e5500b986bb312c45dbbd00432419b344765c71387432dd127efd5eb463cd42f71c3e405913a66b8d45201b9d909b9e66da17bf28f11ea3b7aa5c8
@@ -0,0 +1,42 @@
1
+ name: test
2
+ on: [push, pull_request]
3
+ jobs:
4
+ build:
5
+ runs-on: ubuntu-latest
6
+ strategy:
7
+ matrix:
8
+ ruby: ["2.5", "2.6", "2.7"]
9
+ rails: ["rails5", "rails6"]
10
+ database: ["sqlite", "postgres", "mysql"]
11
+ services:
12
+ postgres:
13
+ image: postgres
14
+ env:
15
+ POSTGRES_USER: search_cop
16
+ POSTGRES_PASSWORD: secret
17
+ POSTGRES_DB: search_cop
18
+ ports:
19
+ - 5432:5432
20
+ mysql:
21
+ image: mysql
22
+ env:
23
+ MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
24
+ MYSQL_ROOT_PASSWORD: ""
25
+ MYSQL_DATABASE: search_cop
26
+ ports:
27
+ - 3306:3306
28
+ steps:
29
+ - uses: actions/checkout@v1
30
+ - uses: actions/setup-ruby@v1
31
+ with:
32
+ ruby-version: ${{ matrix.ruby }}
33
+ - name: test
34
+ env:
35
+ DATABASE: ${{ matrix.database }}
36
+ run: |
37
+ gem install bundler
38
+ bundle config set --local gemfile "gemfiles/${{ matrix.rails }}.gemfile"
39
+ bundle config set --local path "../vendor/bundle"
40
+ bundle install
41
+ bundle exec rake test
42
+ bundle exec rubocop
data/.rubocop.yml ADDED
@@ -0,0 +1,128 @@
1
+ AllCops:
2
+ NewCops: enable
3
+
4
+ Gemspec/RequiredRubyVersion:
5
+ Enabled: false
6
+
7
+ Style/CaseLikeIf:
8
+ Enabled: false
9
+
10
+ Style/RedundantArgument:
11
+ Enabled: false
12
+
13
+ Lint/EmptyBlock:
14
+ Enabled: false
15
+
16
+ Layout/EmptyLineBetweenDefs:
17
+ Enabled: false
18
+
19
+ Style/FrozenStringLiteralComment:
20
+ Enabled: false
21
+
22
+ Lint/RedundantRequireStatement:
23
+ Enabled: false
24
+
25
+ Layout/ArgumentAlignment:
26
+ EnforcedStyle: with_fixed_indentation
27
+
28
+ Layout/FirstArrayElementIndentation:
29
+ EnforcedStyle: consistent
30
+
31
+ Style/PercentLiteralDelimiters:
32
+ Enabled: false
33
+
34
+ Style/SpecialGlobalVars:
35
+ EnforcedStyle: use_english_names
36
+
37
+ Security/Eval:
38
+ Enabled: false
39
+
40
+ Style/WordArray:
41
+ EnforcedStyle: brackets
42
+
43
+ Style/ClassAndModuleChildren:
44
+ Enabled: false
45
+
46
+ Style/TrivialAccessors:
47
+ Enabled: false
48
+
49
+ Style/Alias:
50
+ Enabled: false
51
+
52
+ Style/StringLiteralsInInterpolation:
53
+ EnforcedStyle: double_quotes
54
+
55
+ Metrics/ClassLength:
56
+ Enabled: false
57
+
58
+ Naming/MethodParameterName:
59
+ Enabled: false
60
+
61
+ Style/SymbolArray:
62
+ EnforcedStyle: brackets
63
+
64
+ Layout/RescueEnsureAlignment:
65
+ Enabled: false
66
+
67
+ Layout/LineLength:
68
+ Enabled: false
69
+
70
+ Metrics/MethodLength:
71
+ Enabled: false
72
+
73
+ Metrics/ModuleLength:
74
+ Enabled: false
75
+
76
+ Style/ZeroLengthPredicate:
77
+ Enabled: false
78
+
79
+ Metrics/PerceivedComplexity:
80
+ Enabled: false
81
+
82
+ Metrics/AbcSize:
83
+ Enabled: false
84
+
85
+ Metrics/CyclomaticComplexity:
86
+ Enabled: false
87
+
88
+ Metrics/BlockLength:
89
+ Enabled: false
90
+
91
+ Metrics/BlockNesting:
92
+ Enabled: false
93
+
94
+ Style/NumericPredicate:
95
+ Enabled: false
96
+
97
+ Naming/AccessorMethodName:
98
+ Enabled: false
99
+
100
+ Naming/MemoizedInstanceVariableName:
101
+ Enabled: false
102
+
103
+ Style/StringLiterals:
104
+ EnforcedStyle: double_quotes
105
+
106
+ Style/Documentation:
107
+ Enabled: false
108
+
109
+ Naming/ConstantName:
110
+ Enabled: false
111
+
112
+ Style/MutableConstant:
113
+ Enabled: false
114
+
115
+ Layout/MultilineMethodCallIndentation:
116
+ EnforcedStyle: indented
117
+
118
+ Layout/ParameterAlignment:
119
+ EnforcedStyle: with_fixed_indentation
120
+
121
+ Lint/UnusedMethodArgument:
122
+ Enabled: false
123
+
124
+ Style/IfUnlessModifier:
125
+ Enabled: false
126
+
127
+ Style/RedundantBegin:
128
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -3,13 +3,18 @@
3
3
 
4
4
  Version 1.2.0:
5
5
 
6
+ * Added support for disabling the right wildcard
7
+ * Fixed escaping of wildcard chars (`_`, `%`)
8
+
9
+ Version 1.1.0:
10
+
6
11
  * Adds customizable default operator to concatenate conditions (#49)
7
12
  * Make the postgis adapter use the postgres extensions
8
13
 
9
14
  Version 1.0.9:
10
15
 
11
- * Use [:blank:] instead of \s for space (#46)
12
- * Updated SearchCop::Visitors::Visitor to check the connection's adapter_name when extending. (#47)
16
+ * Use `[:blank:]` instead of `\s` for space (#46)
17
+ * Updated `SearchCop::Visitors::Visitor` to check the connection's `adapter_name` when extending. (#47)
13
18
  * Fix for negative numeric values
14
19
  * allow searching for relative dates, like hours, days, weeks, months or years ago
15
20
 
@@ -19,8 +24,8 @@ Version 1.0.8:
19
24
 
20
25
  Version 1.0.7:
21
26
 
22
- * Bugfix regarding NOT queries in fulltext mode #32
23
- * Safely handle NULL values for match queries
27
+ * Bugfix regarding `NOT` queries in fulltext mode #32
28
+ * Safely handle `NULL` values for match queries
24
29
  * Added coalesce option
25
30
 
26
31
  Version 1.0.6:
@@ -58,7 +63,7 @@ Version 1.0.0:
58
63
 
59
64
  Version 0.0.5:
60
65
 
61
- * Supporting :default => false
66
+ * Supporting `:default => false`
62
67
  * Datetime/Date greater operator fix
63
68
  * Use reflection to find associated models
64
69
  * Providing reflection
@@ -67,16 +72,16 @@ Version 0.0.4:
67
72
 
68
73
  * Fixed date attributes
69
74
  * Fail softly for mixed datatype attributes
70
- * Support custom table, class and alias names via attr_searchable_alias
75
+ * Support custom table, class and alias names via `attr_searchable_alias`
71
76
 
72
77
  Version 0.0.3:
73
78
 
74
- * belongs_to association fixes
79
+ * `belongs_to` association fixes
75
80
 
76
81
  Version 0.0.2:
77
82
 
78
83
  * Arel abstraction layer added
79
- * count() queries resulting in "Cannot visit AttrSearchableGrammar::Nodes..." fixed
84
+ * `count()` queries resulting in "Cannot visit AttrSearchableGrammar::Nodes..." fixed
80
85
  * Better error messages
81
- * Model#unsafe_search added
86
+ * `Model#unsafe_search` added
82
87
 
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: "../"
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
-
@@ -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
-