rokaki 0.4.1 → 0.5.0
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/README.md +9 -8
- data/lib/rokaki/filter_model/like_keys.rb +48 -0
- data/lib/rokaki/filter_model.rb +21 -4
- data/lib/rokaki/version.rb +1 -1
- metadata +3 -3
- data/lib/rokaki/filter_model/like.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebc3f6bb8aab2597c36dd7876792e22395a56a8d099b18cb0d48157e178e81bf
|
4
|
+
data.tar.gz: df20e88198f10346531fa5e5ffde6c8627ef5d19192119b07362865175e7357a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f419fea3a5e3e292d8f44c6006df9ee799d49b4a1aa14820441c2e76c21cb514b668079ea9b727bc64cfb65d107efb162d49a1176bfadc5037b588db2323352
|
7
|
+
data.tar.gz: c683abe335a7d84718da478711c10704830470771e92420cd3ad3540a1062dbb065865e58fdcea4e0d5478cf4ab43293413ed7e0c6337e6f8d8a19e760a67555
|
data/README.md
CHANGED
@@ -23,7 +23,7 @@ To use the basic DSL include the `Rokaki::Filterable` module
|
|
23
23
|
|
24
24
|
A simple example might be:-
|
25
25
|
|
26
|
-
```
|
26
|
+
```ruby
|
27
27
|
class FilterArticles
|
28
28
|
include Rokaki::Filterable
|
29
29
|
|
@@ -55,7 +55,7 @@ You can specify a `filter_key_prefix` and a `filter_key_infix` to change the str
|
|
55
55
|
## ActiveRecord
|
56
56
|
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
57
|
|
58
|
-
```
|
58
|
+
```ruby
|
59
59
|
# Given the models
|
60
60
|
class Author < ActiveRecord::Base
|
61
61
|
has_many :articles, inverse_of: :author
|
@@ -86,17 +86,17 @@ filtered_results = filter.results
|
|
86
86
|
```
|
87
87
|
|
88
88
|
### Partial matching
|
89
|
-
You can use `like` to perform a partial match on a specific key, there are 3 options:- `:prefix`, `:circumfix` and `:suffix`. There are two syntaxes you can use for this:-
|
89
|
+
You can use `like` (or, if you use postgres, the case insensitive `ilike`) to perform a partial match on a specific key, there are 3 options:- `:prefix`, `:circumfix` and `:suffix`. There are two syntaxes you can use for this:-
|
90
90
|
|
91
91
|
#### 1. The `filter` command syntax
|
92
92
|
|
93
93
|
|
94
|
-
```
|
94
|
+
```ruby
|
95
95
|
class ArticleFilter
|
96
96
|
include FilterModel
|
97
97
|
|
98
98
|
filter :article,
|
99
|
-
like: {
|
99
|
+
like: { # you can use ilike here instead if you use postgres and want case insensitive results
|
100
100
|
author: {
|
101
101
|
first_name: :circumfix,
|
102
102
|
last_name: :circumfix
|
@@ -117,12 +117,13 @@ Or
|
|
117
117
|
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`
|
118
118
|
|
119
119
|
|
120
|
-
```
|
120
|
+
```ruby
|
121
121
|
class ArticleFilter
|
122
122
|
include FilterModel
|
123
123
|
|
124
124
|
filters :date, :title, author: [:first_name, :last_name]
|
125
125
|
like title: :circumfix
|
126
|
+
# ilike title: :circumfix # case insensitive postgres mode
|
126
127
|
|
127
128
|
attr_accessor :filters
|
128
129
|
|
@@ -135,7 +136,7 @@ end
|
|
135
136
|
|
136
137
|
Or without the model in the initializer
|
137
138
|
|
138
|
-
```
|
139
|
+
```ruby
|
139
140
|
class ArticleFilter
|
140
141
|
include FilterModel
|
141
142
|
|
@@ -153,7 +154,7 @@ end
|
|
153
154
|
|
154
155
|
Would produce a query with a LIKE which circumfixes '%' around the filter term, like:-
|
155
156
|
|
156
|
-
```
|
157
|
+
```ruby
|
157
158
|
@model = @model.where('title LIKE :query', query: "%#{title}%")
|
158
159
|
```
|
159
160
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rokaki
|
4
|
+
module FilterModel
|
5
|
+
class LikeKeys
|
6
|
+
def initialize(args)
|
7
|
+
@args = args
|
8
|
+
@like_keys = []
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :args, :like_keys
|
12
|
+
|
13
|
+
def call
|
14
|
+
args.keys.each do |key|
|
15
|
+
like_keys << map_keys(args[key], key)
|
16
|
+
end
|
17
|
+
like_keys
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def map_keys(value, key)
|
23
|
+
key_result = {}
|
24
|
+
|
25
|
+
if value.is_a? Hash
|
26
|
+
value.keys.each do |sub_key|
|
27
|
+
sub_value = value[sub_key]
|
28
|
+
|
29
|
+
if sub_value.is_a? Symbol
|
30
|
+
if key_result[key].is_a? Array
|
31
|
+
key_result[key] << sub_key
|
32
|
+
else
|
33
|
+
key_result[key] = [ sub_key ]
|
34
|
+
end
|
35
|
+
|
36
|
+
elsif sub_value.is_a? Hash
|
37
|
+
key_result[key] = map_keys(sub_value, sub_key)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
else
|
41
|
+
key_result = key
|
42
|
+
end
|
43
|
+
|
44
|
+
key_result
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/rokaki/filter_model.rb
CHANGED
@@ -16,6 +16,7 @@ module Rokaki
|
|
16
16
|
filter_model(model)
|
17
17
|
|
18
18
|
like(options[:like]) if options[:like]
|
19
|
+
ilike(options[:ilike]) if options[:ilike]
|
19
20
|
filters(*options[:match]) if options[:match]
|
20
21
|
end
|
21
22
|
|
@@ -54,10 +55,9 @@ module Rokaki
|
|
54
55
|
|
55
56
|
query = ''
|
56
57
|
if @_like_semantics && mode = @_like_semantics[key]
|
57
|
-
query =
|
58
|
-
|
59
|
-
query
|
60
|
-
query += "query: \"\#{#{filter}}%\")" if mode == :suffix
|
58
|
+
query = like_semantics(type: 'LIKE', query: query, filter: filter, mode: mode, key: key)
|
59
|
+
elsif @i_like_semantics && mode = @i_like_semantics[key]
|
60
|
+
query = like_semantics(type: 'ILIKE', query: query, filter: filter, mode: mode, key: key)
|
61
61
|
else
|
62
62
|
query = "@model.where(#{filter}: #{key})"
|
63
63
|
end
|
@@ -65,6 +65,14 @@ module Rokaki
|
|
65
65
|
query
|
66
66
|
end
|
67
67
|
|
68
|
+
def like_semantics(type:, query:, filter:, mode:, key:)
|
69
|
+
query = "@model.where(\"#{key} #{type} :query\", "
|
70
|
+
query += "query: \"%\#{#{filter}}%\")" if mode == :circumfix
|
71
|
+
query += "query: \"%\#{#{filter}}\")" if mode == :prefix
|
72
|
+
query += "query: \"\#{#{filter}}%\")" if mode == :suffix
|
73
|
+
query
|
74
|
+
end
|
75
|
+
|
68
76
|
def _build_deep_chain(keys)
|
69
77
|
name = filter_key_prefix.to_s
|
70
78
|
count = keys.size - 1
|
@@ -120,6 +128,15 @@ module Rokaki
|
|
120
128
|
filters(*key_builder.call)
|
121
129
|
end
|
122
130
|
|
131
|
+
def ilike(args)
|
132
|
+
raise ArgumentError, 'argument mush be a hash' unless args.is_a? Hash
|
133
|
+
@i_like_semantics = (@i_like_semantics || {}).merge(args)
|
134
|
+
|
135
|
+
key_builder = LikeKeys.new(args)
|
136
|
+
|
137
|
+
filters(*key_builder.call)
|
138
|
+
end
|
139
|
+
|
123
140
|
def deep_chain(keys, value)
|
124
141
|
if value.is_a? Hash
|
125
142
|
value.keys.map do |key|
|
data/lib/rokaki/version.rb
CHANGED
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.5.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-10-
|
11
|
+
date: 2019-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -143,7 +143,7 @@ files:
|
|
143
143
|
- bin/setup
|
144
144
|
- lib/rokaki.rb
|
145
145
|
- lib/rokaki/filter_model.rb
|
146
|
-
- lib/rokaki/filter_model/
|
146
|
+
- lib/rokaki/filter_model/like_keys.rb
|
147
147
|
- lib/rokaki/filterable.rb
|
148
148
|
- lib/rokaki/version.rb
|
149
149
|
- rokaki.gemspec
|
File without changes
|