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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +42 -0
- data/.rubocop.yml +128 -0
- data/CHANGELOG.md +14 -9
- data/Gemfile +4 -5
- data/README.md +11 -1
- data/Rakefile +0 -1
- data/docker-compose.yml +8 -1
- data/gemfiles/{5.1.gemfile → rails5.gemfile} +2 -2
- data/gemfiles/rails6.gemfile +13 -0
- data/lib/search_cop.rb +5 -23
- data/lib/search_cop/grammar_parser.rb +1 -3
- data/lib/search_cop/hash_parser.rb +19 -19
- data/lib/search_cop/helpers.rb +15 -0
- data/lib/search_cop/query_builder.rb +0 -2
- data/lib/search_cop/query_info.rb +0 -2
- data/lib/search_cop/search_scope.rb +2 -4
- data/lib/search_cop/version.rb +1 -1
- data/lib/search_cop/visitors.rb +0 -2
- data/lib/search_cop/visitors/mysql.rb +4 -2
- data/lib/search_cop/visitors/postgres.rb +5 -3
- data/lib/search_cop/visitors/visitor.rb +5 -3
- data/lib/search_cop_grammar.rb +1 -3
- data/lib/search_cop_grammar/attributes.rb +45 -34
- data/lib/search_cop_grammar/nodes.rb +0 -2
- data/search_cop.gemspec +8 -8
- data/test/and_test.rb +6 -8
- data/test/boolean_test.rb +7 -9
- data/test/database.yml +2 -1
- data/test/date_test.rb +14 -16
- data/test/datetime_test.rb +15 -17
- data/test/default_operator_test.rb +14 -10
- data/test/error_test.rb +2 -4
- data/test/float_test.rb +9 -11
- data/test/fulltext_test.rb +6 -8
- data/test/hash_test.rb +32 -34
- data/test/integer_test.rb +9 -11
- data/test/not_test.rb +6 -8
- data/test/or_test.rb +8 -10
- data/test/scope_test.rb +11 -13
- data/test/search_cop_test.rb +32 -34
- data/test/string_test.rb +67 -19
- data/test/test_helper.rb +13 -15
- data/test/visitor_test.rb +4 -6
- metadata +28 -13
- data/.travis.yml +0 -34
- data/gemfiles/4.2.gemfile +0 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8cb7e91b305057b2ea3df0c96643f8cd2cc726583f2362db9d576ef128826a75
|
|
4
|
+
data.tar.gz: 419ee38ec698795d478f7749486e63b533c9cc497057aa820b5627b343cbdeb4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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
|
|
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
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SearchCop
|
|
2
2
|
|
|
3
|
-
[](https://github.com/mrkamel/search_cop/actions?query=workflow%3Atest)
|
|
4
4
|
[](https://codeclimate.com/github/mrkamel/search_cop)
|
|
5
5
|
[](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
data/docker-compose.yml
CHANGED
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
|
-
|
|
48
|
-
|
|
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
|
|
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("
|
|
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(
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
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
|
-
|
|
39
|
-
|
|
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
|
|
42
|
+
collection.send(value.keys.first, value.values.first.to_s)
|
|
42
43
|
end
|
|
43
44
|
else
|
|
44
|
-
collection.send
|
|
45
|
+
collection.send(:matches, value.to_s)
|
|
45
46
|
end
|
|
46
47
|
end
|
|
47
48
|
end
|
|
48
|
-
|