rokaki 0.7.0 → 0.8.1.2
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/.gitignore +1 -0
- data/Gemfile.lock +49 -48
- data/README.md +141 -27
- data/lib/rokaki/filter_model.rb +21 -4
- data/lib/rokaki/filter_model/nested_filter.rb +4 -3
- data/lib/rokaki/filterable.rb +42 -5
- data/lib/rokaki/version.rb +1 -1
- data/rokaki.gemspec +3 -2
- metadata +33 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f371c83c5d42bd91e4f51363b7ec474807fceb3fb94dc7f9bd76bd067554d167
|
|
4
|
+
data.tar.gz: 373f24755a5f2bd886aa56575b1f60f475db07db6a67b4716ed419a0896996eb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 200432e50f8d847fa7203760b7f52cbfd6743dfdb4247388dfe5e636b79331acec739759fe65b52ebde23585eb90ffbada5802cf5be2f19431410bd612c084f3
|
|
7
|
+
data.tar.gz: 49207149db07210dc0c55fdfbf976737a404e4c255acff2484347b53339d8b18d2ed9f6bd0ca3a5efc2a79b583bf4f6489583cbc586ecce30aa1bde498201881
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
rokaki (0.
|
|
4
|
+
rokaki (0.8.1.2)
|
|
5
5
|
activesupport
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
|
-
activemodel (6.0.
|
|
11
|
-
activesupport (= 6.0.
|
|
12
|
-
activerecord (6.0.
|
|
13
|
-
activemodel (= 6.0.
|
|
14
|
-
activesupport (= 6.0.
|
|
15
|
-
activesupport (6.0.
|
|
10
|
+
activemodel (6.0.3.2)
|
|
11
|
+
activesupport (= 6.0.3.2)
|
|
12
|
+
activerecord (6.0.3.2)
|
|
13
|
+
activemodel (= 6.0.3.2)
|
|
14
|
+
activesupport (= 6.0.3.2)
|
|
15
|
+
activesupport (6.0.3.2)
|
|
16
16
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
17
17
|
i18n (>= 0.7, < 2)
|
|
18
18
|
minitest (~> 5.1)
|
|
19
19
|
tzinfo (~> 1.1)
|
|
20
|
-
zeitwerk (~> 2.
|
|
21
|
-
byebug (11.
|
|
22
|
-
coderay (1.1.
|
|
23
|
-
concurrent-ruby (1.1.
|
|
20
|
+
zeitwerk (~> 2.2, >= 2.2.2)
|
|
21
|
+
byebug (11.1.3)
|
|
22
|
+
coderay (1.1.3)
|
|
23
|
+
concurrent-ruby (1.1.6)
|
|
24
24
|
diff-lcs (1.3)
|
|
25
|
-
|
|
25
|
+
factory_bot (6.0.2)
|
|
26
|
+
activesupport (>= 5.0.0)
|
|
27
|
+
ffi (1.13.1)
|
|
26
28
|
formatador (0.2.5)
|
|
27
|
-
guard (2.
|
|
29
|
+
guard (2.16.2)
|
|
28
30
|
formatador (>= 0.2.4)
|
|
29
31
|
listen (>= 2.7, < 4.0)
|
|
30
32
|
lumberjack (>= 1.0.12, < 2.0)
|
|
@@ -38,51 +40,49 @@ GEM
|
|
|
38
40
|
guard (~> 2.1)
|
|
39
41
|
guard-compat (~> 1.1)
|
|
40
42
|
rspec (>= 2.99.0, < 4.0)
|
|
41
|
-
i18n (1.
|
|
43
|
+
i18n (1.8.3)
|
|
42
44
|
concurrent-ruby (~> 1.0)
|
|
43
|
-
listen (3.1
|
|
44
|
-
rb-fsevent (~> 0.
|
|
45
|
-
rb-inotify (~> 0.9, >= 0.9.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
minitest (5.11.3)
|
|
45
|
+
listen (3.2.1)
|
|
46
|
+
rb-fsevent (~> 0.10, >= 0.10.3)
|
|
47
|
+
rb-inotify (~> 0.9, >= 0.9.10)
|
|
48
|
+
lumberjack (1.2.6)
|
|
49
|
+
method_source (1.0.0)
|
|
50
|
+
minitest (5.14.1)
|
|
50
51
|
nenv (0.3.0)
|
|
51
52
|
notiffany (0.1.3)
|
|
52
53
|
nenv (~> 0.1)
|
|
53
54
|
shellany (~> 0.0)
|
|
54
|
-
pg (1.
|
|
55
|
-
pry (0.
|
|
56
|
-
coderay (~> 1.1
|
|
57
|
-
method_source (~>
|
|
58
|
-
pry-byebug (3.
|
|
55
|
+
pg (1.2.3)
|
|
56
|
+
pry (0.13.1)
|
|
57
|
+
coderay (~> 1.1)
|
|
58
|
+
method_source (~> 1.0)
|
|
59
|
+
pry-byebug (3.9.0)
|
|
59
60
|
byebug (~> 11.0)
|
|
60
|
-
pry (~> 0.
|
|
61
|
-
rake (
|
|
62
|
-
rb-fsevent (0.10.
|
|
63
|
-
rb-inotify (0.10.
|
|
61
|
+
pry (~> 0.13.0)
|
|
62
|
+
rake (13.0.1)
|
|
63
|
+
rb-fsevent (0.10.4)
|
|
64
|
+
rb-inotify (0.10.1)
|
|
64
65
|
ffi (~> 1.0)
|
|
65
|
-
rspec (3.
|
|
66
|
-
rspec-core (~> 3.
|
|
67
|
-
rspec-expectations (~> 3.
|
|
68
|
-
rspec-mocks (~> 3.
|
|
69
|
-
rspec-core (3.
|
|
70
|
-
rspec-support (~> 3.
|
|
71
|
-
rspec-expectations (3.
|
|
66
|
+
rspec (3.9.0)
|
|
67
|
+
rspec-core (~> 3.9.0)
|
|
68
|
+
rspec-expectations (~> 3.9.0)
|
|
69
|
+
rspec-mocks (~> 3.9.0)
|
|
70
|
+
rspec-core (3.9.2)
|
|
71
|
+
rspec-support (~> 3.9.3)
|
|
72
|
+
rspec-expectations (3.9.2)
|
|
72
73
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
73
|
-
rspec-support (~> 3.
|
|
74
|
-
rspec-mocks (3.
|
|
74
|
+
rspec-support (~> 3.9.0)
|
|
75
|
+
rspec-mocks (3.9.1)
|
|
75
76
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
76
|
-
rspec-support (~> 3.
|
|
77
|
-
rspec-support (3.
|
|
78
|
-
ruby_dep (1.5.0)
|
|
77
|
+
rspec-support (~> 3.9.0)
|
|
78
|
+
rspec-support (3.9.3)
|
|
79
79
|
shellany (0.0.1)
|
|
80
|
-
sqlite3 (1.4.
|
|
81
|
-
thor (0.
|
|
80
|
+
sqlite3 (1.4.2)
|
|
81
|
+
thor (1.0.1)
|
|
82
82
|
thread_safe (0.3.6)
|
|
83
|
-
tzinfo (1.2.
|
|
83
|
+
tzinfo (1.2.7)
|
|
84
84
|
thread_safe (~> 0.1)
|
|
85
|
-
zeitwerk (2.
|
|
85
|
+
zeitwerk (2.3.0)
|
|
86
86
|
|
|
87
87
|
PLATFORMS
|
|
88
88
|
ruby
|
|
@@ -90,15 +90,16 @@ PLATFORMS
|
|
|
90
90
|
DEPENDENCIES
|
|
91
91
|
activerecord
|
|
92
92
|
bundler (~> 2.0)
|
|
93
|
+
factory_bot
|
|
93
94
|
guard
|
|
94
95
|
guard-rspec
|
|
95
96
|
pg
|
|
96
97
|
pry
|
|
97
98
|
pry-byebug
|
|
98
|
-
rake (~>
|
|
99
|
+
rake (~> 13.0)
|
|
99
100
|
rokaki!
|
|
100
101
|
rspec (~> 3.0)
|
|
101
102
|
sqlite3
|
|
102
103
|
|
|
103
104
|
BUNDLED WITH
|
|
104
|
-
2.
|
|
105
|
+
2.1.4
|
data/README.md
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
# Rokaki
|
|
2
2
|
[](https://badge.fury.io/rb/rokaki)
|
|
3
3
|
|
|
4
|
-
This gem was born out of a desire to dry up filtering services in Rails or any
|
|
5
|
-
|
|
6
|
-
It's a simple gem that just provides you with a basic dsl based on the filter params that you might pass through from a web request.
|
|
4
|
+
This gem was born out of a desire to dry up filtering services in Rails apps or any Ruby app that uses the concept of "filters" or "facets".
|
|
7
5
|
|
|
6
|
+
There are two modes of use `Filterable` and `FilterModel` that can be activated through the use of two mixins respectively, `include Rokaki::Filterable` or `include Rokaki::FilterModel`.
|
|
8
7
|
## Installation
|
|
9
8
|
|
|
10
9
|
Add this line to your application's Gemfile:
|
|
11
10
|
|
|
11
|
+
You can install from Rubygems:
|
|
12
|
+
```
|
|
13
|
+
gem 'rokaki'
|
|
14
|
+
```
|
|
15
|
+
Or from github
|
|
16
|
+
|
|
12
17
|
```ruby
|
|
13
18
|
gem 'rokaki', git: 'https://github.com/tevio/rokaki.git'
|
|
14
19
|
```
|
|
@@ -17,42 +22,118 @@ And then execute:
|
|
|
17
22
|
|
|
18
23
|
$ bundle
|
|
19
24
|
|
|
20
|
-
## Usage
|
|
25
|
+
## `Rokaki::Filterable` - Usage
|
|
21
26
|
|
|
22
|
-
To use the
|
|
27
|
+
To use the DSL first include the `Rokaki::Filterable` module in your [por](http://blog.jayfields.com/2007/10/ruby-poro.html) class.
|
|
28
|
+
|
|
29
|
+
### `#define_filter_keys`
|
|
30
|
+
#### A Simple Example
|
|
23
31
|
|
|
24
32
|
A simple example might be:-
|
|
25
33
|
|
|
26
34
|
```ruby
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
class FilterArticles
|
|
36
|
+
include Rokaki::Filterable
|
|
29
37
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
def initialize(filters:)
|
|
39
|
+
@filters = filters
|
|
40
|
+
@articles = Article
|
|
41
|
+
end
|
|
34
42
|
|
|
35
|
-
|
|
43
|
+
attr_accessor :filters
|
|
36
44
|
|
|
37
|
-
|
|
45
|
+
define_filter_keys :date, author: [:first_name, :last_name]
|
|
38
46
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
end
|
|
47
|
+
def filter_results
|
|
48
|
+
@articles = @articles.where(date: date) if date
|
|
49
|
+
@articles = @articles.joins(:author).where(author: { first_name: author_first_name }) if author_first_name
|
|
43
50
|
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
article_filter = FilterArticles.new(filters: {
|
|
54
|
+
date: '10-10-10',
|
|
55
|
+
author: {
|
|
56
|
+
first_name: 'Steve',
|
|
57
|
+
last_name: 'Martin'
|
|
58
|
+
}})
|
|
59
|
+
article_filter.author_first_name == 'Steve'
|
|
60
|
+
article_filter.author_last_name == 'Martin'
|
|
61
|
+
article_filter.date == '10-10-10'
|
|
44
62
|
```
|
|
45
63
|
|
|
46
|
-
|
|
64
|
+
In this example Rokaki maps the "flat" attribute "keys" `date`, `author_first_name` and `author_last_name` to a `@filters` object with the expected deep structure `{ date: '10-10-10', author: { first_name: 'Steve' } }`, to make it simple to use them in filter queries.
|
|
65
|
+
|
|
66
|
+
#### A More Complex Example
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
class AdvancedFilterable
|
|
70
|
+
include Rokaki::Filterable
|
|
71
|
+
|
|
72
|
+
def initialize(filters:)
|
|
73
|
+
@fyltrz = filters
|
|
74
|
+
end
|
|
75
|
+
attr_accessor :fyltrz
|
|
76
|
+
|
|
77
|
+
filterable_object_name :fyltrz
|
|
78
|
+
filter_key_infix :__
|
|
79
|
+
define_filter_keys :basic, advanced: {
|
|
80
|
+
filter_key_1: [:filter_key_2, { filter_key_3: :deep_node }],
|
|
81
|
+
filter_key_4: :deep_leaf_array
|
|
82
|
+
}
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
advanced_filterable = AdvancedFilterable.new(filters: {
|
|
87
|
+
basic: 'ABC',
|
|
88
|
+
advanced: {
|
|
89
|
+
filter_key_1: {
|
|
90
|
+
filter_key_2: '123',
|
|
91
|
+
filter_key_3: { deep_node: 'NODE' }
|
|
92
|
+
},
|
|
93
|
+
filter_key_4: { deep_leaf_array: [1,2,3,4] }
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
advanced_filterable.advanced__filter_key_4__deep_leaf_array == [1,2,3,4]
|
|
98
|
+
advanced_filterable.advanced__filter_key_1__filter_key_3__deep_node == 'NODE'
|
|
99
|
+
```
|
|
100
|
+
### `#define_filter_map`
|
|
101
|
+
|
|
102
|
+
This method takes a single field in the passed in filters hash and maps it to fields named in the second param, this is useful if you want to search for a single value across many different fields or associated tables simultaneously.
|
|
103
|
+
|
|
104
|
+
#### A Simple Example
|
|
105
|
+
```ruby
|
|
106
|
+
class FilterMap
|
|
107
|
+
include Rokaki::Filterable
|
|
108
|
+
|
|
109
|
+
def initialize(fylterz:)
|
|
110
|
+
@fylterz = fylterz
|
|
111
|
+
end
|
|
112
|
+
attr_accessor :fylterz
|
|
113
|
+
|
|
114
|
+
filterable_object_name :fylterz
|
|
115
|
+
define_filter_map :query, :mapped_a, association: :field
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
filter_map = FilterMap.new(fytlerz: { query: 'H2O' })
|
|
119
|
+
|
|
120
|
+
filter_map.mapped_a == 'H2O'
|
|
121
|
+
filter_map.association_field = 'H2O'
|
|
122
|
+
```
|
|
47
123
|
|
|
48
|
-
|
|
49
|
-
You can specify a `filter_key_prefix` and a `filter_key_infix` to change the structure of the accessors.
|
|
124
|
+
#### Additional `Filterable` options
|
|
125
|
+
You can specify several configuration options, for example a `filter_key_prefix` and a `filter_key_infix` to change the structure of the generated filter accessors.
|
|
50
126
|
|
|
51
127
|
`filter_key_prefix :__` would result in key accessors like `__author_first_name`
|
|
52
128
|
|
|
53
129
|
`filter_key_infix :__` would result in key accessors like `author__first_name`
|
|
54
130
|
|
|
55
|
-
|
|
131
|
+
`filterable_object_name :fylterz` would use an internal filter state object named `@fyltrz` instead of the default `@filters`
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
## `Rokaki::FilterModel` - Usage
|
|
135
|
+
|
|
136
|
+
### ActiveRecord
|
|
56
137
|
Include `Rokaki::FilterModel` in any ActiveRecord model (only AR >= 6.0.0 tested so far) you can generate the filter keys and the actual filter lookup code using the `filters` keyword on a model like so:-
|
|
57
138
|
|
|
58
139
|
```ruby
|
|
@@ -67,7 +148,7 @@ end
|
|
|
67
148
|
|
|
68
149
|
|
|
69
150
|
class ArticleFilter
|
|
70
|
-
include FilterModel
|
|
151
|
+
include Rokaki::FilterModel
|
|
71
152
|
|
|
72
153
|
filters :date, :title, author: [:first_name, :last_name]
|
|
73
154
|
|
|
@@ -96,7 +177,7 @@ You can use `like` (or, if you use postgres, the case insensitive `ilike`) to pe
|
|
|
96
177
|
|
|
97
178
|
```ruby
|
|
98
179
|
class ArticleFilter
|
|
99
|
-
include FilterModel
|
|
180
|
+
include Rokaki::FilterModel
|
|
100
181
|
|
|
101
182
|
filter :article,
|
|
102
183
|
like: { # you can use ilike here instead if you use postgres and want case insensitive results
|
|
@@ -115,14 +196,45 @@ end
|
|
|
115
196
|
```
|
|
116
197
|
Or
|
|
117
198
|
|
|
118
|
-
#### 2. The
|
|
199
|
+
#### 2. The `filter_map` command syntax
|
|
200
|
+
`filter_map` takes the model name, then a single 'query' field and maps it to fields named in the options, this is useful if you want to search for a single value across many different fields or associated tables simultaneously. (builds on `define_filter_map`)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
```ruby
|
|
204
|
+
class AuthorFilter
|
|
205
|
+
include Rokaki::FilterModel
|
|
206
|
+
|
|
207
|
+
filter_map :author, :query,
|
|
208
|
+
like: {
|
|
209
|
+
articles: {
|
|
210
|
+
title: :circumfix,
|
|
211
|
+
reviews: {
|
|
212
|
+
title: :circumfix
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
attr_accessor :filters, :model
|
|
218
|
+
|
|
219
|
+
def initialize(filters:)
|
|
220
|
+
@filters = filters
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
filters = { query: "Jiddu" }
|
|
225
|
+
filtered_authors = AuthorFilter.new(filters: filters).results
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
In the above example we search for authors who have written articles containing the word "Jiddu" in the title that also have reviews containing the sames word in their titles.
|
|
229
|
+
|
|
230
|
+
#### 3. The porcelain command syntax
|
|
119
231
|
|
|
120
232
|
In this syntax you will need to provide three keywords:- `filters`, `like` and `filter_model` if you are not passing in the model type and assigning it to `@model`
|
|
121
233
|
|
|
122
234
|
|
|
123
235
|
```ruby
|
|
124
236
|
class ArticleFilter
|
|
125
|
-
include FilterModel
|
|
237
|
+
include Rokaki::FilterModel
|
|
126
238
|
|
|
127
239
|
filters :date, :title, author: [:first_name, :last_name]
|
|
128
240
|
like title: :circumfix
|
|
@@ -141,7 +253,7 @@ Or without the model in the initializer
|
|
|
141
253
|
|
|
142
254
|
```ruby
|
|
143
255
|
class ArticleFilter
|
|
144
|
-
include FilterModel
|
|
256
|
+
include Rokaki::FilterModel
|
|
145
257
|
|
|
146
258
|
filters :date, :title, author: [:first_name, :last_name]
|
|
147
259
|
like title: :circumfix
|
|
@@ -165,7 +277,7 @@ Would produce a query with a LIKE which circumfixes '%' around the filter term,
|
|
|
165
277
|
You can filter joins both with basic matching and partial matching
|
|
166
278
|
```ruby
|
|
167
279
|
class ArticleFilter
|
|
168
|
-
include FilterModel
|
|
280
|
+
include Rokaki::FilterModel
|
|
169
281
|
|
|
170
282
|
filter :author,
|
|
171
283
|
like: {
|
|
@@ -189,6 +301,8 @@ You can pass array params (and partially match them), to filters (search multipl
|
|
|
189
301
|
|
|
190
302
|
```ruby
|
|
191
303
|
class ArticleFilter
|
|
304
|
+
include Rokaki::FilterModel
|
|
305
|
+
|
|
192
306
|
filter :article,
|
|
193
307
|
like: {
|
|
194
308
|
author: {
|
data/lib/rokaki/filter_model.rb
CHANGED
|
@@ -25,17 +25,34 @@ module Rokaki
|
|
|
25
25
|
|
|
26
26
|
private
|
|
27
27
|
|
|
28
|
+
def filter_map(model, query_key, options)
|
|
29
|
+
filter_model(model)
|
|
30
|
+
@filter_map_query_key = query_key
|
|
31
|
+
|
|
32
|
+
@_filter_db = options[:db] || :postgres
|
|
33
|
+
@_filter_mode = options[:mode] || :and
|
|
34
|
+
like(options[:like]) if options[:like]
|
|
35
|
+
ilike(options[:ilike]) if options[:ilike]
|
|
36
|
+
filters(*options[:match]) if options[:match]
|
|
37
|
+
end
|
|
38
|
+
|
|
28
39
|
def filter(model, options)
|
|
29
40
|
filter_model(model)
|
|
41
|
+
@filter_map_query_key = nil
|
|
30
42
|
|
|
31
43
|
@_filter_db = options[:db] || :postgres
|
|
44
|
+
@_filter_mode = options[:mode] || :and
|
|
32
45
|
like(options[:like]) if options[:like]
|
|
33
46
|
ilike(options[:ilike]) if options[:ilike]
|
|
34
47
|
filters(*options[:match]) if options[:match]
|
|
35
48
|
end
|
|
36
49
|
|
|
37
50
|
def filters(*filter_keys)
|
|
38
|
-
|
|
51
|
+
if @filter_map_query_key
|
|
52
|
+
define_filter_map(@filter_map_query_key, *filter_keys)
|
|
53
|
+
else
|
|
54
|
+
define_filter_keys(*filter_keys)
|
|
55
|
+
end
|
|
39
56
|
|
|
40
57
|
@_chain_filters ||= []
|
|
41
58
|
filter_keys.each do |filter_key|
|
|
@@ -86,9 +103,9 @@ module Rokaki
|
|
|
86
103
|
end
|
|
87
104
|
end
|
|
88
105
|
|
|
89
|
-
def associated_table(association)
|
|
90
|
-
|
|
91
|
-
end
|
|
106
|
+
# def associated_table(association)
|
|
107
|
+
# @model.reflect_on_association(association).klass.table_name
|
|
108
|
+
# end
|
|
92
109
|
|
|
93
110
|
def filter_model(model_class)
|
|
94
111
|
@model = (model_class.is_a?(Class) ? model_class : Object.const_get(model_class.capitalize))
|
|
@@ -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:, db:)
|
|
7
|
+
def initialize(filter_key_object:, prefix:, infix:, like_semantics:, i_like_semantics:, db:, mode: :and)
|
|
8
8
|
@filter_key_object = filter_key_object
|
|
9
9
|
@prefix = prefix
|
|
10
10
|
@infix = infix
|
|
@@ -13,8 +13,9 @@ module Rokaki
|
|
|
13
13
|
@filter_methods = []
|
|
14
14
|
@filter_templates = []
|
|
15
15
|
@db = db
|
|
16
|
+
@mode = mode
|
|
16
17
|
end
|
|
17
|
-
attr_reader :filter_key_object, :prefix, :infix, :like_semantics, :i_like_semantics, :db
|
|
18
|
+
attr_reader :filter_key_object, :prefix, :infix, :like_semantics, :i_like_semantics, :db, :mode
|
|
18
19
|
attr_accessor :filter_methods, :filter_templates
|
|
19
20
|
|
|
20
21
|
def call # _chain_nested_filter
|
|
@@ -56,7 +57,7 @@ module Rokaki
|
|
|
56
57
|
end
|
|
57
58
|
|
|
58
59
|
def find_i_like_key(keys)
|
|
59
|
-
return nil unless
|
|
60
|
+
return nil unless i_like_semantics && i_like_semantics.keys.any?
|
|
60
61
|
current_like_key = i_like_semantics
|
|
61
62
|
keys.each do |key|
|
|
62
63
|
current_like_key = current_like_key[key]
|
data/lib/rokaki/filterable.rb
CHANGED
|
@@ -16,6 +16,17 @@ module Rokaki
|
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
def define_filter_map(query_field, *filter_keys)
|
|
20
|
+
filter_keys.each do |filter_key|
|
|
21
|
+
_map_filters(query_field, [filter_key]) unless filter_key.is_a? Hash
|
|
22
|
+
_nested_map query_field, filter_key if filter_key.is_a? Hash
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def define_query_key(key = nil)
|
|
27
|
+
@filter_map_query_key = key
|
|
28
|
+
end
|
|
29
|
+
|
|
19
30
|
def filter_key_prefix(prefix = nil)
|
|
20
31
|
@filter_key_prefix ||= prefix
|
|
21
32
|
end
|
|
@@ -24,6 +35,10 @@ module Rokaki
|
|
|
24
35
|
@filter_key_infix ||= infix
|
|
25
36
|
end
|
|
26
37
|
|
|
38
|
+
def filterable_object_name(name = 'filters')
|
|
39
|
+
@filterable_object_name ||= name
|
|
40
|
+
end
|
|
41
|
+
|
|
27
42
|
def _build_filter(keys)
|
|
28
43
|
name = @filter_key_prefix.to_s
|
|
29
44
|
count = keys.size - 1
|
|
@@ -33,12 +48,30 @@ module Rokaki
|
|
|
33
48
|
name += filter_key_infix.to_s unless count == i
|
|
34
49
|
end
|
|
35
50
|
|
|
36
|
-
class_eval "def #{name};
|
|
51
|
+
class_eval "def #{name}; #{filterable_object_name}.dig(*#{keys}); end;", __FILE__, __LINE__
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def _map_filters(query_field, keys)
|
|
55
|
+
name = @filter_key_prefix.to_s
|
|
56
|
+
count = keys.size - 1
|
|
57
|
+
|
|
58
|
+
keys.each_with_index do |key, i|
|
|
59
|
+
name += key.to_s
|
|
60
|
+
name += filter_key_infix.to_s unless count == i
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class_eval "def #{name}; #{filterable_object_name}.dig(:#{query_field}); end;", __FILE__, __LINE__
|
|
37
64
|
end
|
|
38
65
|
|
|
39
66
|
def _nested_key(filters_object)
|
|
40
67
|
filters_object.keys.each do |key|
|
|
41
|
-
deep_map([key], filters_object[key])
|
|
68
|
+
deep_map([key], filters_object[key]) { |keys| _build_filter(keys) }
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def _nested_map(query_field, filters_object)
|
|
73
|
+
filters_object.keys.each do |key|
|
|
74
|
+
deep_map([key], filters_object[key]) { |keys| _map_filters(query_field, keys) }
|
|
42
75
|
end
|
|
43
76
|
end
|
|
44
77
|
|
|
@@ -46,20 +79,24 @@ module Rokaki
|
|
|
46
79
|
if value.is_a? Hash
|
|
47
80
|
value.keys.map do |key|
|
|
48
81
|
_keys = keys.dup << key
|
|
49
|
-
deep_map(_keys, value[key])
|
|
82
|
+
deep_map(_keys, value[key], &Proc.new)
|
|
50
83
|
end
|
|
51
84
|
end
|
|
52
85
|
|
|
53
86
|
if value.is_a? Array
|
|
54
87
|
value.each do |av|
|
|
88
|
+
if av.is_a? Symbol
|
|
55
89
|
_keys = keys.dup << av
|
|
56
|
-
|
|
90
|
+
yield _keys
|
|
91
|
+
else
|
|
92
|
+
deep_map(keys, av, &Proc.new)
|
|
93
|
+
end
|
|
57
94
|
end
|
|
58
95
|
end
|
|
59
96
|
|
|
60
97
|
if value.is_a? Symbol
|
|
61
98
|
_keys = keys.dup << value
|
|
62
|
-
|
|
99
|
+
yield _keys
|
|
63
100
|
end
|
|
64
101
|
end
|
|
65
102
|
|
data/lib/rokaki/version.rb
CHANGED
data/rokaki.gemspec
CHANGED
|
@@ -34,12 +34,13 @@ Gem::Specification.new do |spec|
|
|
|
34
34
|
|
|
35
35
|
spec.add_development_dependency 'activerecord'
|
|
36
36
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
37
|
+
spec.add_development_dependency 'factory_bot'
|
|
37
38
|
spec.add_development_dependency 'guard'
|
|
38
39
|
spec.add_development_dependency 'guard-rspec'
|
|
40
|
+
spec.add_development_dependency 'pg'
|
|
39
41
|
spec.add_development_dependency 'pry'
|
|
40
42
|
spec.add_development_dependency 'pry-byebug'
|
|
41
|
-
spec.add_development_dependency 'rake', '~>
|
|
43
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
42
44
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
43
45
|
spec.add_development_dependency 'sqlite3'
|
|
44
|
-
spec.add_development_dependency 'pg'
|
|
45
46
|
end
|
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.8.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Steve Martin
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-06-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -52,6 +52,20 @@ dependencies:
|
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '2.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: factory_bot
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
55
69
|
- !ruby/object:Gem::Dependency
|
|
56
70
|
name: guard
|
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -81,7 +95,7 @@ dependencies:
|
|
|
81
95
|
- !ruby/object:Gem::Version
|
|
82
96
|
version: '0'
|
|
83
97
|
- !ruby/object:Gem::Dependency
|
|
84
|
-
name:
|
|
98
|
+
name: pg
|
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
|
86
100
|
requirements:
|
|
87
101
|
- - ">="
|
|
@@ -95,7 +109,7 @@ dependencies:
|
|
|
95
109
|
- !ruby/object:Gem::Version
|
|
96
110
|
version: '0'
|
|
97
111
|
- !ruby/object:Gem::Dependency
|
|
98
|
-
name: pry
|
|
112
|
+
name: pry
|
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
|
100
114
|
requirements:
|
|
101
115
|
- - ">="
|
|
@@ -109,49 +123,49 @@ dependencies:
|
|
|
109
123
|
- !ruby/object:Gem::Version
|
|
110
124
|
version: '0'
|
|
111
125
|
- !ruby/object:Gem::Dependency
|
|
112
|
-
name:
|
|
126
|
+
name: pry-byebug
|
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
|
114
128
|
requirements:
|
|
115
|
-
- - "
|
|
129
|
+
- - ">="
|
|
116
130
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: '
|
|
131
|
+
version: '0'
|
|
118
132
|
type: :development
|
|
119
133
|
prerelease: false
|
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
|
121
135
|
requirements:
|
|
122
|
-
- - "
|
|
136
|
+
- - ">="
|
|
123
137
|
- !ruby/object:Gem::Version
|
|
124
|
-
version: '
|
|
138
|
+
version: '0'
|
|
125
139
|
- !ruby/object:Gem::Dependency
|
|
126
|
-
name:
|
|
140
|
+
name: rake
|
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
|
128
142
|
requirements:
|
|
129
143
|
- - "~>"
|
|
130
144
|
- !ruby/object:Gem::Version
|
|
131
|
-
version: '
|
|
145
|
+
version: '13.0'
|
|
132
146
|
type: :development
|
|
133
147
|
prerelease: false
|
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
|
135
149
|
requirements:
|
|
136
150
|
- - "~>"
|
|
137
151
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: '
|
|
152
|
+
version: '13.0'
|
|
139
153
|
- !ruby/object:Gem::Dependency
|
|
140
|
-
name:
|
|
154
|
+
name: rspec
|
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
|
142
156
|
requirements:
|
|
143
|
-
- - "
|
|
157
|
+
- - "~>"
|
|
144
158
|
- !ruby/object:Gem::Version
|
|
145
|
-
version: '0'
|
|
159
|
+
version: '3.0'
|
|
146
160
|
type: :development
|
|
147
161
|
prerelease: false
|
|
148
162
|
version_requirements: !ruby/object:Gem::Requirement
|
|
149
163
|
requirements:
|
|
150
|
-
- - "
|
|
164
|
+
- - "~>"
|
|
151
165
|
- !ruby/object:Gem::Version
|
|
152
|
-
version: '0'
|
|
166
|
+
version: '3.0'
|
|
153
167
|
- !ruby/object:Gem::Dependency
|
|
154
|
-
name:
|
|
168
|
+
name: sqlite3
|
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
|
156
170
|
requirements:
|
|
157
171
|
- - ">="
|
|
@@ -212,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
212
226
|
- !ruby/object:Gem::Version
|
|
213
227
|
version: '0'
|
|
214
228
|
requirements: []
|
|
215
|
-
rubygems_version: 3.
|
|
229
|
+
rubygems_version: 3.1.2
|
|
216
230
|
signing_key:
|
|
217
231
|
specification_version: 4
|
|
218
232
|
summary: A web request filtering library
|