groovy 0.4.6 → 0.5.1
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 +3 -0
- data/example/basic.rb +15 -1
- data/example/relations.rb +1 -0
- data/lib/groovy/model.rb +36 -20
- data/lib/groovy/query.rb +17 -12
- data/lib/groovy/schema.rb +14 -14
- data/lib/groovy/vector.rb +21 -0
- data/lib/groovy/version.rb +1 -1
- data/spec/model_spec.rb +22 -0
- 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: af9ef6dd23a84a0887fa26436fb1a3f98112621f25b1088c7e5835706fedefc9
|
4
|
+
data.tar.gz: 4fa395ca4c1f32c3d31df1707a2ee66e2c6fabf0550957962b7d5efa3fd7458c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c6936e830cb7449843a43882cf5895b452806ab61ca7f01c2e7c97ae272d0daeb456a2f4d9c16b5cad52c46b8f9902e851b4e6e9c43d27de1d995bdca44fdbf
|
7
|
+
data.tar.gz: dbde160c35f34339e5f155bea793c0c4fd5671916326a34c9c69efe9e266baffb47ed12e0afe5edd7a1fae5ba46abc7c41cc8957cba511be5ad4f3972df09ed9
|
data/README.md
CHANGED
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/example/relations.rb
CHANGED
data/lib/groovy/model.rb
CHANGED
@@ -26,7 +26,7 @@ module Groovy
|
|
26
26
|
# end
|
27
27
|
|
28
28
|
def self.model_from_table(table_name)
|
29
|
-
Kernel.const_get(table_name.sub(/ies$/, 'y').sub(/s$/, '').
|
29
|
+
Kernel.const_get(table_name.to_s.sub(/ies$/, 'y').sub(/s$/, '').classify)
|
30
30
|
end
|
31
31
|
|
32
32
|
def self.included(base)
|
@@ -133,11 +133,11 @@ module Groovy
|
|
133
133
|
end
|
134
134
|
|
135
135
|
def update_all(attrs)
|
136
|
-
|
136
|
+
all.each { |child| child.update_attributes(attrs) }
|
137
137
|
end
|
138
138
|
|
139
139
|
def delete_all
|
140
|
-
#
|
140
|
+
# all.each { |child| child.delete }
|
141
141
|
table.delete { |record| record._id > -1 }
|
142
142
|
end
|
143
143
|
|
@@ -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)
|
@@ -191,14 +190,19 @@ module Groovy
|
|
191
190
|
query_class.new(self, table)
|
192
191
|
end
|
193
192
|
|
193
|
+
def scopes
|
194
|
+
@scopes ||= []
|
195
|
+
end
|
196
|
+
|
194
197
|
def scope(name, obj)
|
198
|
+
scopes.push(name)
|
195
199
|
query_class.add_scope(name, obj)
|
196
200
|
define_singleton_method(name) do |*args|
|
197
201
|
query.public_send(name, *args)
|
198
202
|
end
|
199
203
|
end
|
200
204
|
|
201
|
-
[:first, :last, :select, :
|
205
|
+
[:first, :last, :select, :find_by, :search, :where, :not, :sort_by, :limit, :offset, :paginate, :in_batches].each do |scope_method|
|
202
206
|
define_method scope_method do |*args, &block|
|
203
207
|
query.public_send(scope_method, *args, &block)
|
204
208
|
end
|
@@ -283,13 +287,13 @@ module Groovy
|
|
283
287
|
end
|
284
288
|
end
|
285
289
|
|
286
|
-
attr_reader :id, :
|
290
|
+
attr_reader :id, :record, :changes
|
287
291
|
|
288
292
|
def initialize(attrs = nil, record = nil, key = nil)
|
289
293
|
@attributes, @vectors, @_key = {}, {}, key # key is used on creation only
|
290
294
|
|
291
295
|
if set_record(record)
|
292
|
-
|
296
|
+
# load_attributes_from_record(record)
|
293
297
|
else
|
294
298
|
attrs ||= {}
|
295
299
|
unless attrs.is_a?(Hash)
|
@@ -307,8 +311,13 @@ module Groovy
|
|
307
311
|
|
308
312
|
# get reference to the actual record in the Groonga table,
|
309
313
|
# not the temporary one we get as part of a search result.
|
310
|
-
def load_record
|
311
|
-
|
314
|
+
# def load_record
|
315
|
+
# self.class.table[id]
|
316
|
+
# end
|
317
|
+
|
318
|
+
def attributes
|
319
|
+
load_attributes_from_record # populate missing
|
320
|
+
@attributes
|
312
321
|
end
|
313
322
|
|
314
323
|
def inspect
|
@@ -321,7 +330,9 @@ module Groovy
|
|
321
330
|
end
|
322
331
|
|
323
332
|
def [](key)
|
324
|
-
|
333
|
+
k = key.to_sym
|
334
|
+
@attributes[k] = get_record_attribute(k) unless @attributes.key?(k)
|
335
|
+
@attributes[k]
|
325
336
|
end
|
326
337
|
|
327
338
|
def []=(key, val)
|
@@ -382,11 +393,15 @@ module Groovy
|
|
382
393
|
end
|
383
394
|
|
384
395
|
def reload
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
396
|
+
unless new_record?
|
397
|
+
# raise RecordNotPersisted if id.nil?
|
398
|
+
# ensure_persisted!
|
399
|
+
rec = self.class.table[id] # _key
|
400
|
+
set_record(rec)
|
401
|
+
# load_attributes_from_record
|
402
|
+
end
|
403
|
+
|
404
|
+
@attributes = {}
|
390
405
|
@changes = {}
|
391
406
|
self
|
392
407
|
end
|
@@ -406,6 +421,7 @@ module Groovy
|
|
406
421
|
private
|
407
422
|
|
408
423
|
def get_record_attribute(key)
|
424
|
+
return if record.nil?
|
409
425
|
val = record[key]
|
410
426
|
if self.class.schema.time_columns.include?(key)
|
411
427
|
fix_time_value(val)
|
@@ -423,15 +439,15 @@ module Groovy
|
|
423
439
|
# record.respond_to?(:_key) ? record._key : id
|
424
440
|
# end
|
425
441
|
|
426
|
-
def
|
442
|
+
def load_attributes_from_record
|
427
443
|
self.class.attribute_names.each do |col|
|
428
|
-
public_send("#{col}=", get_record_attribute(col))
|
444
|
+
public_send("#{col}=", get_record_attribute(col)) unless @attributes.key?(col)
|
429
445
|
end
|
430
446
|
end
|
431
447
|
|
432
448
|
def set_attribute(key, val)
|
433
|
-
changes[key.to_sym] = [self[key], val] if changes # nil
|
434
|
-
attributes[key.to_sym] = val
|
449
|
+
changes[key.to_sym] = [self[key], val] if changes # nil before initializing
|
450
|
+
@attributes[key.to_sym] = val
|
435
451
|
end
|
436
452
|
|
437
453
|
def get_ref(name)
|
@@ -456,7 +472,7 @@ module Groovy
|
|
456
472
|
|
457
473
|
def create
|
458
474
|
fire_callbacks(:before_create)
|
459
|
-
set_record(self.class.insert(attributes, @_key))
|
475
|
+
set_record(self.class.insert(@attributes, @_key))
|
460
476
|
fire_callbacks(:after_create)
|
461
477
|
self
|
462
478
|
end
|
data/lib/groovy/query.rb
CHANGED
@@ -62,13 +62,13 @@ module Groovy
|
|
62
62
|
where(conditions).limit(1).first
|
63
63
|
end
|
64
64
|
|
65
|
-
def find_each(opts = {}, &block)
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
65
|
+
# def find_each(opts = {}, &block)
|
66
|
+
# count = 0
|
67
|
+
# in_batches({ of: 10 }.merge(opts)) do |group|
|
68
|
+
# group.each { |item| count += 1; yield(item) }
|
69
|
+
# end
|
70
|
+
# count
|
71
|
+
# end
|
72
72
|
|
73
73
|
# http://groonga.org/docs/reference/grn_expr/query_syntax.html
|
74
74
|
# TODO: support match_columns (search value in two or more columns)
|
@@ -192,11 +192,16 @@ module Groovy
|
|
192
192
|
end
|
193
193
|
|
194
194
|
def [](index)
|
195
|
-
|
195
|
+
if r = results[index]
|
196
|
+
model.new_from_record(r)
|
197
|
+
end
|
196
198
|
end
|
197
199
|
|
198
200
|
def each(&block)
|
199
|
-
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
|
200
205
|
end
|
201
206
|
|
202
207
|
def update_all(attrs)
|
@@ -236,15 +241,15 @@ module Groovy
|
|
236
241
|
end
|
237
242
|
end
|
238
243
|
|
244
|
+
private
|
245
|
+
attr_reader :model, :table, :options, :select_block
|
246
|
+
|
239
247
|
def records
|
240
248
|
@records ||= results.map do |r|
|
241
249
|
model.new_from_record(r)
|
242
250
|
end
|
243
251
|
end
|
244
252
|
|
245
|
-
private
|
246
|
-
attr_reader :model, :table, :options, :select_block
|
247
|
-
|
248
253
|
def get_last(count = 1)
|
249
254
|
if count > 1
|
250
255
|
records[(size-count)..-1]
|
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,47 +34,44 @@ 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
|
-
columns_by_type('Time')
|
57
|
+
@cache[:time_columns] ||= columns_by_type('Time')
|
60
58
|
end
|
61
59
|
|
62
60
|
def integer_columns
|
63
|
-
columns_by_type('Int32')
|
61
|
+
@cache[:integer_columns] ||= columns_by_type('Int32')
|
64
62
|
end
|
65
63
|
|
66
64
|
def boolean_columns
|
67
|
-
columns_by_type('Bool')
|
65
|
+
@cache[:boolean_columns] ||= columns_by_type('Bool')
|
68
66
|
end
|
69
67
|
|
70
68
|
def columns_by_type(type)
|
71
69
|
get_names(table.columns.select { |c| c.column? && c.range.name == type })
|
72
70
|
end
|
73
71
|
|
74
|
-
|
75
|
-
|
76
|
-
|
72
|
+
def reload
|
73
|
+
@cache = {}
|
74
|
+
end
|
77
75
|
|
78
76
|
def rebuild!
|
79
77
|
log("Rebuilding!")
|
@@ -116,6 +114,8 @@ module Groovy
|
|
116
114
|
@index_columns.each do |col|
|
117
115
|
add_index_on(col)
|
118
116
|
end
|
117
|
+
|
118
|
+
reload
|
119
119
|
self
|
120
120
|
end
|
121
121
|
|
data/lib/groovy/vector.rb
CHANGED
@@ -74,9 +74,30 @@ module Groovy
|
|
74
74
|
|
75
75
|
alias_method :<<, :push
|
76
76
|
|
77
|
+
[:first, :last, :find_by, :search, :where, :not, :sort_by, :limit, :offset, :paginate, :in_batches].each do |scope_method|
|
78
|
+
define_method scope_method do |*args, &block|
|
79
|
+
query.public_send(scope_method, *args, &block)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
77
83
|
private
|
78
84
|
attr_reader :obj, :key
|
79
85
|
|
86
|
+
def query
|
87
|
+
model = Model.model_from_table(key.capitalize)
|
88
|
+
obj_name = obj.class.name.downcase
|
89
|
+
model.query.where(obj_name => obj.id)
|
90
|
+
end
|
91
|
+
|
92
|
+
def method_missing(name, *args, &block)
|
93
|
+
model = Model.model_from_table(key.capitalize)
|
94
|
+
if model.scopes.include?(name)
|
95
|
+
query.send(name)
|
96
|
+
else
|
97
|
+
super
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
80
101
|
def remove_record(rec)
|
81
102
|
recs = obj.record[key].delete_if { |r| r == rec }
|
82
103
|
obj.record[key] = recs
|
data/lib/groovy/version.rb
CHANGED
data/spec/model_spec.rb
CHANGED
@@ -86,6 +86,28 @@ describe Groovy::Model do
|
|
86
86
|
end
|
87
87
|
|
88
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
|
89
111
|
end
|
90
112
|
|
91
113
|
describe '#[]=' 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
|
+
version: 0.5.1
|
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:
|
11
|
+
date: 2022-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rroonga
|