groovy 0.4.2 → 0.4.7
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/example/basic.rb +15 -1
- data/lib/groovy/model.rb +38 -31
- data/lib/groovy/query.rb +42 -19
- data/lib/groovy/schema.rb +23 -12
- data/lib/groovy/version.rb +1 -1
- data/spec/model_spec.rb +31 -1
- data/spec/query_spec.rb +13 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43812d3bd8ef9579ceed22b3d19e78378ceb3a924bfc8d6c0983e49199c26c88
|
4
|
+
data.tar.gz: 5960ca73a253d62f31301995c8f643bcaa084a99140b5f59eee0161c816d20e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22cc09a73d9804f5d5e1cb432d3948ff24ef9a28dbd84b5a403b3709477d013089617ebf19b23f4d3450c3c7dc8e15c01ab527698c5efa5821c9d351056777ad
|
7
|
+
data.tar.gz: 809b9fa8e3158df7afeb6e80967d7156772094b21b69f6fe7d9f5e6db03626fe8a9b2ee123f89c7bf791ef6e195415524b1e967291d836becdc6173fbd0bfbfc
|
data/example/basic.rb
CHANGED
@@ -28,4 +28,18 @@ populate if Product.count == 0
|
|
28
28
|
|
29
29
|
# 50_000 products: 50M
|
30
30
|
# 100_000 products: 50M
|
31
|
-
# 500_000 products: 62M
|
31
|
+
# 500_000 products: 62M
|
32
|
+
|
33
|
+
module MemInfo
|
34
|
+
KERNEL_PAGE_SIZE = `getconf PAGESIZE`.chomp.to_i rescue 4096
|
35
|
+
STATM_PATH = "/proc/#{Process.pid}/statm"
|
36
|
+
STATM_FOUND = File.exist?(STATM_PATH)
|
37
|
+
def self.rss
|
38
|
+
STATM_FOUND ? (File.read(STATM_PATH).split(' ')[1].to_i * KERNEL_PAGE_SIZE) / 1024 : 0
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
puts MemInfo.rss
|
43
|
+
prices = Product.all.map { |x| x.price }
|
44
|
+
puts prices.inspect
|
45
|
+
puts MemInfo.rss
|
data/lib/groovy/model.rb
CHANGED
@@ -150,7 +150,6 @@ module Groovy
|
|
150
150
|
# Groonga["#{table_name}.#{name}"] # .search, .similar_search, etc
|
151
151
|
# end
|
152
152
|
|
153
|
-
|
154
153
|
def index_search(column, query, options = {}, &block)
|
155
154
|
results = table.select { |rec| rec[column].match(query) }
|
156
155
|
render_results(results, &block)
|
@@ -187,16 +186,6 @@ module Groovy
|
|
187
186
|
query
|
188
187
|
end
|
189
188
|
|
190
|
-
def first(num = 1)
|
191
|
-
arr = limit(num)
|
192
|
-
num == 1 ? arr.first : arr
|
193
|
-
end
|
194
|
-
|
195
|
-
def last(num = 1)
|
196
|
-
arr = all.sort_by(_id: :desc).limit(num)
|
197
|
-
num == 1 ? arr.first : arr
|
198
|
-
end
|
199
|
-
|
200
189
|
def query
|
201
190
|
query_class.new(self, table)
|
202
191
|
end
|
@@ -208,7 +197,7 @@ module Groovy
|
|
208
197
|
end
|
209
198
|
end
|
210
199
|
|
211
|
-
[:select, :find_each, :find_by, :search, :where, :not, :sort_by, :limit, :offset, :paginate, :in_batches].each do |scope_method|
|
200
|
+
[:first, :last, :select, :find_each, :find_by, :search, :where, :not, :sort_by, :limit, :offset, :paginate, :in_batches].each do |scope_method|
|
212
201
|
define_method scope_method do |*args, &block|
|
213
202
|
query.public_send(scope_method, *args, &block)
|
214
203
|
end
|
@@ -221,6 +210,12 @@ module Groovy
|
|
221
210
|
set_timestamp(attributes, :created_at)
|
222
211
|
set_timestamp(attributes, :updated_at)
|
223
212
|
|
213
|
+
# remove nil attributes for integer columns, otherwise
|
214
|
+
# we get a TypeError (no implicit conversion from nil to integer)
|
215
|
+
attributes.each do |k, v|
|
216
|
+
attributes.delete(k) if v.nil? # && schema.integer_columns.include?(k)
|
217
|
+
end
|
218
|
+
|
224
219
|
if table.support_key?
|
225
220
|
raise "Key required" if key.nil?
|
226
221
|
table.add(key, attributes)
|
@@ -287,17 +282,17 @@ module Groovy
|
|
287
282
|
end
|
288
283
|
end
|
289
284
|
|
290
|
-
attr_reader :id, :
|
285
|
+
attr_reader :id, :record, :changes
|
291
286
|
|
292
287
|
def initialize(attrs = nil, record = nil, key = nil)
|
293
288
|
@attributes, @vectors, @_key = {}, {}, key # key is used on creation only
|
294
289
|
|
295
290
|
if set_record(record)
|
296
|
-
|
291
|
+
# load_attributes_from_record(record)
|
297
292
|
else
|
298
293
|
attrs ||= {}
|
299
294
|
unless attrs.is_a?(Hash)
|
300
|
-
raise ArgumentError.new("Attributes should be a Hash")
|
295
|
+
raise ArgumentError.new("Attributes should be a Hash, not a #{attrs.class}")
|
301
296
|
end
|
302
297
|
|
303
298
|
# don't call set_attributes since we don't want to call
|
@@ -311,8 +306,13 @@ module Groovy
|
|
311
306
|
|
312
307
|
# get reference to the actual record in the Groonga table,
|
313
308
|
# not the temporary one we get as part of a search result.
|
314
|
-
def load_record
|
315
|
-
|
309
|
+
# def load_record
|
310
|
+
# self.class.table[id]
|
311
|
+
# end
|
312
|
+
|
313
|
+
def attributes
|
314
|
+
load_attributes_from_record # populate missing
|
315
|
+
@attributes
|
316
316
|
end
|
317
317
|
|
318
318
|
def inspect
|
@@ -325,7 +325,9 @@ module Groovy
|
|
325
325
|
end
|
326
326
|
|
327
327
|
def [](key)
|
328
|
-
|
328
|
+
k = key.to_sym
|
329
|
+
@attributes[k] = get_record_attribute(k) unless @attributes.key?(k)
|
330
|
+
@attributes[k]
|
329
331
|
end
|
330
332
|
|
331
333
|
def []=(key, val)
|
@@ -386,11 +388,15 @@ module Groovy
|
|
386
388
|
end
|
387
389
|
|
388
390
|
def reload
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
391
|
+
unless new_record?
|
392
|
+
# raise RecordNotPersisted if id.nil?
|
393
|
+
# ensure_persisted!
|
394
|
+
rec = self.class.table[id] # _key
|
395
|
+
set_record(rec)
|
396
|
+
# load_attributes_from_record
|
397
|
+
end
|
398
|
+
|
399
|
+
@attributes = {}
|
394
400
|
@changes = {}
|
395
401
|
self
|
396
402
|
end
|
@@ -400,18 +406,19 @@ module Groovy
|
|
400
406
|
end
|
401
407
|
|
402
408
|
def ==(other)
|
403
|
-
self.id == other.id
|
409
|
+
self.class == other.class && self.id == other.id
|
404
410
|
end
|
405
411
|
|
406
412
|
def <=>(other)
|
407
|
-
self.id <=> other.id
|
413
|
+
self.class == other.class && self.id <=> other.id
|
408
414
|
end
|
409
415
|
|
410
416
|
private
|
411
417
|
|
412
418
|
def get_record_attribute(key)
|
419
|
+
return if record.nil?
|
413
420
|
val = record[key]
|
414
|
-
if self.class.schema.
|
421
|
+
if self.class.schema.time_columns.include?(key)
|
415
422
|
fix_time_value(val)
|
416
423
|
else
|
417
424
|
val
|
@@ -427,15 +434,15 @@ module Groovy
|
|
427
434
|
# record.respond_to?(:_key) ? record._key : id
|
428
435
|
# end
|
429
436
|
|
430
|
-
def
|
437
|
+
def load_attributes_from_record
|
431
438
|
self.class.attribute_names.each do |col|
|
432
|
-
public_send("#{col}=", get_record_attribute(col))
|
439
|
+
public_send("#{col}=", get_record_attribute(col)) unless @attributes.key?(col)
|
433
440
|
end
|
434
441
|
end
|
435
442
|
|
436
443
|
def set_attribute(key, val)
|
437
|
-
changes[key.to_sym] = [self[key], val] if changes # nil
|
438
|
-
attributes[key.to_sym] = val
|
444
|
+
changes[key.to_sym] = [self[key], val] if changes # nil before initializing
|
445
|
+
@attributes[key.to_sym] = val
|
439
446
|
end
|
440
447
|
|
441
448
|
def get_ref(name)
|
@@ -460,7 +467,7 @@ module Groovy
|
|
460
467
|
|
461
468
|
def create
|
462
469
|
fire_callbacks(:before_create)
|
463
|
-
set_record(self.class.insert(attributes, @_key))
|
470
|
+
set_record(self.class.insert(@attributes, @_key))
|
464
471
|
fire_callbacks(:after_create)
|
465
472
|
self
|
466
473
|
end
|
data/lib/groovy/query.rb
CHANGED
@@ -3,9 +3,11 @@ module Groovy
|
|
3
3
|
class Query
|
4
4
|
|
5
5
|
include Enumerable
|
6
|
+
|
6
7
|
AND = '+'.freeze
|
7
8
|
NOT = '-'.freeze
|
8
9
|
PER_PAGE = 50.freeze
|
10
|
+
# ESCAPE_CHARS_REGEX = /([\(\)\/\\])/.freeze
|
9
11
|
VALID_QUERY_CHARS = 'a-zA-Z0-9_\.,&-'.freeze
|
10
12
|
REMOVE_INVALID_CHARS_REGEX = Regexp.new('[^\s' + VALID_QUERY_CHARS + ']').freeze
|
11
13
|
|
@@ -81,7 +83,7 @@ module Groovy
|
|
81
83
|
add_param(AND + [key, val.max].join(':<=')) if val.max # gte
|
82
84
|
|
83
85
|
elsif val.is_a?(Regexp)
|
84
|
-
str = val.source.gsub(REMOVE_INVALID_CHARS_REGEX, '')
|
86
|
+
str = val.source.gsub('/', '_slash_').gsub('(', '_openp_').gsub(')', '_closep_').gsub(REMOVE_INVALID_CHARS_REGEX, '')
|
85
87
|
param = val.source[0] == '^' ? ':^' : val.source[-1] == '$' ? ':$' : ':~' # starts with or regexp
|
86
88
|
add_param(AND + [key, str.downcase].join(param)) # regex must be downcase
|
87
89
|
|
@@ -115,7 +117,7 @@ module Groovy
|
|
115
117
|
add_param(AND + [key, val.max].join(':>=')) if val.max # lte, nil if range.max is -1
|
116
118
|
|
117
119
|
elsif val.is_a?(Regexp)
|
118
|
-
str = val.source.gsub(REMOVE_INVALID_CHARS_REGEX, '')
|
120
|
+
str = val.source.gsub('/', '_slash_').gsub('(', '_openp_').gsub(')', '_closep_').gsub(REMOVE_INVALID_CHARS_REGEX, '')
|
119
121
|
param = val.source[0] == '^' ? ':^' : val.source[-1] == '$' ? ':$' : ':~' # starts with or regexp
|
120
122
|
add_param(NOT + [key, str.downcase].join(param)) # regex must be downcase
|
121
123
|
|
@@ -137,12 +139,12 @@ module Groovy
|
|
137
139
|
end
|
138
140
|
|
139
141
|
def limit(num)
|
140
|
-
|
142
|
+
sorting[:limit] = num
|
141
143
|
self
|
142
144
|
end
|
143
145
|
|
144
146
|
def offset(num)
|
145
|
-
|
147
|
+
sorting[:offset] = num
|
146
148
|
self
|
147
149
|
end
|
148
150
|
|
@@ -154,8 +156,8 @@ module Groovy
|
|
154
156
|
|
155
157
|
# sort_by(title: :asc)
|
156
158
|
def sort_by(hash)
|
157
|
-
if hash.is_a?(String) || hash.is_a?(Symbol) # e.g. 'title.desc' or :title (asc by default)
|
158
|
-
param, dir = hash.to_s.split(
|
159
|
+
if hash.is_a?(String) || hash.is_a?(Symbol) # e.g. 'title.desc', 'title desc' or :title (asc by default)
|
160
|
+
param, dir = hash.to_s.split(/\s|\./)
|
159
161
|
hash = {}
|
160
162
|
hash[param] = dir || 'asc'
|
161
163
|
end
|
@@ -190,11 +192,16 @@ module Groovy
|
|
190
192
|
end
|
191
193
|
|
192
194
|
def [](index)
|
193
|
-
|
195
|
+
if r = results[index]
|
196
|
+
model.new_from_record(r)
|
197
|
+
end
|
194
198
|
end
|
195
199
|
|
196
200
|
def each(&block)
|
197
|
-
records.each { |r| block.call(r) }
|
201
|
+
# records.each { |r| block.call(r) }
|
202
|
+
results.each_with_index do |r, index|
|
203
|
+
yield model.new_from_record(r)
|
204
|
+
end
|
198
205
|
end
|
199
206
|
|
200
207
|
def update_all(attrs)
|
@@ -206,35 +213,50 @@ module Groovy
|
|
206
213
|
@total_entries
|
207
214
|
end
|
208
215
|
|
209
|
-
def
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
216
|
+
def first(num = 1)
|
217
|
+
limit(num)
|
218
|
+
num == 1 ? records.first : records
|
219
|
+
end
|
220
|
+
|
221
|
+
def last(num = 1)
|
222
|
+
if sorting[:by]
|
223
|
+
get_last(num)
|
224
|
+
else # no sorting, so
|
225
|
+
sort_by(_id: :desc).limit(num)
|
226
|
+
# if last(2) or more, then re-sort by ascending ID
|
227
|
+
num == 1 ? records.first : records.sort { |a,b| a.id <=> b.id }
|
214
228
|
end
|
215
229
|
end
|
216
230
|
|
217
231
|
def in_batches(of: 1000, from: nil, &block)
|
218
|
-
|
219
|
-
|
232
|
+
sorting[:limit] = of
|
233
|
+
sorting[:offset] = from || 0
|
220
234
|
|
221
235
|
while results.any?
|
222
236
|
yield to_a
|
223
237
|
break if results.size < of
|
224
238
|
|
225
|
-
|
239
|
+
sorting[:offset] += of
|
226
240
|
@records = @results = nil # reset
|
227
241
|
end
|
228
242
|
end
|
229
243
|
|
244
|
+
private
|
245
|
+
attr_reader :model, :table, :options, :select_block
|
246
|
+
|
230
247
|
def records
|
231
248
|
@records ||= results.map do |r|
|
232
249
|
model.new_from_record(r)
|
233
250
|
end
|
234
251
|
end
|
235
252
|
|
236
|
-
|
237
|
-
|
253
|
+
def get_last(count = 1)
|
254
|
+
if count > 1
|
255
|
+
records[(size-count)..-1]
|
256
|
+
else
|
257
|
+
records[size-1]
|
258
|
+
end
|
259
|
+
end
|
238
260
|
|
239
261
|
def add_param(param)
|
240
262
|
raise "Select block already given!" if select_block
|
@@ -264,7 +286,7 @@ module Groovy
|
|
264
286
|
|
265
287
|
@total_entries = set.size
|
266
288
|
|
267
|
-
debug "Sorting with #{sort_key_and_order}
|
289
|
+
debug "Sorting with #{sort_key_and_order} (options: #{sorting.inspect})"
|
268
290
|
set = set.sort(sort_key_and_order, {
|
269
291
|
limit: sorting[:limit],
|
270
292
|
offset: sorting[:offset], # [sorting[:offset], @total_entries].min
|
@@ -296,6 +318,7 @@ module Groovy
|
|
296
318
|
query = parameters.join(' ').split(/ or /i).map do |part|
|
297
319
|
part.gsub(' ', ' ') # replace double with single spaces
|
298
320
|
.gsub(space_regex, '\ \1') # escape spaces before word letters
|
321
|
+
.gsub('_slash_', '\/').gsub('_openp_', '\(').gsub('_closep_', '\)')
|
299
322
|
.gsub(/(\d\d):(\d\d):(\d\d)/, '\1\:\2\:\3') # escape hh:mm:ss in timestamps
|
300
323
|
end.join(' OR ').sub(/^-/, '_id:>0 -') #.gsub(' OR -', ' -')
|
301
324
|
end
|
data/lib/groovy/schema.rb
CHANGED
@@ -26,6 +26,7 @@ module Groovy
|
|
26
26
|
def initialize(context, table_name, opts = {})
|
27
27
|
@context, @table_name, @opts = context, table_name, opts || {}
|
28
28
|
@spec, @index_columns = {}, []
|
29
|
+
@cache = {}
|
29
30
|
end
|
30
31
|
|
31
32
|
def table
|
@@ -33,35 +34,43 @@ module Groovy
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def search_table
|
36
|
-
@search_table ||= context[SEARCH_TABLE_NAME]
|
37
|
+
@cache[:search_table] ||= context[SEARCH_TABLE_NAME]
|
37
38
|
end
|
38
39
|
|
39
40
|
def column_names
|
40
|
-
get_names
|
41
|
+
@cache[:column_names] ||= get_names(table.columns)
|
41
42
|
end
|
42
43
|
|
43
44
|
def singular_references
|
44
|
-
|
45
|
-
get_names(table.columns.select(&:reference_column?).reject(&:vector?))
|
45
|
+
@cache[:singular_references] ||= get_names(table.columns.select(&:reference_column?).reject(&:vector?))
|
46
46
|
end
|
47
47
|
|
48
48
|
def plural_references
|
49
|
-
|
50
|
-
get_names(table.columns.select(&:vector?))
|
49
|
+
@cache[:plural_references] ||= get_names(table.columns.select(&:vector?))
|
51
50
|
end
|
52
51
|
|
53
52
|
def attribute_columns
|
54
|
-
|
55
|
-
get_names(table.columns.select { |c| c.column? && !c.reference_column? && !c.vector? })
|
53
|
+
@cache[:attribute_columns] ||= get_names(table.columns.select { |c| c.column? && !c.reference_column? && !c.vector? })
|
56
54
|
end
|
57
55
|
|
58
56
|
def time_columns
|
59
|
-
|
60
|
-
get_names(table.columns.select { |c| c.column? && c.range.name == 'Time' })
|
57
|
+
@cache[:time_columns] ||= columns_by_type('Time')
|
61
58
|
end
|
62
59
|
|
63
|
-
def
|
64
|
-
|
60
|
+
def integer_columns
|
61
|
+
@cache[:integer_columns] ||= columns_by_type('Int32')
|
62
|
+
end
|
63
|
+
|
64
|
+
def boolean_columns
|
65
|
+
@cache[:boolean_columns] ||= columns_by_type('Bool')
|
66
|
+
end
|
67
|
+
|
68
|
+
def columns_by_type(type)
|
69
|
+
get_names(table.columns.select { |c| c.column? && c.range.name == type })
|
70
|
+
end
|
71
|
+
|
72
|
+
def reload
|
73
|
+
@cache = {}
|
65
74
|
end
|
66
75
|
|
67
76
|
def rebuild!
|
@@ -105,6 +114,8 @@ module Groovy
|
|
105
114
|
@index_columns.each do |col|
|
106
115
|
add_index_on(col)
|
107
116
|
end
|
117
|
+
|
118
|
+
reload
|
108
119
|
self
|
109
120
|
end
|
110
121
|
|
data/lib/groovy/version.rb
CHANGED
data/spec/model_spec.rb
CHANGED
@@ -17,7 +17,7 @@ describe Groovy::Model do
|
|
17
17
|
describe '.scope' do
|
18
18
|
|
19
19
|
before :all do
|
20
|
-
TestProduct.class_eval do
|
20
|
+
TestProduct.class_eval do
|
21
21
|
scope :with_name, -> (name) { where(name: name) if name }
|
22
22
|
scope :by_price_asc, -> { sort_by(price: :asc) }
|
23
23
|
scope :cheapest, -> { by_price_asc }
|
@@ -49,6 +49,13 @@ describe Groovy::Model do
|
|
49
49
|
end
|
50
50
|
|
51
51
|
describe '.create' do
|
52
|
+
|
53
|
+
it 'does not explode when inserting nil values for columns' do
|
54
|
+
expect do
|
55
|
+
TestProduct.create({ price: nil })
|
56
|
+
end.not_to raise_error
|
57
|
+
end
|
58
|
+
|
52
59
|
end
|
53
60
|
|
54
61
|
describe '.find' do
|
@@ -60,6 +67,7 @@ describe Groovy::Model do
|
|
60
67
|
describe '.delete_all' do
|
61
68
|
|
62
69
|
before do
|
70
|
+
TestProduct.delete_all
|
63
71
|
@first = TestProduct.create!(name: 'A product', price: 100)
|
64
72
|
@second = TestProduct.create!(name: 'Another product', price: 200)
|
65
73
|
expect(TestProduct.count).to eq(2)
|
@@ -78,6 +86,28 @@ describe Groovy::Model do
|
|
78
86
|
end
|
79
87
|
|
80
88
|
describe '#[]' do
|
89
|
+
it 'reads value from record' do
|
90
|
+
prod = TestProduct.create!(name: 'A product', price: 100)
|
91
|
+
expect(prod.name).to eq('A product')
|
92
|
+
expect(prod['name']).to eq('A product')
|
93
|
+
expect(prod[:name]).to eq('A product')
|
94
|
+
|
95
|
+
prod = TestProduct.find(prod.id)
|
96
|
+
expect(prod.name).to eq('A product')
|
97
|
+
expect(prod['name']).to eq('A product')
|
98
|
+
expect(prod[:name]).to eq('A product')
|
99
|
+
|
100
|
+
prod = TestProduct.new
|
101
|
+
expect(prod.name).to eq(nil)
|
102
|
+
prod.name = 'Another product'
|
103
|
+
expect(prod.name).to eq('Another product')
|
104
|
+
prod.reload
|
105
|
+
expect(prod.name).to eq(nil)
|
106
|
+
prod.name = 'Another product'
|
107
|
+
prod.save
|
108
|
+
prod.reload
|
109
|
+
expect(prod.name).to eq('Another product')
|
110
|
+
end
|
81
111
|
end
|
82
112
|
|
83
113
|
describe '#[]=' do
|
data/spec/query_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe Groovy::Query do
|
|
8
8
|
@p1 = TestProduct.create!(name: "Product 1", visible: true, price: 10, tag_list: 'one, number two & three')
|
9
9
|
@p2 = TestProduct.create!(name: "Product 2", visible: false, price: 20, tag_list: 'number two, three')
|
10
10
|
@p3 = TestProduct.create!(name: "Product 3: The Best", visible: true, price: 30, tag_list: nil)
|
11
|
-
@p4 = TestProduct.create!(name: "Product 4", visible: false, price: 40, tag_list: 'one, number two')
|
11
|
+
@p4 = TestProduct.create!(name: "Product 4", visible: false, price: 40, tag_list: 'one, number two / something')
|
12
12
|
@p5 = TestProduct.create!(name: "Product 5", visible: true, price: 50, tag_list: '')
|
13
13
|
end
|
14
14
|
|
@@ -124,6 +124,12 @@ describe Groovy::Query do
|
|
124
124
|
res = TestProduct.where(tag_list: /two & three/)
|
125
125
|
expect(res.map(&:id)).to eq([@p1.id])
|
126
126
|
end
|
127
|
+
|
128
|
+
it 'works with slashes' do
|
129
|
+
str = 'two / something'
|
130
|
+
res = TestProduct.where(tag_list: /#{str}/)
|
131
|
+
expect(res.map(&:id)).to eq([@p4.id])
|
132
|
+
end
|
127
133
|
end
|
128
134
|
|
129
135
|
describe 'starts with regex' do
|
@@ -253,6 +259,12 @@ describe Groovy::Query do
|
|
253
259
|
res = TestProduct.not(tag_list: /two & three/)
|
254
260
|
expect(res.map(&:id)).to eq([@p2.id, @p3.id, @p4.id, @p5.id])
|
255
261
|
end
|
262
|
+
|
263
|
+
it 'works with slashes' do
|
264
|
+
str = 'two / something'
|
265
|
+
res = TestProduct.not(tag_list: /#{str}/)
|
266
|
+
expect(res.map(&:id)).to eq([@p1.id, @p2.id, @p3.id, @p5.id])
|
267
|
+
end
|
256
268
|
end
|
257
269
|
|
258
270
|
describe 'starts with regex' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: groovy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomás Pollak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-10-
|
11
|
+
date: 2020-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rroonga
|