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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7da479ed93b1e8e6aa8e91e080356e71b39061a647960175c49ef0f5a1b90855
4
- data.tar.gz: 021aaa044351b96fec1566c1e900f816908cc9a7dcd53d7d8b2a547e7d120872
3
+ metadata.gz: a46db4e821b0a8fb7f661ed539c18c6509b0a644b3bc0f790c0619ab72ff4108
4
+ data.tar.gz: f6ae9809a6a82c9a1de24ecf7d79b9f0cc6cab530579751df919832c0fa3593e
5
5
  SHA512:
6
- metadata.gz: 6f4b5be13f85b953aced1c4269539d5abe5c2611a22bbc3fdda2c19c8254e872116b51ec235e856015e0574f8439d761d3eb433c6f94499683590084814b560d
7
- data.tar.gz: fb29f358eca0b1186afd6cb1417538bac16731a8a2c1faf06c9526afd7e00bc93bcbdfd642b1a8912b02fbe39318842e8730a738586e64ed5df5d7915e94a6b2
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.5.1)
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
- query = "@model.where(\"#{key} #{type} :query\", "
63
- query += "query: \"%\#{#{filter}}%\")" if mode == :circumfix
64
- query += "query: \"%\#{#{filter}}\")" if mode == :prefix
65
- query += "query: \"\#{#{filter}}%\")" if mode == :suffix
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
- query = "where(\"#{key}.#{leaf} #{type} :query\", "
139
- query += "query: \"%\#{#{filter}}%\")" if mode == :circumfix
140
- query += "query: \"%\#{#{filter}}\")" if mode == :prefix
141
- query += "query: \"\#{#{filter}}%\")" if mode == :suffix
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
 
@@ -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(model)
86
- @model = (model.is_a?(Class) ? model : Object.const_get(model.capitalize))
87
- class_eval "def model; @model ||= #{@model}; end;"
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
@@ -1,3 +1,3 @@
1
1
  module Rokaki
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
data/rokaki.gemspec CHANGED
@@ -41,4 +41,5 @@ Gem::Specification.new do |spec|
41
41
  spec.add_development_dependency 'rake', '~> 10.0'
42
42
  spec.add_development_dependency 'rspec', '~> 3.0'
43
43
  spec.add_development_dependency 'sqlite3'
44
+ spec.add_development_dependency 'pg'
44
45
  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.6.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-07 00:00:00.000000000 Z
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