rokaki 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -1
- data/README.md +56 -0
- data/lib/rokaki/filter_model/basic_filter.rb +13 -6
- data/lib/rokaki/filter_model/nested_filter.rb +13 -6
- data/lib/rokaki/filter_model.rb +22 -14
- data/lib/rokaki/version.rb +1 -1
- data/rokaki.gemspec +1 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a46db4e821b0a8fb7f661ed539c18c6509b0a644b3bc0f790c0619ab72ff4108
|
4
|
+
data.tar.gz: f6ae9809a6a82c9a1de24ecf7d79b9f0cc6cab530579751df919832c0fa3593e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55b11eee1380defcbd8b56e584b4d4ea145571718da3fa82e5445b2233d779bf169c173d19f5afbf5e7eb6dc69a070a8a08ff64fa3dc41fc4d29690ab2de0556
|
7
|
+
data.tar.gz: 88869cad8ba114234d2581661277963d3eb2effd4aecded8be6d2b7140dcb8331b68d529b4e388518c8ca503deff5f5b8ede87d33bb98152c8e29f676eb268ba
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rokaki (0.
|
4
|
+
rokaki (0.6.0)
|
5
5
|
activesupport
|
6
6
|
|
7
7
|
GEM
|
@@ -51,6 +51,7 @@ GEM
|
|
51
51
|
notiffany (0.1.3)
|
52
52
|
nenv (~> 0.1)
|
53
53
|
shellany (~> 0.0)
|
54
|
+
pg (1.1.4)
|
54
55
|
pry (0.12.2)
|
55
56
|
coderay (~> 1.1.0)
|
56
57
|
method_source (~> 0.9.0)
|
@@ -91,6 +92,7 @@ DEPENDENCIES
|
|
91
92
|
bundler (~> 2.0)
|
92
93
|
guard
|
93
94
|
guard-rspec
|
95
|
+
pg
|
94
96
|
pry
|
95
97
|
pry-byebug
|
96
98
|
rake (~> 10.0)
|
data/README.md
CHANGED
@@ -161,6 +161,62 @@ Would produce a query with a LIKE which circumfixes '%' around the filter term,
|
|
161
161
|
@model = @model.where('title LIKE :query', query: "%#{title}%")
|
162
162
|
```
|
163
163
|
|
164
|
+
### Deep nesting
|
165
|
+
You can filter joins both with basic matching and partial matching
|
166
|
+
```ruby
|
167
|
+
class ArticleFilter
|
168
|
+
include FilterModel
|
169
|
+
|
170
|
+
filter :author,
|
171
|
+
like: {
|
172
|
+
articles: {
|
173
|
+
reviews: {
|
174
|
+
title: :circumfix
|
175
|
+
}
|
176
|
+
},
|
177
|
+
}
|
178
|
+
|
179
|
+
attr_accessor :filters
|
180
|
+
|
181
|
+
def initialize(filters:)
|
182
|
+
@filters = filters
|
183
|
+
end
|
184
|
+
end
|
185
|
+
```
|
186
|
+
|
187
|
+
### Array params
|
188
|
+
You can pass array params (and partially match them), to filters (search multiple matches) in databases that support it (postgres) by passing the `db` param to the filter keyword, and passing an array of search terms at runtine
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
class ArticleFilter
|
192
|
+
filter :article,
|
193
|
+
like: {
|
194
|
+
author: {
|
195
|
+
first_name: :circumfix,
|
196
|
+
last_name: :circumfix
|
197
|
+
}
|
198
|
+
},
|
199
|
+
match: %i[title created_at],
|
200
|
+
db: :postgres
|
201
|
+
|
202
|
+
attr_accessor :filters
|
203
|
+
|
204
|
+
def initialize(filters:)
|
205
|
+
@filters = filters
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
filterable = ArticleFilter.new(filters:
|
210
|
+
{
|
211
|
+
author: {
|
212
|
+
first_name: ['Match One', 'Match Two']
|
213
|
+
}
|
214
|
+
}
|
215
|
+
)
|
216
|
+
|
217
|
+
filterable.results
|
218
|
+
```
|
219
|
+
|
164
220
|
|
165
221
|
## Development
|
166
222
|
|
@@ -3,14 +3,15 @@
|
|
3
3
|
module Rokaki
|
4
4
|
module FilterModel
|
5
5
|
class BasicFilter
|
6
|
-
def initialize(keys:, prefix:, infix:, like_semantics:, i_like_semantics:)
|
6
|
+
def initialize(keys:, prefix:, infix:, like_semantics:, i_like_semantics:, db:)
|
7
7
|
@keys = keys
|
8
8
|
@prefix = prefix
|
9
9
|
@infix = infix
|
10
10
|
@like_semantics = like_semantics
|
11
11
|
@i_like_semantics = i_like_semantics
|
12
|
+
@db = db
|
12
13
|
end
|
13
|
-
attr_reader :keys, :prefix, :infix, :like_semantics, :i_like_semantics
|
14
|
+
attr_reader :keys, :prefix, :infix, :like_semantics, :i_like_semantics, :db
|
14
15
|
attr_accessor :filter_method, :filter_template
|
15
16
|
|
16
17
|
def call
|
@@ -59,10 +60,16 @@ module Rokaki
|
|
59
60
|
end
|
60
61
|
|
61
62
|
def build_like_query(type:, query:, filter:, mode:, key:)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
if db == :postgres
|
64
|
+
query = "@model.where(\"#{key} #{type} ANY (ARRAY[?])\", "
|
65
|
+
query += "prepare_terms(#{filter}, :#{mode}))"
|
66
|
+
else
|
67
|
+
query = "@model.where(\"#{key} #{type} :query\", "
|
68
|
+
query += "query: \"%\#{#{filter}}%\")" if mode == :circumfix
|
69
|
+
query += "query: \"%\#{#{filter}}\")" if mode == :prefix
|
70
|
+
query += "query: \"\#{#{filter}}%\")" if mode == :suffix
|
71
|
+
end
|
72
|
+
|
66
73
|
query
|
67
74
|
end
|
68
75
|
end
|
@@ -4,7 +4,7 @@ require 'active_support/inflector'
|
|
4
4
|
module Rokaki
|
5
5
|
module FilterModel
|
6
6
|
class NestedFilter
|
7
|
-
def initialize(filter_key_object:, prefix:, infix:, like_semantics:, i_like_semantics:)
|
7
|
+
def initialize(filter_key_object:, prefix:, infix:, like_semantics:, i_like_semantics:, db:)
|
8
8
|
@filter_key_object = filter_key_object
|
9
9
|
@prefix = prefix
|
10
10
|
@infix = infix
|
@@ -12,8 +12,9 @@ module Rokaki
|
|
12
12
|
@i_like_semantics = i_like_semantics
|
13
13
|
@filter_methods = []
|
14
14
|
@filter_templates = []
|
15
|
+
@db = db
|
15
16
|
end
|
16
|
-
attr_reader :filter_key_object, :prefix, :infix, :like_semantics, :i_like_semantics
|
17
|
+
attr_reader :filter_key_object, :prefix, :infix, :like_semantics, :i_like_semantics, :db
|
17
18
|
attr_accessor :filter_methods, :filter_templates
|
18
19
|
|
19
20
|
def call # _chain_nested_filter
|
@@ -135,10 +136,16 @@ module Rokaki
|
|
135
136
|
end
|
136
137
|
|
137
138
|
def build_like_query(type:, query:, filter:, mode:, key:, leaf:)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
139
|
+
if db == :postgres
|
140
|
+
query = "where(\"#{key}.#{leaf} #{type} ANY (ARRAY[?])\", "
|
141
|
+
query += "prepare_terms(#{filter}, :#{mode}))"
|
142
|
+
else
|
143
|
+
query = "where(\"#{key}.#{leaf} #{type} :query\", "
|
144
|
+
query += "query: \"%\#{#{filter}}%\")" if mode == :circumfix
|
145
|
+
query += "query: \"%\#{#{filter}}\")" if mode == :prefix
|
146
|
+
query += "query: \"\#{#{filter}}%\")" if mode == :suffix
|
147
|
+
end
|
148
|
+
|
142
149
|
query
|
143
150
|
end
|
144
151
|
|
data/lib/rokaki/filter_model.rb
CHANGED
@@ -7,6 +7,19 @@ module Rokaki
|
|
7
7
|
base.extend(ClassMethods)
|
8
8
|
end
|
9
9
|
|
10
|
+
def prepare_terms(param, mode)
|
11
|
+
if param.is_a? Array
|
12
|
+
return param.map { |term| "%#{term}%" } if mode == :circumfix
|
13
|
+
return param.map { |term| "%#{term}" } if mode == :prefix
|
14
|
+
return param.map { |term| "#{term}%" } if mode == :suffix
|
15
|
+
else
|
16
|
+
return ["%#{param}%"] if mode == :circumfix
|
17
|
+
return ["%#{param}"] if mode == :prefix
|
18
|
+
return ["#{param}%"] if mode == :suffix
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
10
23
|
module ClassMethods
|
11
24
|
include Filterable::ClassMethods
|
12
25
|
|
@@ -15,6 +28,7 @@ module Rokaki
|
|
15
28
|
def filter(model, options)
|
16
29
|
filter_model(model)
|
17
30
|
|
31
|
+
@_filter_db = options[:db] || :postgres
|
18
32
|
like(options[:like]) if options[:like]
|
19
33
|
ilike(options[:ilike]) if options[:ilike]
|
20
34
|
filters(*options[:match]) if options[:match]
|
@@ -42,7 +56,8 @@ module Rokaki
|
|
42
56
|
prefix: filter_key_prefix,
|
43
57
|
infix: filter_key_infix,
|
44
58
|
like_semantics: @_like_semantics,
|
45
|
-
i_like_semantics: @i_like_semantics
|
59
|
+
i_like_semantics: @i_like_semantics,
|
60
|
+
db: @_filter_db
|
46
61
|
)
|
47
62
|
basic_filter.call
|
48
63
|
|
@@ -51,21 +66,14 @@ module Rokaki
|
|
51
66
|
@_chain_filters << basic_filter.filter_template
|
52
67
|
end
|
53
68
|
|
54
|
-
def like_semantics(type:, query:, filter:, mode:, key:)
|
55
|
-
query = "@model.where(\"#{key} #{type} :query\", "
|
56
|
-
query += "query: \"%\#{#{filter}}%\")" if mode == :circumfix
|
57
|
-
query += "query: \"%\#{#{filter}}\")" if mode == :prefix
|
58
|
-
query += "query: \"\#{#{filter}}%\")" if mode == :suffix
|
59
|
-
query
|
60
|
-
end
|
61
|
-
|
62
69
|
def _chain_nested_filter(filters_object)
|
63
70
|
nested_filter = NestedFilter.new(
|
64
71
|
filter_key_object: filters_object,
|
65
72
|
prefix: filter_key_prefix,
|
66
73
|
infix: filter_key_infix,
|
67
74
|
like_semantics: @_like_semantics,
|
68
|
-
i_like_semantics: @i_like_semantics
|
75
|
+
i_like_semantics: @i_like_semantics,
|
76
|
+
db: @_filter_db
|
69
77
|
)
|
70
78
|
nested_filter.call
|
71
79
|
|
@@ -82,9 +90,9 @@ module Rokaki
|
|
82
90
|
@model.reflect_on_association(association).klass.table_name
|
83
91
|
end
|
84
92
|
|
85
|
-
def filter_model(
|
86
|
-
@model = (
|
87
|
-
class_eval "def
|
93
|
+
def filter_model(model_class)
|
94
|
+
@model = (model_class.is_a?(Class) ? model_class : Object.const_get(model_class.capitalize))
|
95
|
+
class_eval "def set_model; @model ||= #{@model}; end;"
|
88
96
|
end
|
89
97
|
|
90
98
|
def like(args)
|
@@ -132,7 +140,7 @@ module Rokaki
|
|
132
140
|
# filter_model method
|
133
141
|
#
|
134
142
|
def define_results
|
135
|
-
results_def = 'def results; model;'
|
143
|
+
results_def = 'def results; @model || set_model;'
|
136
144
|
@_chain_filters.each do |item|
|
137
145
|
results_def += item
|
138
146
|
end
|
data/lib/rokaki/version.rb
CHANGED
data/rokaki.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rokaki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Martin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-11-
|
11
|
+
date: 2019-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -150,6 +150,20 @@ dependencies:
|
|
150
150
|
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: pg
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
153
167
|
description: A dsl for filtering data in web requests
|
154
168
|
email:
|
155
169
|
- steve@martian.media
|