rokaki 0.8.3 → 0.8.3.1
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 +6 -1
- data/README.md +58 -2
- data/lib/rokaki.rb +0 -3
- data/lib/rokaki/filter_model.rb +3 -2
- data/lib/rokaki/filter_model/join_map.rb +8 -7
- data/lib/rokaki/filter_model/nested_filter.rb +1 -1
- data/lib/rokaki/filter_model/nested_like_filters.rb +4 -4
- data/lib/rokaki/filterable.rb +8 -4
- data/lib/rokaki/version.rb +1 -1
- data/rokaki.gemspec +8 -4
- metadata +37 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f2a62792073dd9728a44158d6f30dc4f0f8119316bda3a3846c16fc2abc57f7
|
4
|
+
data.tar.gz: 80e9bfc7b677b7e291996c5bda1fc6652ddfbb592b31083446ef992755f00404
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6570c3b380c66092b3a583b1c94a51f8364f06d936522cc72676e23c3aa1717b4b89cc65c0d3ed6e6d67291b3c7e1c3c83d8254acd7df8f9971700b314a71aa0
|
7
|
+
data.tar.gz: 913e7bf304da343a4dce4d061dbcdaa37c2f26d7a396e590e393a224a4ac7c30c439f8d085de1a865828c9931f1bcf99dc66b32c8494e8481dcc6c5539d03ea6
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rokaki (0.8.3)
|
4
|
+
rokaki (0.8.3.1)
|
5
5
|
activesupport
|
6
6
|
|
7
7
|
GEM
|
@@ -21,6 +21,10 @@ GEM
|
|
21
21
|
byebug (11.1.3)
|
22
22
|
coderay (1.1.3)
|
23
23
|
concurrent-ruby (1.1.6)
|
24
|
+
database_cleaner (1.8.5)
|
25
|
+
database_cleaner-active_record (1.8.0)
|
26
|
+
activerecord
|
27
|
+
database_cleaner (~> 1.8.0)
|
24
28
|
diff-lcs (1.3)
|
25
29
|
factory_bot (6.0.2)
|
26
30
|
activesupport (>= 5.0.0)
|
@@ -90,6 +94,7 @@ PLATFORMS
|
|
90
94
|
DEPENDENCIES
|
91
95
|
activerecord
|
92
96
|
bundler (~> 2.0)
|
97
|
+
database_cleaner-active_record
|
93
98
|
factory_bot
|
94
99
|
guard
|
95
100
|
guard-rspec
|
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# Rokaki
|
2
|
+
## You know, for air.
|
3
|
+
|
2
4
|
[](https://badge.fury.io/rb/rokaki)
|
3
5
|
|
4
6
|
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".
|
@@ -46,7 +48,8 @@ class FilterArticles
|
|
46
48
|
|
47
49
|
def filter_results
|
48
50
|
@articles = @articles.where(date: date) if date
|
49
|
-
@articles = @articles.joins(:author).where(
|
51
|
+
@articles = @articles.joins(:author).where(authors: { first_name: author_first_name }) if author_first_name
|
52
|
+
@articles = @articles.joins(:author).where(authors: { last_name: author_last_name }) if author_last_name
|
50
53
|
end
|
51
54
|
end
|
52
55
|
|
@@ -98,6 +101,7 @@ advanced_filterable.advanced__filter_key_4__deep_leaf_array == [1,2,3,4]
|
|
98
101
|
advanced_filterable.advanced__filter_key_1__filter_key_3__deep_node == 'NODE'
|
99
102
|
```
|
100
103
|
### `#define_filter_map`
|
104
|
+
The define_filter_map method is more suited to classic "search", where you might want to search multiple fields on a model or across a graph. See the section on [filter_map](https://github.com/tevio/rokaki#2-the-filter_map-command-syntax) with OR for more on this kind of application.
|
101
105
|
|
102
106
|
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
107
|
|
@@ -115,7 +119,7 @@ class FilterMap
|
|
115
119
|
define_filter_map :query, :mapped_a, association: :field
|
116
120
|
end
|
117
121
|
|
118
|
-
filter_map = FilterMap.new(
|
122
|
+
filter_map = FilterMap.new(fylterz: { query: 'H2O' })
|
119
123
|
|
120
124
|
filter_map.mapped_a == 'H2O'
|
121
125
|
filter_map.association_field = 'H2O'
|
@@ -257,6 +261,58 @@ filters = { query: "Lao" }
|
|
257
261
|
filtered_authors = AuthorFilter.new(filters: filters).results
|
258
262
|
```
|
259
263
|
|
264
|
+
## CAVEATS
|
265
|
+
Active record OR over a join may require you to add something like the following in an initializer in order for it to function properly:-
|
266
|
+
|
267
|
+
### #structurally_incompatible_values_for_or
|
268
|
+
|
269
|
+
``` ruby
|
270
|
+
module ActiveRecord
|
271
|
+
module QueryMethods
|
272
|
+
def structurally_incompatible_values_for_or(other)
|
273
|
+
Relation::SINGLE_VALUE_METHODS.reject { |m| send("#{m}_value") == other.send("#{m}_value") } +
|
274
|
+
(Relation::MULTI_VALUE_METHODS - [:joins, :eager_load, :references, :extending]).reject { |m| send("#{m}_values") == other.send("#{m}_values") } +
|
275
|
+
(Relation::CLAUSE_METHODS - [:having, :where]).reject { |m| send("#{m}_clause") == other.send("#{m}_clause") }
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
```
|
280
|
+
|
281
|
+
### A has one relation to a model called Or
|
282
|
+
If you happen to have a model/table named 'Or' then you can override the `or:` key syntax by specifying a special `or_key`:-
|
283
|
+
|
284
|
+
```ruby
|
285
|
+
class AuthorFilter
|
286
|
+
include Rokaki::FilterModel
|
287
|
+
|
288
|
+
or_key :my_or
|
289
|
+
filter_map :author, :query,
|
290
|
+
like: {
|
291
|
+
articles: {
|
292
|
+
title: :circumfix,
|
293
|
+
my_or: { # the or is aware of the join and will generate a compound join aware or query
|
294
|
+
or: { # The Or model has a title field
|
295
|
+
title: :circumfix
|
296
|
+
}
|
297
|
+
}
|
298
|
+
},
|
299
|
+
}
|
300
|
+
|
301
|
+
attr_accessor :filters, :model
|
302
|
+
|
303
|
+
def initialize(filters:)
|
304
|
+
@filters = filters
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
filters = { query: "Syntaxes" }
|
309
|
+
filtered_authors = AuthorFilter.new(filters: filters).results
|
310
|
+
```
|
311
|
+
|
312
|
+
|
313
|
+
See [this issue](https://github.com/rails/rails/issues/24055) for details.
|
314
|
+
|
315
|
+
|
260
316
|
#### 3. The porcelain command syntax
|
261
317
|
|
262
318
|
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`
|
data/lib/rokaki.rb
CHANGED
data/lib/rokaki/filter_model.rb
CHANGED
@@ -8,7 +8,7 @@ module Rokaki
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def prepare_terms(param, mode)
|
11
|
-
if param
|
11
|
+
if Array === param
|
12
12
|
return param.map { |term| "%#{term}%" } if mode == :circumfix
|
13
13
|
return param.map { |term| "%#{term}" } if mode == :prefix
|
14
14
|
return param.map { |term| "#{term}%" } if mode == :suffix
|
@@ -79,7 +79,8 @@ module Rokaki
|
|
79
79
|
prefix: filter_key_prefix,
|
80
80
|
infix: filter_key_infix,
|
81
81
|
db: @_filter_db,
|
82
|
-
type: term_type
|
82
|
+
type: term_type,
|
83
|
+
or_key: or_key
|
83
84
|
)
|
84
85
|
nested_like_filter.call
|
85
86
|
|
@@ -25,7 +25,7 @@ module Rokaki
|
|
25
25
|
current_key_path = []
|
26
26
|
previous_key = nil
|
27
27
|
|
28
|
-
if key_path
|
28
|
+
if Symbol === key_path
|
29
29
|
if key_paths.length == 1
|
30
30
|
@result = key_paths
|
31
31
|
else
|
@@ -33,7 +33,7 @@ module Rokaki
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
if key_path
|
36
|
+
if Array === key_path
|
37
37
|
key_path.each do |key|
|
38
38
|
current_path_length = current_key_path.length
|
39
39
|
|
@@ -42,9 +42,9 @@ module Rokaki
|
|
42
42
|
if current_path_length == 1
|
43
43
|
parent_result = result[previous_key]
|
44
44
|
|
45
|
-
if
|
45
|
+
if Symbol === parent_result && parent_result != key
|
46
46
|
result[previous_key] = [parent_result, key]
|
47
|
-
elsif parent_result
|
47
|
+
elsif Array === parent_result
|
48
48
|
|
49
49
|
parent_result.each_with_index do |array_item, index|
|
50
50
|
if array_item == key
|
@@ -63,13 +63,14 @@ module Rokaki
|
|
63
63
|
|
64
64
|
if previous_path_length == 1
|
65
65
|
res = result.dig(*previous_key_path)
|
66
|
-
|
66
|
+
|
67
|
+
if Symbol === res
|
67
68
|
result[previous_key_path.first] = { previous_key => key }
|
68
|
-
elsif res.is_a?(Hash)
|
69
69
|
end
|
70
70
|
elsif previous_path_length > 1
|
71
71
|
res = result.dig(*previous_key_path)
|
72
|
-
|
72
|
+
|
73
|
+
if Symbol === res
|
73
74
|
base = previous_key_path.pop
|
74
75
|
result.dig(*previous_key_path)[base] = { previous_key => key }
|
75
76
|
end
|
@@ -81,7 +81,7 @@ module Rokaki
|
|
81
81
|
base_modes = modes[index]
|
82
82
|
key_path_item.each_with_index do |key_path, kp_index|
|
83
83
|
|
84
|
-
|
84
|
+
build_query(keys: key_path.dup, join_map: join_map.result, mode: base_modes[kp_index], filter_name: item_filter_names[kp_index], search_mode: item_search_modes[kp_index])
|
85
85
|
end
|
86
86
|
|
87
87
|
item_filter_queries = filter_queries[index]
|
@@ -102,7 +102,7 @@ module Rokaki
|
|
102
102
|
|
103
103
|
method_name = ([prefix, :filter, base_name]).compact.join(infix.to_s)
|
104
104
|
|
105
|
-
|
105
|
+
build_query(keys: key_path_item.dup, join_map: join_map.result, filter_name: filter_name, search_mode: search_modes[index])
|
106
106
|
|
107
107
|
@filter_methods << "def #{method_name}; #{filter_queries[index]}; end;"
|
108
108
|
@templates << "@model = #{method_name} if #{filter_name};"
|
@@ -190,7 +190,7 @@ module Rokaki
|
|
190
190
|
end
|
191
191
|
|
192
192
|
# DOUBLE SPLAT HASHES TO MAKE ARG LISTS!
|
193
|
-
def
|
193
|
+
def build_query(keys: , join_map:, mode: :and, filter_name:, search_mode:)
|
194
194
|
leaf = nil
|
195
195
|
leaf = keys.pop
|
196
196
|
|
@@ -212,7 +212,7 @@ module Rokaki
|
|
212
212
|
filter_query = "@model.joins(**#{join_map}).#{query}"
|
213
213
|
end
|
214
214
|
|
215
|
-
if mode ==
|
215
|
+
if mode == or_key
|
216
216
|
@filter_queries << [@filter_queries.pop, filter_query].flatten
|
217
217
|
else
|
218
218
|
@filter_queries << filter_query
|
data/lib/rokaki/filterable.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rokaki
|
4
|
+
# include this module for rokaki's filtering dsl in any object
|
5
|
+
#
|
2
6
|
module Filterable
|
3
7
|
def self.included(base)
|
4
8
|
base.extend(ClassMethods)
|
@@ -11,15 +15,15 @@ module Rokaki
|
|
11
15
|
|
12
16
|
def define_filter_keys(*filter_keys)
|
13
17
|
filter_keys.each do |filter_key|
|
14
|
-
_build_filter([filter_key]) unless filter_key
|
15
|
-
_nested_key filter_key if filter_key
|
18
|
+
_build_filter([filter_key]) unless Hash === filter_key
|
19
|
+
_nested_key filter_key if Hash === filter_key
|
16
20
|
end
|
17
21
|
end
|
18
22
|
|
19
23
|
def define_filter_map(query_field, *filter_keys)
|
20
24
|
filter_keys.each do |filter_key|
|
21
|
-
_map_filters(query_field, [filter_key]) unless filter_key
|
22
|
-
_nested_map query_field, filter_key if filter_key
|
25
|
+
_map_filters(query_field, [filter_key]) unless Hash === filter_key
|
26
|
+
_nested_map query_field, filter_key if Hash === filter_key
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
data/lib/rokaki/version.rb
CHANGED
data/rokaki.gemspec
CHANGED
@@ -34,13 +34,17 @@ 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'
|
38
|
-
spec.add_development_dependency 'guard'
|
39
|
-
spec.add_development_dependency 'guard-rspec'
|
40
|
-
spec.add_development_dependency 'pg'
|
41
37
|
spec.add_development_dependency 'pry'
|
42
38
|
spec.add_development_dependency 'pry-byebug'
|
43
39
|
spec.add_development_dependency 'rake', '~> 13.0'
|
40
|
+
|
41
|
+
spec.add_development_dependency 'guard'
|
42
|
+
spec.add_development_dependency 'guard-rspec'
|
44
43
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
44
|
+
spec.add_development_dependency 'factory_bot'
|
45
|
+
|
46
|
+
spec.add_development_dependency 'pg'
|
45
47
|
spec.add_development_dependency 'sqlite3'
|
48
|
+
spec.add_development_dependency 'database_cleaner-active_record'
|
49
|
+
|
46
50
|
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.8.3
|
4
|
+
version: 0.8.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Martin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-06-
|
11
|
+
date: 2020-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '2.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: pry
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: pry-byebug
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -81,21 +81,21 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rake
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
89
|
+
version: '13.0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
96
|
+
version: '13.0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: guard
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: guard-rspec
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
@@ -123,7 +123,21 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '3.0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '3.0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: factory_bot
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - ">="
|
@@ -137,35 +151,35 @@ dependencies:
|
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: '0'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
154
|
+
name: pg
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
142
156
|
requirements:
|
143
|
-
- - "
|
157
|
+
- - ">="
|
144
158
|
- !ruby/object:Gem::Version
|
145
|
-
version: '
|
159
|
+
version: '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: '
|
166
|
+
version: '0'
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
168
|
+
name: sqlite3
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
156
170
|
requirements:
|
157
|
-
- - "
|
171
|
+
- - ">="
|
158
172
|
- !ruby/object:Gem::Version
|
159
|
-
version: '
|
173
|
+
version: '0'
|
160
174
|
type: :development
|
161
175
|
prerelease: false
|
162
176
|
version_requirements: !ruby/object:Gem::Requirement
|
163
177
|
requirements:
|
164
|
-
- - "
|
178
|
+
- - ">="
|
165
179
|
- !ruby/object:Gem::Version
|
166
|
-
version: '
|
180
|
+
version: '0'
|
167
181
|
- !ruby/object:Gem::Dependency
|
168
|
-
name:
|
182
|
+
name: database_cleaner-active_record
|
169
183
|
requirement: !ruby/object:Gem::Requirement
|
170
184
|
requirements:
|
171
185
|
- - ">="
|