rokaki 0.8.3 → 0.8.3.1

Sign up to get free protection for your applications and to get access to all the features.
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
  - - ">="