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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 53402d2c7b2fca689234d8bed13602eef1bac7a161b09fe15da517da8939e5ac
4
- data.tar.gz: 2a903781f7d5f2e4b90c419def1dc5a2b8289798a708a66e6be91604de02de86
3
+ metadata.gz: 8f2a62792073dd9728a44158d6f30dc4f0f8119316bda3a3846c16fc2abc57f7
4
+ data.tar.gz: 80e9bfc7b677b7e291996c5bda1fc6652ddfbb592b31083446ef992755f00404
5
5
  SHA512:
6
- metadata.gz: 7cd1957fe50f484e465a7c592a6e770e6a0e46975479ea4863deab66434031936d477b852ae8b72095943bc0db47d1379cd089b280485f5d4a7aa90d50cc6a12
7
- data.tar.gz: 9b966c7cafd777655fcb6f20b70b3c331d2f8175c8bf22c49ef4295188f25ae15a7b8581738f4fbac5eb5e605b129088936c8588097015d366080b8866687891
6
+ metadata.gz: 6570c3b380c66092b3a583b1c94a51f8364f06d936522cc72676e23c3aa1717b4b89cc65c0d3ed6e6d67291b3c7e1c3c83d8254acd7df8f9971700b314a71aa0
7
+ data.tar.gz: 913e7bf304da343a4dce4d061dbcdaa37c2f26d7a396e590e393a224a4ac7c30c439f8d085de1a865828c9931f1bcf99dc66b32c8494e8481dcc6c5539d03ea6
data/.gitignore CHANGED
@@ -11,3 +11,4 @@
11
11
  .rspec_status
12
12
  tags
13
13
  *.gem
14
+ TODO.md
@@ -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
  [![Gem Version](https://badge.fury.io/rb/rokaki.svg)](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(author: { first_name: author_first_name }) if author_first_name
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(fytlerz: { query: 'H2O' })
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`
@@ -11,7 +11,4 @@ require 'rokaki/filter_model/nested_like_filters'
11
11
 
12
12
  module Rokaki
13
13
  class Error < StandardError; end
14
-
15
- # include this module for filters dsl in an object
16
- #
17
14
  end
@@ -8,7 +8,7 @@ module Rokaki
8
8
  end
9
9
 
10
10
  def prepare_terms(param, mode)
11
- if param.is_a? Array
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.is_a?(Symbol)
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.is_a?(Array)
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 parent_result.is_a?(Symbol) && parent_result != key
45
+ if Symbol === parent_result && parent_result != key
46
46
  result[previous_key] = [parent_result, key]
47
- elsif parent_result.is_a?(Array)
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
- if res.is_a? Symbol
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
- if res.is_a? Symbol
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
@@ -66,7 +66,7 @@ module Rokaki
66
66
  end
67
67
 
68
68
  def _build_deep_chain(keys)
69
- name = '' # prefix.to_s
69
+ name = ''
70
70
  count = keys.size - 1
71
71
 
72
72
  joins_before = []
@@ -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
- build_filter(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])
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
- build_filter(keys: key_path_item.dup, join_map: join_map.result, filter_name: filter_name, search_mode: search_modes[index])
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 build_filter(keys: , join_map:, mode: :and, filter_name:, search_mode:)
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 == :or
215
+ if mode == or_key
216
216
  @filter_queries << [@filter_queries.pop, filter_query].flatten
217
217
  else
218
218
  @filter_queries << filter_query
@@ -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.is_a? Hash
15
- _nested_key filter_key if filter_key.is_a? Hash
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.is_a? Hash
22
- _nested_map query_field, filter_key if filter_key.is_a? Hash
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
 
@@ -1,3 +1,3 @@
1
1
  module Rokaki
2
- VERSION = "0.8.3"
2
+ VERSION = "0.8.3.1"
3
3
  end
@@ -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-26 00:00:00.000000000 Z
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: factory_bot
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: guard
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: guard-rspec
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: pg
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: pry
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: pry-byebug
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: rake
154
+ name: pg
141
155
  requirement: !ruby/object:Gem::Requirement
142
156
  requirements:
143
- - - "~>"
157
+ - - ">="
144
158
  - !ruby/object:Gem::Version
145
- version: '13.0'
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: '13.0'
166
+ version: '0'
153
167
  - !ruby/object:Gem::Dependency
154
- name: rspec
168
+ name: sqlite3
155
169
  requirement: !ruby/object:Gem::Requirement
156
170
  requirements:
157
- - - "~>"
171
+ - - ">="
158
172
  - !ruby/object:Gem::Version
159
- version: '3.0'
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: '3.0'
180
+ version: '0'
167
181
  - !ruby/object:Gem::Dependency
168
- name: sqlite3
182
+ name: database_cleaner-active_record
169
183
  requirement: !ruby/object:Gem::Requirement
170
184
  requirements:
171
185
  - - ">="