groovy 0.4.2 → 0.4.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|