rokaki 0.10.0 → 0.11.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/.github/workflows/spec.yml +30 -0
- data/Gemfile.lock +16 -1
- data/README.md +18 -7
- data/lib/rokaki/filter_model/basic_filter.rb +11 -0
- data/lib/rokaki/filter_model/nested_filter.rb +28 -12
- data/lib/rokaki/filter_model/nested_like_filters.rb +41 -15
- data/lib/rokaki/filter_model.rb +58 -0
- data/lib/rokaki/version.rb +1 -1
- data/rokaki.gemspec +3 -0
- metadata +30 -3
- data/CODE_OF_CONDUCT.md +0 -74
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a8fb8c022307112af51183df513130d6ad467142320a4db9be178870583c2394
|
|
4
|
+
data.tar.gz: 611539f7d9500f30c5a847a89a7548119c14d4eac47761e9c08b5e706ae9f77c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3648caca4052f03440da996d1aed083c3ba9a29a5f14f06e9e9b2757d4d95f3356e793e22f1b1ebe0a149536a001367e6006d26d8521ce518885e32c36502130
|
|
7
|
+
data.tar.gz: ca064a797447597677bd5b2d2e00f6a2836bc5e69341990ac7da0742ccdc41383834f7a8c9bb6c4089a37e0293786c2536727b5c79d1dabf05a4c9df20f02b77
|
data/.github/workflows/spec.yml
CHANGED
|
@@ -25,8 +25,24 @@ jobs:
|
|
|
25
25
|
- 5432:5432
|
|
26
26
|
# needed because the postgres container does not provide a healthcheck
|
|
27
27
|
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
|
28
|
+
|
|
29
|
+
sqlserver:
|
|
30
|
+
image: mcr.microsoft.com/mssql/server:2022-latest
|
|
31
|
+
env:
|
|
32
|
+
ACCEPT_EULA: "Y"
|
|
33
|
+
MSSQL_SA_PASSWORD: "5QL5£rv£r"
|
|
34
|
+
ports:
|
|
35
|
+
- 1433:1433
|
|
36
|
+
# No built-in healthcheck; we'll wait in a step using nc
|
|
37
|
+
|
|
28
38
|
steps:
|
|
29
39
|
- uses: actions/checkout@v2
|
|
40
|
+
|
|
41
|
+
- name: Install system dependencies
|
|
42
|
+
run: |
|
|
43
|
+
sudo apt-get update
|
|
44
|
+
sudo apt-get install -y build-essential libpq-dev default-libmysqlclient-dev freetds-dev netcat-openbsd
|
|
45
|
+
|
|
30
46
|
- name: Set up Ruby
|
|
31
47
|
uses: ruby/setup-ruby@v1
|
|
32
48
|
with:
|
|
@@ -34,6 +50,20 @@ jobs:
|
|
|
34
50
|
ruby-version: 3.3.0
|
|
35
51
|
# runs 'bundle install' and caches installed gems automatically
|
|
36
52
|
bundler-cache: true
|
|
53
|
+
|
|
54
|
+
- name: Wait for databases to be ready
|
|
55
|
+
shell: bash
|
|
56
|
+
run: |
|
|
57
|
+
for i in {1..60}; do
|
|
58
|
+
nc -z 127.0.0.1 3306 && echo "MySQL up" && break || sleep 1
|
|
59
|
+
done
|
|
60
|
+
for i in {1..60}; do
|
|
61
|
+
nc -z 127.0.0.1 5432 && echo "Postgres up" && break || sleep 1
|
|
62
|
+
done
|
|
63
|
+
for i in {1..120}; do
|
|
64
|
+
nc -z 127.0.0.1 1433 && echo "SQL Server up" && break || sleep 1
|
|
65
|
+
done
|
|
66
|
+
|
|
37
67
|
- name: Run tests
|
|
38
68
|
run: |
|
|
39
69
|
./spec/ordered_run.sh
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
rokaki (0.
|
|
4
|
+
rokaki (0.11.0)
|
|
5
5
|
activesupport
|
|
6
6
|
|
|
7
7
|
GEM
|
|
@@ -13,6 +13,9 @@ GEM
|
|
|
13
13
|
activemodel (= 8.0.3)
|
|
14
14
|
activesupport (= 8.0.3)
|
|
15
15
|
timeout (>= 0.4.0)
|
|
16
|
+
activerecord-sqlserver-adapter (8.0.9)
|
|
17
|
+
activerecord (~> 8.0.0)
|
|
18
|
+
tiny_tds
|
|
16
19
|
activesupport (8.0.3)
|
|
17
20
|
base64
|
|
18
21
|
benchmark (>= 0.3)
|
|
@@ -132,6 +135,16 @@ GEM
|
|
|
132
135
|
sqlite3 (2.7.4-x86_64-linux-musl)
|
|
133
136
|
thor (1.4.0)
|
|
134
137
|
timeout (0.4.3)
|
|
138
|
+
tiny_tds (3.3.0)
|
|
139
|
+
bigdecimal (~> 3)
|
|
140
|
+
tiny_tds (3.3.0-aarch64-linux-gnu)
|
|
141
|
+
bigdecimal (~> 3)
|
|
142
|
+
tiny_tds (3.3.0-aarch64-linux-musl)
|
|
143
|
+
bigdecimal (~> 3)
|
|
144
|
+
tiny_tds (3.3.0-x86_64-linux-gnu)
|
|
145
|
+
bigdecimal (~> 3)
|
|
146
|
+
tiny_tds (3.3.0-x86_64-linux-musl)
|
|
147
|
+
bigdecimal (~> 3)
|
|
135
148
|
tzinfo (2.0.6)
|
|
136
149
|
concurrent-ruby (~> 1.0)
|
|
137
150
|
uri (1.0.3)
|
|
@@ -152,6 +165,7 @@ PLATFORMS
|
|
|
152
165
|
|
|
153
166
|
DEPENDENCIES
|
|
154
167
|
activerecord
|
|
168
|
+
activerecord-sqlserver-adapter
|
|
155
169
|
bundler (~> 2.0)
|
|
156
170
|
database_cleaner-active_record
|
|
157
171
|
factory_bot
|
|
@@ -165,6 +179,7 @@ DEPENDENCIES
|
|
|
165
179
|
rokaki!
|
|
166
180
|
rspec (~> 3.0)
|
|
167
181
|
sqlite3
|
|
182
|
+
tiny_tds
|
|
168
183
|
|
|
169
184
|
BUNDLED WITH
|
|
170
185
|
2.5.3
|
data/README.md
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
# Rokaki
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/rb/rokaki)
|
|
4
|
+
[](https://github.com/tevio/rokaki/actions/workflows/spec.yml)
|
|
4
5
|
|
|
5
|
-
This gem was
|
|
6
|
+
This gem was written to dry up filtering services in ActiveRecord based Rails apps or any plain Ruby app looking to implement "filters" or "faceted" search.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
The overall vision is to abstract away all of the lower level repetitive SQL and relational code to allow you to write model filters in a simple, relatively intuitive way, using ruby hashes and arrays mostly.
|
|
9
|
+
|
|
10
|
+
The DSL allows you to construct complex search models to filter results through without writing any SQL. I would recommend the reader to consult the specs in order to understand the features and syntax in detail, an intermediate understanding of Ruby and rspec TDD, and basic relational logic are recommended.
|
|
11
|
+
|
|
12
|
+
There are two modes of use, `Filterable` (designed for plain Ruby) and `FilterModel` (designed for Rails) that can be activated through the use of two mixins respectively, `include Rokaki::Filterable` or `include Rokaki::FilterModel`.
|
|
8
13
|
## Installation
|
|
9
14
|
|
|
10
15
|
Add this line to your application's Gemfile:
|
|
@@ -137,7 +142,7 @@ You can specify several configuration options, for example a `filter_key_prefix`
|
|
|
137
142
|
## `Rokaki::FilterModel` - Usage
|
|
138
143
|
|
|
139
144
|
### ActiveRecord
|
|
140
|
-
Include `Rokaki::FilterModel` in any ActiveRecord model (only AR >=
|
|
145
|
+
Include `Rokaki::FilterModel` in any ActiveRecord model (only AR >= 8.0.3 tested so far) you can generate the filter keys and the actual filter lookup code using the `filters` keyword on a model like so:-
|
|
141
146
|
|
|
142
147
|
```ruby
|
|
143
148
|
# Given the models
|
|
@@ -173,7 +178,7 @@ You can also filter collections of fields, simply pass an array of filter values
|
|
|
173
178
|
|
|
174
179
|
|
|
175
180
|
### Partial matching
|
|
176
|
-
You can use `like`
|
|
181
|
+
You can use `like` or the case insensitive `ilike` to perform a partial match on a specific field, there are 3 options:- `:prefix`, `:circumfix` and `:suffix`. There are two syntaxes you can use for this:-
|
|
177
182
|
|
|
178
183
|
#### 1. The `filter` command syntax
|
|
179
184
|
|
|
@@ -183,7 +188,7 @@ class ArticleFilter
|
|
|
183
188
|
include Rokaki::FilterModel
|
|
184
189
|
|
|
185
190
|
filter :article,
|
|
186
|
-
like: { # you can use ilike here instead if you
|
|
191
|
+
like: { # you can use ilike here instead if you want case insensitive results
|
|
187
192
|
author: {
|
|
188
193
|
first_name: :circumfix,
|
|
189
194
|
last_name: :circumfix
|
|
@@ -323,7 +328,7 @@ class ArticleFilter
|
|
|
323
328
|
|
|
324
329
|
filters :date, :title, author: [:first_name, :last_name]
|
|
325
330
|
like title: :circumfix
|
|
326
|
-
# ilike title: :circumfix # case insensitive
|
|
331
|
+
# ilike title: :circumfix # case insensitive mode
|
|
327
332
|
|
|
328
333
|
attr_accessor :filters
|
|
329
334
|
|
|
@@ -436,7 +441,13 @@ docker pull mysql
|
|
|
436
441
|
docker run --name rokaki-mysql -e MYSQL_ROOT_PASSWORD=rokaki -e MYSQL_PASSWORD=rokaki -e MYSQL_DATABASE=rokaki -e MYSQL_USER=rokaki -d -p 3306:3306 mysql:latest mysqld
|
|
437
442
|
```
|
|
438
443
|
|
|
439
|
-
|
|
444
|
+
### Specialised test runner
|
|
445
|
+
The test suite is designed to run against all supported database backends, since this can cause problems with timing and connection pools, the recommended way to run the tests is via a shell script.
|
|
446
|
+
|
|
447
|
+
From the rokaki root directory run: `./spec/ordered_run.sh`. This is the same script that runs on the Github CI here: [](https://github.com/tevio/rokaki/actions/workflows/spec.yml)
|
|
448
|
+
|
|
449
|
+
### Standard test runner (only recommended for development cycles)
|
|
450
|
+
You can still run `rake spec` to run the tests, there's no guarantee they will all pass due to race conditions from using multiple db backends (see above), but this mode is recommended for focusing on specific backends or tests during development (comment out what you don't want). You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
440
451
|
|
|
441
452
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
442
453
|
|
|
@@ -38,6 +38,10 @@ module Rokaki
|
|
|
38
38
|
'LIKE'
|
|
39
39
|
elsif db == :mysql
|
|
40
40
|
'LIKE BINARY'
|
|
41
|
+
elsif db == :sqlserver
|
|
42
|
+
'LIKE'
|
|
43
|
+
else
|
|
44
|
+
'LIKE'
|
|
41
45
|
end
|
|
42
46
|
end
|
|
43
47
|
|
|
@@ -46,6 +50,10 @@ module Rokaki
|
|
|
46
50
|
'ILIKE'
|
|
47
51
|
elsif db == :mysql
|
|
48
52
|
'LIKE'
|
|
53
|
+
elsif db == :sqlserver
|
|
54
|
+
'LIKE'
|
|
55
|
+
else
|
|
56
|
+
'LIKE'
|
|
49
57
|
end
|
|
50
58
|
end
|
|
51
59
|
|
|
@@ -94,6 +102,9 @@ module Rokaki
|
|
|
94
102
|
if db == :postgres
|
|
95
103
|
query = "@model.where(\"#{key} #{type} ANY (ARRAY[?])\", "
|
|
96
104
|
query += "prepare_terms(#{filter}, :#{mode}))"
|
|
105
|
+
elsif db == :sqlserver
|
|
106
|
+
# Delegate to helper that supports arrays and escaping with ESCAPE
|
|
107
|
+
query = "sqlserver_like(@model, \"#{key}\", \"#{type}\", #{filter}, :#{mode})"
|
|
97
108
|
else
|
|
98
109
|
query = "@model.where(\"#{key} #{type} :query\", "
|
|
99
110
|
query += "query: \"%\#{#{filter}}%\")" if mode == :circumfix
|
|
@@ -70,6 +70,10 @@ module Rokaki
|
|
|
70
70
|
'LIKE'
|
|
71
71
|
elsif db == :mysql
|
|
72
72
|
'LIKE BINARY'
|
|
73
|
+
elsif db == :sqlserver
|
|
74
|
+
'LIKE'
|
|
75
|
+
else
|
|
76
|
+
'LIKE'
|
|
73
77
|
end
|
|
74
78
|
end
|
|
75
79
|
|
|
@@ -78,6 +82,10 @@ module Rokaki
|
|
|
78
82
|
'ILIKE'
|
|
79
83
|
elsif db == :mysql
|
|
80
84
|
'LIKE'
|
|
85
|
+
elsif db == :sqlserver
|
|
86
|
+
'LIKE'
|
|
87
|
+
else
|
|
88
|
+
'LIKE'
|
|
81
89
|
end
|
|
82
90
|
end
|
|
83
91
|
|
|
@@ -131,19 +139,27 @@ module Rokaki
|
|
|
131
139
|
where = where.join
|
|
132
140
|
|
|
133
141
|
if search_mode
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
search_mode: search_mode,
|
|
139
|
-
key: keys.last.to_s.pluralize,
|
|
140
|
-
leaf: leaf
|
|
141
|
-
)
|
|
142
|
+
if db == :sqlserver
|
|
143
|
+
key_leaf = "#{keys.last.to_s.pluralize}.#{leaf}"
|
|
144
|
+
@filter_methods << "def #{prefix}filter#{infix}#{name};"\
|
|
145
|
+
"sqlserver_like(@model.joins(#{joins}), \"#{key_leaf}\", \"#{type}\", #{prefix}#{name}, :#{search_mode}); end;"
|
|
142
146
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
+
@filter_templates << "@model = #{prefix}filter#{infix}#{name} if #{prefix}#{name};"
|
|
148
|
+
else
|
|
149
|
+
query = build_like_query(
|
|
150
|
+
type: type,
|
|
151
|
+
query: '',
|
|
152
|
+
filter: "#{prefix}#{name}",
|
|
153
|
+
search_mode: search_mode,
|
|
154
|
+
key: keys.last.to_s.pluralize,
|
|
155
|
+
leaf: leaf
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
@filter_methods << "def #{prefix}filter#{infix}#{name};"\
|
|
159
|
+
"@model.joins(#{joins}).#{query}; end;"
|
|
160
|
+
|
|
161
|
+
@filter_templates << "@model = #{prefix}filter#{infix}#{name} if #{prefix}#{name};"
|
|
162
|
+
end
|
|
147
163
|
else
|
|
148
164
|
@filter_methods << "def #{prefix}filter#{infix}#{name};"\
|
|
149
165
|
"@model.joins(#{joins}).where(#{where}); end;"
|
|
@@ -194,22 +194,37 @@ module Rokaki
|
|
|
194
194
|
leaf = nil
|
|
195
195
|
leaf = keys.pop
|
|
196
196
|
|
|
197
|
+
# Compute key_leaf (qualified column) like other branches
|
|
198
|
+
key_leaf = keys.last ? "#{keys.last.to_s.pluralize}.#{leaf}" : leaf
|
|
199
|
+
|
|
200
|
+
if db == :sqlserver
|
|
201
|
+
# Build relation base with joins
|
|
202
|
+
if join_map.empty?
|
|
203
|
+
rel_expr = "@model"
|
|
204
|
+
elsif join_map.is_a?(Array)
|
|
205
|
+
rel_expr = "@model.joins(*#{join_map})"
|
|
206
|
+
else
|
|
207
|
+
rel_expr = "@model.joins(**#{join_map})"
|
|
208
|
+
end
|
|
197
209
|
|
|
198
|
-
|
|
199
|
-
type: type,
|
|
200
|
-
query: '',
|
|
201
|
-
filter: filter_name,
|
|
202
|
-
search_mode: search_mode,
|
|
203
|
-
key: keys.last,
|
|
204
|
-
leaf: leaf
|
|
205
|
-
)
|
|
206
|
-
|
|
207
|
-
if join_map.empty?
|
|
208
|
-
filter_query = "@model.#{query}"
|
|
209
|
-
elsif join_map.is_a?(Array)
|
|
210
|
-
filter_query = "@model.joins(*#{join_map}).#{query}"
|
|
210
|
+
filter_query = "sqlserver_like(#{rel_expr}, \"#{key_leaf}\", \"#{type.to_s.upcase}\", #{filter_name}, :#{search_mode})"
|
|
211
211
|
else
|
|
212
|
-
|
|
212
|
+
query = build_like_query(
|
|
213
|
+
type: type,
|
|
214
|
+
query: '',
|
|
215
|
+
filter: filter_name,
|
|
216
|
+
search_mode: search_mode,
|
|
217
|
+
key: keys.last,
|
|
218
|
+
leaf: leaf
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
if join_map.empty?
|
|
222
|
+
filter_query = "@model.#{query}"
|
|
223
|
+
elsif join_map.is_a?(Array)
|
|
224
|
+
filter_query = "@model.joins(*#{join_map}).#{query}"
|
|
225
|
+
else
|
|
226
|
+
filter_query = "@model.joins(**#{join_map}).#{query}"
|
|
227
|
+
end
|
|
213
228
|
end
|
|
214
229
|
|
|
215
230
|
if mode == or_key
|
|
@@ -225,9 +240,20 @@ module Rokaki
|
|
|
225
240
|
if db == :postgres
|
|
226
241
|
query = "where(\"#{key_leaf} #{type.to_s.upcase} ANY (ARRAY[?])\", "
|
|
227
242
|
query += "prepare_terms(#{filter}, :#{search_mode}))"
|
|
228
|
-
|
|
243
|
+
elsif db == :mysql
|
|
229
244
|
query = "where(\"#{key_leaf} #{type.to_s.upcase} :query\", "
|
|
230
245
|
query += "query: prepare_regex_terms(#{filter}, :#{search_mode}))"
|
|
246
|
+
else # :sqlserver and others
|
|
247
|
+
query = "where(\"#{key_leaf} #{type.to_s.upcase} :query\", "
|
|
248
|
+
if search_mode == :circumfix
|
|
249
|
+
query += "query: \"%\#{#{filter}}%\")"
|
|
250
|
+
elsif search_mode == :prefix
|
|
251
|
+
query += "query: \"%\#{#{filter}}\")"
|
|
252
|
+
elsif search_mode == :suffix
|
|
253
|
+
query += "query: \"\#{#{filter}}%\")"
|
|
254
|
+
else
|
|
255
|
+
query += "query: \"%\#{#{filter}}%\")"
|
|
256
|
+
end
|
|
231
257
|
end
|
|
232
258
|
|
|
233
259
|
query
|
data/lib/rokaki/filter_model.rb
CHANGED
|
@@ -19,6 +19,56 @@ module Rokaki
|
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
# Escape special LIKE characters in SQL Server patterns: %, _, [ and \\
|
|
23
|
+
def escape_like(term)
|
|
24
|
+
term.to_s.gsub(/[\\%_\[]/) { |m| "\\#{m}" }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Build LIKE patterns with proper prefix/suffix/circumfix and escaping for SQL Server
|
|
28
|
+
# Returns a String when param is scalar, or an Array of Strings when param is an Array
|
|
29
|
+
def prepare_like_terms(param, mode)
|
|
30
|
+
if Array === param
|
|
31
|
+
case mode
|
|
32
|
+
when :circumfix
|
|
33
|
+
param.map { |t| "%#{escape_like(t)}%" }
|
|
34
|
+
when :prefix
|
|
35
|
+
param.map { |t| "%#{escape_like(t)}" }
|
|
36
|
+
when :suffix
|
|
37
|
+
param.map { |t| "#{escape_like(t)}%" }
|
|
38
|
+
else
|
|
39
|
+
param.map { |t| "%#{escape_like(t)}%" }
|
|
40
|
+
end
|
|
41
|
+
else
|
|
42
|
+
case mode
|
|
43
|
+
when :circumfix
|
|
44
|
+
"%#{escape_like(param)}%"
|
|
45
|
+
when :prefix
|
|
46
|
+
"%#{escape_like(param)}"
|
|
47
|
+
when :suffix
|
|
48
|
+
"#{escape_like(param)}%"
|
|
49
|
+
else
|
|
50
|
+
"%#{escape_like(param)}%"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Compose a SQL Server LIKE relation supporting arrays of terms (OR chained)
|
|
56
|
+
# column should be a fully qualified column expression, e.g., "authors.first_name" or "cs.title"
|
|
57
|
+
# type is usually "LIKE"
|
|
58
|
+
def sqlserver_like(model, column, type, value, mode)
|
|
59
|
+
terms = prepare_like_terms(value, mode)
|
|
60
|
+
if terms.is_a?(Array)
|
|
61
|
+
return model.none if terms.empty?
|
|
62
|
+
rel = model.where("#{column} #{type} :q0 ESCAPE '\\'", q0: terms[0])
|
|
63
|
+
terms[1..-1]&.each_with_index do |t, i|
|
|
64
|
+
rel = rel.or(model.where("#{column} #{type} :q#{i + 1} ESCAPE '\\'", "q#{i + 1}".to_sym => t))
|
|
65
|
+
end
|
|
66
|
+
rel
|
|
67
|
+
else
|
|
68
|
+
model.where("#{column} #{type} :q ESCAPE '\\'", q: terms)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
22
72
|
def prepare_regex_terms(param, mode)
|
|
23
73
|
if Array === param
|
|
24
74
|
param_map = param.map { |term| ".*#{term}.*" } if mode == :circumfix
|
|
@@ -187,6 +237,10 @@ module Rokaki
|
|
|
187
237
|
elsif @_filter_db == :mysql
|
|
188
238
|
# 'LIKE BINARY'
|
|
189
239
|
'REGEXP'
|
|
240
|
+
elsif @_filter_db == :sqlserver
|
|
241
|
+
'LIKE'
|
|
242
|
+
else
|
|
243
|
+
'LIKE'
|
|
190
244
|
end
|
|
191
245
|
end
|
|
192
246
|
|
|
@@ -196,6 +250,10 @@ module Rokaki
|
|
|
196
250
|
elsif @_filter_db == :mysql
|
|
197
251
|
# 'LIKE'
|
|
198
252
|
'REGEXP'
|
|
253
|
+
elsif @_filter_db == :sqlserver
|
|
254
|
+
'LIKE'
|
|
255
|
+
else
|
|
256
|
+
'LIKE'
|
|
199
257
|
end
|
|
200
258
|
end
|
|
201
259
|
|
data/lib/rokaki/version.rb
CHANGED
data/rokaki.gemspec
CHANGED
|
@@ -47,5 +47,8 @@ Gem::Specification.new do |spec|
|
|
|
47
47
|
spec.add_development_dependency 'mysql2'
|
|
48
48
|
spec.add_development_dependency 'sqlite3'
|
|
49
49
|
spec.add_development_dependency 'database_cleaner-active_record'
|
|
50
|
+
# For SQL Server testing
|
|
51
|
+
spec.add_development_dependency 'tiny_tds'
|
|
52
|
+
spec.add_development_dependency 'activerecord-sqlserver-adapter'
|
|
50
53
|
|
|
51
54
|
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.
|
|
4
|
+
version: 0.11.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: 2025-10-
|
|
11
|
+
date: 2025-10-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -206,6 +206,34 @@ dependencies:
|
|
|
206
206
|
- - ">="
|
|
207
207
|
- !ruby/object:Gem::Version
|
|
208
208
|
version: '0'
|
|
209
|
+
- !ruby/object:Gem::Dependency
|
|
210
|
+
name: tiny_tds
|
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
|
212
|
+
requirements:
|
|
213
|
+
- - ">="
|
|
214
|
+
- !ruby/object:Gem::Version
|
|
215
|
+
version: '0'
|
|
216
|
+
type: :development
|
|
217
|
+
prerelease: false
|
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
219
|
+
requirements:
|
|
220
|
+
- - ">="
|
|
221
|
+
- !ruby/object:Gem::Version
|
|
222
|
+
version: '0'
|
|
223
|
+
- !ruby/object:Gem::Dependency
|
|
224
|
+
name: activerecord-sqlserver-adapter
|
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
|
226
|
+
requirements:
|
|
227
|
+
- - ">="
|
|
228
|
+
- !ruby/object:Gem::Version
|
|
229
|
+
version: '0'
|
|
230
|
+
type: :development
|
|
231
|
+
prerelease: false
|
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
233
|
+
requirements:
|
|
234
|
+
- - ">="
|
|
235
|
+
- !ruby/object:Gem::Version
|
|
236
|
+
version: '0'
|
|
209
237
|
description: A dsl for filtering data in web requests
|
|
210
238
|
email:
|
|
211
239
|
- steve@martian.media
|
|
@@ -219,7 +247,6 @@ files:
|
|
|
219
247
|
- ".rspec"
|
|
220
248
|
- ".ruby-version"
|
|
221
249
|
- ".travis.yml"
|
|
222
|
-
- CODE_OF_CONDUCT.md
|
|
223
250
|
- Gemfile
|
|
224
251
|
- Gemfile.lock
|
|
225
252
|
- Guardfile
|
data/CODE_OF_CONDUCT.md
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# Contributor Covenant Code of Conduct
|
|
2
|
-
|
|
3
|
-
## Our Pledge
|
|
4
|
-
|
|
5
|
-
In the interest of fostering an open and welcoming environment, we as
|
|
6
|
-
contributors and maintainers pledge to making participation in our project and
|
|
7
|
-
our community a harassment-free experience for everyone, regardless of age, body
|
|
8
|
-
size, disability, ethnicity, gender identity and expression, level of experience,
|
|
9
|
-
nationality, personal appearance, race, religion, or sexual identity and
|
|
10
|
-
orientation.
|
|
11
|
-
|
|
12
|
-
## Our Standards
|
|
13
|
-
|
|
14
|
-
Examples of behavior that contributes to creating a positive environment
|
|
15
|
-
include:
|
|
16
|
-
|
|
17
|
-
* Using welcoming and inclusive language
|
|
18
|
-
* Being respectful of differing viewpoints and experiences
|
|
19
|
-
* Gracefully accepting constructive criticism
|
|
20
|
-
* Focusing on what is best for the community
|
|
21
|
-
* Showing empathy towards other community members
|
|
22
|
-
|
|
23
|
-
Examples of unacceptable behavior by participants include:
|
|
24
|
-
|
|
25
|
-
* The use of sexualized language or imagery and unwelcome sexual attention or
|
|
26
|
-
advances
|
|
27
|
-
* Trolling, insulting/derogatory comments, and personal or political attacks
|
|
28
|
-
* Public or private harassment
|
|
29
|
-
* Publishing others' private information, such as a physical or electronic
|
|
30
|
-
address, without explicit permission
|
|
31
|
-
* Other conduct which could reasonably be considered inappropriate in a
|
|
32
|
-
professional setting
|
|
33
|
-
|
|
34
|
-
## Our Responsibilities
|
|
35
|
-
|
|
36
|
-
Project maintainers are responsible for clarifying the standards of acceptable
|
|
37
|
-
behavior and are expected to take appropriate and fair corrective action in
|
|
38
|
-
response to any instances of unacceptable behavior.
|
|
39
|
-
|
|
40
|
-
Project maintainers have the right and responsibility to remove, edit, or
|
|
41
|
-
reject comments, commits, code, wiki edits, issues, and other contributions
|
|
42
|
-
that are not aligned to this Code of Conduct, or to ban temporarily or
|
|
43
|
-
permanently any contributor for other behaviors that they deem inappropriate,
|
|
44
|
-
threatening, offensive, or harmful.
|
|
45
|
-
|
|
46
|
-
## Scope
|
|
47
|
-
|
|
48
|
-
This Code of Conduct applies both within project spaces and in public spaces
|
|
49
|
-
when an individual is representing the project or its community. Examples of
|
|
50
|
-
representing a project or community include using an official project e-mail
|
|
51
|
-
address, posting via an official social media account, or acting as an appointed
|
|
52
|
-
representative at an online or offline event. Representation of a project may be
|
|
53
|
-
further defined and clarified by project maintainers.
|
|
54
|
-
|
|
55
|
-
## Enforcement
|
|
56
|
-
|
|
57
|
-
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
58
|
-
reported by contacting the project team at steve@martian.media. All
|
|
59
|
-
complaints will be reviewed and investigated and will result in a response that
|
|
60
|
-
is deemed necessary and appropriate to the circumstances. The project team is
|
|
61
|
-
obligated to maintain confidentiality with regard to the reporter of an incident.
|
|
62
|
-
Further details of specific enforcement policies may be posted separately.
|
|
63
|
-
|
|
64
|
-
Project maintainers who do not follow or enforce the Code of Conduct in good
|
|
65
|
-
faith may face temporary or permanent repercussions as determined by other
|
|
66
|
-
members of the project's leadership.
|
|
67
|
-
|
|
68
|
-
## Attribution
|
|
69
|
-
|
|
70
|
-
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
|
71
|
-
available at [http://contributor-covenant.org/version/1/4][version]
|
|
72
|
-
|
|
73
|
-
[homepage]: http://contributor-covenant.org
|
|
74
|
-
[version]: http://contributor-covenant.org/version/1/4/
|