groovy 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/example/Gemfile.lock +1 -1
- data/example/basic.rb +8 -6
- data/example/config.ru +2 -2
- data/example/relations.rb +4 -4
- data/groovy.gemspec +1 -1
- data/lib/groovy.rb +0 -1
- data/lib/groovy/model.rb +37 -12
- data/lib/groovy/query.rb +31 -4
- data/lib/groovy/schema.rb +22 -4
- data/lib/groovy/version.rb +3 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21ec75f430aa5b3ea423b52de62b4d578b4eb0b1e6722e9201c012cd444c616b
|
4
|
+
data.tar.gz: ec46772137b69e14dfe364d383fa9042ec8edd798bd22ed5c2dd4a47f895f1a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 044e5ba04d8097a354be1a6feb07c2ddd06c6e28355a07b41586936a4e572e028f1aefd35bb587dff46f2d1bbad513332d915e7aec01c00df26b09f6a3ffb357
|
7
|
+
data.tar.gz: 30ae3849bb6d769beb08db3ea8c676a0270a1037eb854c5ba7f4df2c3467906ad06055c7409ef8f2cf5284712f668c7153055b77470d0fa902e2d808591eedc4
|
data/example/Gemfile.lock
CHANGED
data/example/basic.rb
CHANGED
@@ -7,18 +7,20 @@ class Product
|
|
7
7
|
include Groovy::Model
|
8
8
|
|
9
9
|
schema do |t|
|
10
|
-
t.
|
11
|
-
t.
|
10
|
+
t.string :name
|
11
|
+
t.integer :price
|
12
12
|
t.timestamps
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
def populate
|
17
|
+
5_000.times do |i|
|
18
|
+
puts "Creating product #{i}" if i % 1000 == 0
|
19
|
+
Product.create!(name: "A product with index #{i}", price: 10000 + i)
|
20
|
+
end
|
19
21
|
end
|
20
22
|
|
21
|
-
|
23
|
+
populate if Product.count == 0
|
22
24
|
|
23
25
|
# 50_000 products: 50M
|
24
26
|
# 100_000 products: 50M
|
data/example/config.ru
CHANGED
data/example/relations.rb
CHANGED
@@ -20,7 +20,7 @@ class Category
|
|
20
20
|
include Groovy::Model
|
21
21
|
|
22
22
|
schema do |t|
|
23
|
-
t.
|
23
|
+
t.string :name
|
24
24
|
t.timestamps
|
25
25
|
end
|
26
26
|
end
|
@@ -30,8 +30,8 @@ class Place
|
|
30
30
|
|
31
31
|
schema do |t|
|
32
32
|
t.reference :categories, "Categories", type: :vector
|
33
|
-
t.
|
34
|
-
t.
|
33
|
+
t.string :name
|
34
|
+
t.string :description, index: true
|
35
35
|
t.timestamps
|
36
36
|
end
|
37
37
|
end
|
@@ -41,7 +41,7 @@ class Location
|
|
41
41
|
|
42
42
|
schema do |t|
|
43
43
|
t.reference :place, "Places"
|
44
|
-
t.
|
44
|
+
t.string :coords
|
45
45
|
t.timestamps
|
46
46
|
end
|
47
47
|
end
|
data/groovy.gemspec
CHANGED
data/lib/groovy.rb
CHANGED
data/lib/groovy/model.rb
CHANGED
@@ -107,12 +107,24 @@ module Groovy
|
|
107
107
|
Query.new(self, table)
|
108
108
|
end
|
109
109
|
|
110
|
-
|
110
|
+
def first(count = 1)
|
111
|
+
arr = limit(count)
|
112
|
+
count == 1 && arr.first || arr
|
113
|
+
end
|
114
|
+
|
115
|
+
def last(count = 1)
|
116
|
+
arr = limit(count).to_a.reverse
|
117
|
+
count == 1 && arr.first || arr
|
118
|
+
end
|
111
119
|
|
112
120
|
def find_by(params)
|
113
121
|
where(params).limit(1).first
|
114
122
|
end
|
115
123
|
|
124
|
+
def in_batches(of: 1000, from: nil, &block)
|
125
|
+
all.in_batches(of: of, from: from, &block)
|
126
|
+
end
|
127
|
+
|
116
128
|
[:search, :where, :not, :sort_by, :limit, :offset].each do |scope_method|
|
117
129
|
define_method scope_method do |*args|
|
118
130
|
Query.new(self, table).tap do |q|
|
@@ -129,12 +141,7 @@ module Groovy
|
|
129
141
|
|
130
142
|
def_instance_delegators :table, :count, :size
|
131
143
|
|
132
|
-
|
133
|
-
|
134
|
-
def db_context
|
135
|
-
Groovy.contexts[context_name] or raise "Context not defined: #{context_name}"
|
136
|
-
end
|
137
|
-
|
144
|
+
# called from instance too, so must by public
|
138
145
|
def insert(key, attributes = nil)
|
139
146
|
if table.support_key?
|
140
147
|
table.add(key, attributes)
|
@@ -149,6 +156,12 @@ module Groovy
|
|
149
156
|
obj[key_name] = Time.now if attribute_names.include?(key_name.to_sym)
|
150
157
|
end
|
151
158
|
|
159
|
+
private
|
160
|
+
|
161
|
+
def db_context
|
162
|
+
Groovy.contexts[context_name] or raise "Context not defined: #{context_name}"
|
163
|
+
end
|
164
|
+
|
152
165
|
def add_attr_accessors(col)
|
153
166
|
define_method(col) { self[col] }
|
154
167
|
define_method("#{col}=") { |val| self[col] = val }
|
@@ -176,20 +189,27 @@ module Groovy
|
|
176
189
|
end
|
177
190
|
end
|
178
191
|
|
179
|
-
attr_reader :attributes, :refs, :record, :changes
|
192
|
+
attr_reader :id, :attributes, :refs, :record, :changes
|
180
193
|
|
181
194
|
def initialize(attributes = nil, record = nil)
|
182
|
-
@attributes =
|
183
|
-
@refs, @vectors = {}, {}
|
195
|
+
@attributes, @refs, @vectors = {}, {}, {}
|
184
196
|
|
185
197
|
if @record = record
|
198
|
+
@id = attributes.delete('_id')
|
186
199
|
# TODO: lazy load this
|
187
|
-
self.class.schema.singular_references.each
|
200
|
+
# self.class.schema.singular_references.each do |col|
|
201
|
+
# set_ref(col, record.public_send(col))
|
202
|
+
# end
|
188
203
|
end
|
189
204
|
|
205
|
+
set_attributes(attributes)
|
190
206
|
@changes = {}
|
191
207
|
end
|
192
208
|
|
209
|
+
def new_record?
|
210
|
+
id.nil?
|
211
|
+
end
|
212
|
+
|
193
213
|
def key
|
194
214
|
return unless record
|
195
215
|
record.respond_to?(:_key) ? record._key : record.id
|
@@ -218,8 +238,13 @@ module Groovy
|
|
218
238
|
changes.any?
|
219
239
|
end
|
220
240
|
|
241
|
+
def set_attributes(obj = {})
|
242
|
+
# we call the method instead of []= to allow overriding setters
|
243
|
+
obj.each { |k,v| public_send("#{k}=", v) }
|
244
|
+
end
|
245
|
+
|
221
246
|
def update_attributes(obj)
|
222
|
-
obj
|
247
|
+
set_attributes(obj)
|
223
248
|
update
|
224
249
|
end
|
225
250
|
|
data/lib/groovy/query.rb
CHANGED
@@ -4,6 +4,7 @@ module Groovy
|
|
4
4
|
include Enumerable
|
5
5
|
AND = '+'.freeze
|
6
6
|
NOT = '-'.freeze
|
7
|
+
PER_PAGE = 50.freeze
|
7
8
|
|
8
9
|
attr_reader :parameters, :sorting
|
9
10
|
|
@@ -23,7 +24,9 @@ module Groovy
|
|
23
24
|
|
24
25
|
def search(obj)
|
25
26
|
obj.each do |col, q|
|
26
|
-
|
27
|
+
unless model.index_columns.include?(col)
|
28
|
+
raise "Not an index column, so cannot do fulltext search: #{col}"
|
29
|
+
end
|
27
30
|
parameters.push(AND + "(#{col}:@#{q})")
|
28
31
|
end
|
29
32
|
end
|
@@ -79,15 +82,21 @@ module Groovy
|
|
79
82
|
end
|
80
83
|
|
81
84
|
def limit(num)
|
82
|
-
@limit = num
|
85
|
+
@sorting[:limit] = num
|
83
86
|
self
|
84
87
|
end
|
85
88
|
|
86
89
|
def offset(num)
|
87
|
-
@offset = num
|
90
|
+
@sorting[:offset] = num
|
88
91
|
self
|
89
92
|
end
|
90
93
|
|
94
|
+
def paginate(page)
|
95
|
+
page = 1 if page.to_i < 1
|
96
|
+
offset = ((page.to_i)-1) * PER_PAGE
|
97
|
+
offset(offset).limit(PER_PAGE)
|
98
|
+
end
|
99
|
+
|
91
100
|
# sort_by(title: :asc)
|
92
101
|
def sort_by(hash)
|
93
102
|
sorting[:by] = hash.keys.map do |key|
|
@@ -97,7 +106,9 @@ module Groovy
|
|
97
106
|
end
|
98
107
|
|
99
108
|
def all
|
100
|
-
@all ||= results.map
|
109
|
+
@all ||= results.map do |r|
|
110
|
+
model.new(r.attributes['_value']['_key'], r)
|
111
|
+
end
|
101
112
|
end
|
102
113
|
|
103
114
|
def size
|
@@ -122,11 +133,26 @@ module Groovy
|
|
122
133
|
all[size-1]
|
123
134
|
end
|
124
135
|
|
136
|
+
def in_batches(of: 1000, from: nil)
|
137
|
+
@sorting[:limit] = of
|
138
|
+
@sorting[:offset] = from || 0
|
139
|
+
|
140
|
+
while results.any?
|
141
|
+
yield all
|
142
|
+
|
143
|
+
@sorting[:offset] += of
|
144
|
+
@all = @results = nil # reset
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
125
148
|
private
|
126
149
|
attr_reader :model, :table, :options
|
127
150
|
|
128
151
|
def results
|
129
152
|
@results ||= execute
|
153
|
+
rescue Groonga::TooLargeOffset
|
154
|
+
# puts "Offset is higher than table size!"
|
155
|
+
[]
|
130
156
|
end
|
131
157
|
|
132
158
|
def execute
|
@@ -138,6 +164,7 @@ module Groovy
|
|
138
164
|
table.select(options)
|
139
165
|
end
|
140
166
|
|
167
|
+
puts "Sorting with #{sort_key_and_order}, #{sorting.inspect}" if ENV['DEBUG']
|
141
168
|
set.sort(sort_key_and_order, {
|
142
169
|
limit: sorting[:limit],
|
143
170
|
offset: sorting[:offset]
|
data/lib/groovy/schema.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__)) + '/types'
|
1
|
+
# require File.expand_path(File.dirname(__FILE__)) + '/types'
|
2
2
|
|
3
3
|
module Groovy
|
4
4
|
class Schema
|
@@ -8,6 +8,17 @@ module Groovy
|
|
8
8
|
compress: :zstandard
|
9
9
|
}.freeze
|
10
10
|
|
11
|
+
TYPES = {
|
12
|
+
'string' => 'short_text',
|
13
|
+
'text' => 'text',
|
14
|
+
'float' => 'float',
|
15
|
+
# 'Bool' => 'boolean',
|
16
|
+
'boolean' => 'boolean',
|
17
|
+
'integer' => 'int32',
|
18
|
+
'big_integer' => 'int64',
|
19
|
+
'time' => 'time'
|
20
|
+
}.freeze
|
21
|
+
|
11
22
|
attr_reader :index_columns
|
12
23
|
|
13
24
|
def initialize(context, table_name, opts = {})
|
@@ -47,19 +58,26 @@ module Groovy
|
|
47
58
|
end
|
48
59
|
|
49
60
|
def column(name, type, options = {})
|
50
|
-
groonga_type = Types.map(type)
|
61
|
+
# groonga_type = Types.map(type)
|
62
|
+
groonga_type = type
|
51
63
|
@index_columns.push(name) if options.delete(:index)
|
52
64
|
@spec[name.to_sym] = { type: groonga_type, args: [COLUMN_DEFAULTS.merge(options)] }
|
53
65
|
end
|
54
66
|
|
67
|
+
TYPES.each do |from_type, to_type|
|
68
|
+
define_method(from_type) do |*args|
|
69
|
+
column(args.shift, to_type, (args.shift || {}))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
55
73
|
def reference(name, table_name = nil, options = {})
|
56
74
|
table_name = "#{name}s" if table_name.nil?
|
57
75
|
@spec[name.to_sym] = { type: :reference, args: [table_name, options] }
|
58
76
|
end
|
59
77
|
|
60
78
|
def timestamps(opts = {})
|
61
|
-
column(:created_at, '
|
62
|
-
column(:updated_at, '
|
79
|
+
column(:created_at, 'time')
|
80
|
+
column(:updated_at, 'time')
|
63
81
|
end
|
64
82
|
|
65
83
|
def sync(db_context = nil)
|
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.1.
|
4
|
+
version: 0.1.2
|
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: 2019-
|
11
|
+
date: 2019-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -61,6 +61,7 @@ files:
|
|
61
61
|
- lib/groovy/schema.rb
|
62
62
|
- lib/groovy/types.rb
|
63
63
|
- lib/groovy/vector.rb
|
64
|
+
- lib/groovy/version.rb
|
64
65
|
- spec/groovy_spec.rb
|
65
66
|
homepage: https://github.com/tomas/groovy
|
66
67
|
licenses: []
|