rasti-db 0.1.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 +7 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +9 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +11 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +161 -0
- data/Rakefile +25 -0
- data/lib/rasti/db/collection.rb +263 -0
- data/lib/rasti/db/helpers.rb +18 -0
- data/lib/rasti/db/model.rb +105 -0
- data/lib/rasti/db/query.rb +113 -0
- data/lib/rasti/db/relations.rb +159 -0
- data/lib/rasti/db/type_converter.rb +52 -0
- data/lib/rasti/db/version.rb +5 -0
- data/lib/rasti/db.rb +10 -0
- data/lib/rasti-db.rb +1 -0
- data/rasti-db.gemspec +44 -0
- data/spec/collection_spec.rb +494 -0
- data/spec/coverage_helper.rb +5 -0
- data/spec/minitest_helper.rb +113 -0
- data/spec/model_spec.rb +82 -0
- data/spec/query_spec.rb +122 -0
- data/spec/relations_spec.rb +144 -0
- data/spec/type_converter_spec.rb +98 -0
- metadata +231 -0
@@ -0,0 +1,494 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe 'Collection' do
|
4
|
+
|
5
|
+
describe 'Specification' do
|
6
|
+
|
7
|
+
it 'Implicit' do
|
8
|
+
Users.collection_name.must_equal :users
|
9
|
+
Users.model.must_equal User
|
10
|
+
Users.primary_key.must_equal :id
|
11
|
+
Users.implicit_foreign_key_name.must_equal :user_id
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'Explicit' do
|
15
|
+
model_class = Rasti::DB::Model[:code, :name]
|
16
|
+
|
17
|
+
collection_class = Class.new(Rasti::DB::Collection) do
|
18
|
+
set_collection_name :countries
|
19
|
+
set_primary_key :code
|
20
|
+
set_model model_class
|
21
|
+
end
|
22
|
+
|
23
|
+
collection_class.collection_name.must_equal :countries
|
24
|
+
collection_class.model.must_equal model_class
|
25
|
+
collection_class.primary_key.must_equal :code
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'Lazy model name' do
|
29
|
+
collection_class = Class.new(Rasti::DB::Collection) do
|
30
|
+
set_model :User
|
31
|
+
end
|
32
|
+
|
33
|
+
collection_class.model.must_equal User
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'Insert, Update and Delete' do
|
39
|
+
|
40
|
+
it 'Insert' do
|
41
|
+
id = users.insert name: 'User 1'
|
42
|
+
|
43
|
+
db[:users][id: id][:name].must_equal 'User 1'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'Insert with many to many' do
|
47
|
+
user_id = db[:users].insert name: 'User 1'
|
48
|
+
|
49
|
+
1.upto(2) do |i|
|
50
|
+
db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...'
|
51
|
+
db[:categories].insert name: "Category #{i}"
|
52
|
+
end
|
53
|
+
|
54
|
+
post_id = posts.insert user_id: user_id, title: 'Post title', body: '...', categories: [1,2]
|
55
|
+
category_id = categories.insert name: 'Category', posts: [1,2]
|
56
|
+
|
57
|
+
db[:categories_posts].where(post_id: post_id).map(:category_id).must_equal [1,2]
|
58
|
+
db[:categories_posts].where(category_id: category_id).map(:post_id).must_equal [1,2]
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'Insert only many to many' do
|
62
|
+
1.upto(3) do |i|
|
63
|
+
db[:categories].insert name: "Category #{i}"
|
64
|
+
end
|
65
|
+
|
66
|
+
user_id = db[:users].insert name: 'User 1'
|
67
|
+
post_id = db[:posts].insert user_id: user_id, title: 'Post title', body: '...'
|
68
|
+
1.upto(2) { |category_id| db[:categories_posts].insert post_id: post_id, category_id: category_id }
|
69
|
+
|
70
|
+
posts.insert_relations post_id, categories: [3]
|
71
|
+
|
72
|
+
db[:categories_posts].where(post_id: post_id).map(:category_id).must_equal [1,2,3]
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'Bulk insert' do
|
76
|
+
users_attrs = 1.upto(2).map { |i| {name: "User #{i}"} }
|
77
|
+
|
78
|
+
ids = users.bulk_insert users_attrs, return: :primary_key
|
79
|
+
|
80
|
+
ids.must_equal [1,2]
|
81
|
+
db[:users][id: 1][:name].must_equal 'User 1'
|
82
|
+
db[:users][id: 2][:name].must_equal 'User 2'
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'Update' do
|
86
|
+
id = db[:users].insert name: 'User 1'
|
87
|
+
|
88
|
+
db[:users][id: id][:name].must_equal 'User 1'
|
89
|
+
|
90
|
+
users.update id, name: 'updated'
|
91
|
+
|
92
|
+
db[:users][id: id][:name].must_equal 'updated'
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'Update with many to many' do
|
96
|
+
user_id = db[:users].insert name: 'User 1'
|
97
|
+
|
98
|
+
1.upto(3) do |i|
|
99
|
+
db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...'
|
100
|
+
db[:categories].insert name: "Category #{i}"
|
101
|
+
end
|
102
|
+
|
103
|
+
db[:categories_posts].insert post_id: 1, category_id: 1
|
104
|
+
db[:categories_posts].insert post_id: 1, category_id: 2
|
105
|
+
db[:categories_posts].insert post_id: 2, category_id: 2
|
106
|
+
|
107
|
+
db[:categories_posts].where(post_id: 1).map(:category_id).must_equal [1,2]
|
108
|
+
|
109
|
+
posts.update 1, categories: [2,3]
|
110
|
+
|
111
|
+
db[:categories_posts].where(post_id: 1).map(:category_id).must_equal [2,3]
|
112
|
+
|
113
|
+
db[:categories_posts].where(category_id: 2).map(:post_id).must_equal [1,2]
|
114
|
+
|
115
|
+
categories.update 2, posts: [2,3]
|
116
|
+
|
117
|
+
db[:categories_posts].where(category_id: 2).map(:post_id).must_equal [2,3]
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'Bulk update' do
|
121
|
+
user_id = db[:users].insert name: 'User 1'
|
122
|
+
1.upto(3) { |i| db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...' }
|
123
|
+
|
124
|
+
posts.bulk_update(body: 'Updated ...') { where id: [1,2] }
|
125
|
+
|
126
|
+
db[:posts][id: 1][:body].must_equal 'Updated ...'
|
127
|
+
db[:posts][id: 2][:body].must_equal 'Updated ...'
|
128
|
+
db[:posts][id: 3][:body].must_equal '...'
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'Delete' do
|
132
|
+
id = db[:users].insert name: 'User 1'
|
133
|
+
|
134
|
+
db[:users].count.must_equal 1
|
135
|
+
|
136
|
+
users.delete id
|
137
|
+
|
138
|
+
db[:users].count.must_equal 0
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'Delete only many to many' do
|
142
|
+
1.upto(3) do |i|
|
143
|
+
db[:categories].insert name: "Category #{i}"
|
144
|
+
end
|
145
|
+
|
146
|
+
user_id = db[:users].insert name: 'User 1'
|
147
|
+
post_id = db[:posts].insert user_id: user_id, title: 'Post title', body: '...'
|
148
|
+
1.upto(3) { |category_id| db[:categories_posts].insert post_id: post_id, category_id: category_id }
|
149
|
+
|
150
|
+
posts.delete_relations post_id, categories: [3]
|
151
|
+
|
152
|
+
db[:categories_posts].where(post_id: post_id).map(:category_id).must_equal [1,2]
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'Bulk delete' do
|
156
|
+
1.upto(3) { |i| db[:users].insert name: "User #{i}" }
|
157
|
+
|
158
|
+
users.bulk_delete { where id: [1,2] }
|
159
|
+
|
160
|
+
db[:users].map(:id).must_equal [3]
|
161
|
+
end
|
162
|
+
|
163
|
+
describe 'Delete cascade' do
|
164
|
+
|
165
|
+
before :each do
|
166
|
+
1.upto(3) do |i|
|
167
|
+
user_id = db[:users].insert name: "User #{i}"
|
168
|
+
category_id = db[:categories].insert name: "Category #{i}"
|
169
|
+
|
170
|
+
1.upto(3) do |n|
|
171
|
+
post_id = db[:posts].insert user_id: user_id, title: "Post #{i}.#{n}", body: '...'
|
172
|
+
db[:categories_posts].insert post_id: post_id, category_id: category_id
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
{1 => 4..6, 2 => 7..9, 3 => 1..3}.each do |user_id, post_ids|
|
177
|
+
post_ids.each do |post_id|
|
178
|
+
db[:comments].insert post_id: post_id, user_id: user_id, text: 'Comment'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
db[:users].count.must_equal 3
|
183
|
+
db[:categories].count.must_equal 3
|
184
|
+
db[:posts].count.must_equal 9
|
185
|
+
db[:categories_posts].count.must_equal 9
|
186
|
+
db[:comments].count.must_equal 9
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'Self relations' do
|
190
|
+
db[:posts].where(id: 1).count.must_equal 1
|
191
|
+
db[:categories_posts].where(post_id: 1).count.must_equal 1
|
192
|
+
db[:comments].where(post_id: 1).count.must_equal 1
|
193
|
+
|
194
|
+
posts.delete_cascade 1
|
195
|
+
|
196
|
+
db[:posts].where(id: 1).count.must_equal 0
|
197
|
+
db[:categories_posts].where(post_id: 1).count.must_equal 0
|
198
|
+
db[:comments].where(post_id: 1).count.must_equal 0
|
199
|
+
|
200
|
+
db[:users].count.must_equal 3
|
201
|
+
db[:categories].count.must_equal 3
|
202
|
+
db[:posts].count.must_equal 8
|
203
|
+
db[:categories_posts].count.must_equal 8
|
204
|
+
db[:comments].count.must_equal 8
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'Deep relations' do
|
208
|
+
db[:users].where(id: 1).count.must_equal 1
|
209
|
+
db[:comments].where(user_id: 1).count.must_equal 3
|
210
|
+
db[:posts].where(user_id: 1).count.must_equal 3
|
211
|
+
db[:comments].join(:posts, id: :post_id).where(posts__user_id: 1).count.must_equal 3
|
212
|
+
db[:categories_posts].join(:posts, id: :post_id).where(posts__user_id: 1).count.must_equal 3
|
213
|
+
|
214
|
+
users.delete_cascade 1
|
215
|
+
|
216
|
+
db[:users].where(id: 1).count.must_equal 0
|
217
|
+
db[:comments].where(user_id: 1).count.must_equal 0
|
218
|
+
db[:posts].where(user_id: 1).count.must_equal 0
|
219
|
+
db[:comments].join(:posts, id: :post_id).where(posts__user_id: 1).count.must_equal 0
|
220
|
+
db[:categories_posts].join(:posts, id: :post_id).where(posts__user_id: 1).count.must_equal 0
|
221
|
+
|
222
|
+
db[:users].count.must_equal 2
|
223
|
+
db[:categories].count.must_equal 3
|
224
|
+
db[:posts].count.must_equal 6
|
225
|
+
db[:categories_posts].count.must_equal 6
|
226
|
+
db[:comments].count.must_equal 3
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
describe 'Queries' do
|
234
|
+
|
235
|
+
it 'Find' do
|
236
|
+
id = db[:users].insert name: 'User 1'
|
237
|
+
|
238
|
+
users.find(id).must_equal User.new(id: id, name: 'User 1')
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'Find graph' do
|
242
|
+
user_id = db[:users].insert name: 'User 1'
|
243
|
+
db[:posts].insert user_id: user_id, title: 'Post 1', body: '...'
|
244
|
+
|
245
|
+
users.find_graph(user_id, :posts).must_equal User.new id: user_id, name: 'User 1', posts: posts.all
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'Count' do
|
249
|
+
1.upto(10) { |i| db[:users].insert name: "User #{i}" }
|
250
|
+
|
251
|
+
users.count.must_equal 10
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'All' do
|
255
|
+
id = db[:users].insert name: 'User 1'
|
256
|
+
|
257
|
+
users.all.must_equal [User.new(id: id, name: 'User 1')]
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'First' do
|
261
|
+
1.upto(10) { |i| db[:users].insert name: "User #{i}" }
|
262
|
+
|
263
|
+
users.first.must_equal User.new(id: 1, name: 'User 1')
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'Exists' do
|
267
|
+
1.upto(10) { |i| db[:users].insert name: "User #{i}" }
|
268
|
+
|
269
|
+
users.exists?(id: 1).must_equal true
|
270
|
+
users.exists?(id: 0).must_equal false
|
271
|
+
|
272
|
+
users.exists? { where id: 1 }.must_equal true
|
273
|
+
users.exists? { where id: 0 }.must_equal false
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'Detect' do
|
277
|
+
1.upto(10) { |i| db[:users].insert name: "User #{i}" }
|
278
|
+
|
279
|
+
users.detect(id: 1).must_equal User.new(id: 1, name: 'User 1')
|
280
|
+
users.detect(id: 0).must_equal nil
|
281
|
+
|
282
|
+
users.detect { where id: 1 }.must_equal User.new(id: 1, name: 'User 1')
|
283
|
+
users.detect { where id: 0 }.must_equal nil
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'Chained query' do
|
287
|
+
1.upto(10) { |i| db[:users].insert name: "User #{i}" }
|
288
|
+
|
289
|
+
models = users.where(id: [1,2]).reverse_order(:id).all
|
290
|
+
|
291
|
+
models.must_equal [2,1].map { |i| User.new(id: i, name: "User #{i}") }
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'Chain dataset as query' do
|
295
|
+
1.upto(2) { |i| db[:users].insert name: "User #{i}" }
|
296
|
+
1.upto(3) { |i| db[:posts].insert user_id: 1, title: "Post #{i}", body: '...' }
|
297
|
+
1.upto(2) { |i| db[:comments].insert post_id: i, user_id: 2, text: 'Comment' }
|
298
|
+
|
299
|
+
models = posts.commented_by(2).all
|
300
|
+
models.must_equal [1,2].map { |i| Post.new(id: i, user_id: 1, title: "Post #{i}", body: '...') }
|
301
|
+
end
|
302
|
+
|
303
|
+
it 'Custom query' do
|
304
|
+
1.upto(2) { |i| db[:users].insert name: "User #{i}" }
|
305
|
+
1.upto(3) { |i| db[:posts].insert user_id: 1, title: "Post #{i}", body: '...' }
|
306
|
+
1.upto(2) { |i| db[:comments].insert post_id: i, user_id: 2, text: 'Comment' }
|
307
|
+
|
308
|
+
models = comments.posts_commented_by(2)
|
309
|
+
models.must_equal [1,2].map { |i| Post.new(id: i, user_id: 1, title: "Post #{i}", body: '...') }
|
310
|
+
end
|
311
|
+
|
312
|
+
describe 'Named queries' do
|
313
|
+
|
314
|
+
before do
|
315
|
+
1.upto(2) { |i| db[:users].insert name: "User #{i}" }
|
316
|
+
1.upto(3) { |i| db[:posts].insert user_id: 1, title: "Post #{i}", body: '...' }
|
317
|
+
4.upto(5) { |i| db[:posts].insert user_id: 2, title: "Post #{i}", body: '...' }
|
318
|
+
end
|
319
|
+
|
320
|
+
it 'Global' do
|
321
|
+
result_1 = posts.created_by(1)
|
322
|
+
result_1.map(&:id).must_equal [1,2,3]
|
323
|
+
|
324
|
+
result_2 = posts.created_by(2)
|
325
|
+
result_2.map(&:id).must_equal [4,5]
|
326
|
+
end
|
327
|
+
|
328
|
+
it 'Chained' do
|
329
|
+
result = posts.created_by(2).entitled('Post 4')
|
330
|
+
result.map(&:id).must_equal [4]
|
331
|
+
end
|
332
|
+
|
333
|
+
end
|
334
|
+
|
335
|
+
it 'Graph' do
|
336
|
+
1.upto(3) do |i|
|
337
|
+
db[:users].insert name: "User #{i}"
|
338
|
+
db[:categories].insert name: "Category #{i}"
|
339
|
+
db[:posts].insert user_id: i, title: "Post #{i}", body: '...'
|
340
|
+
db[:categories_posts].insert post_id: i, category_id: i
|
341
|
+
end
|
342
|
+
|
343
|
+
db[:posts].map(:id).each do |post_id|
|
344
|
+
db[:users].map(:id).each do |user_id|
|
345
|
+
db[:comments].insert post_id: post_id, user_id: user_id, text: 'Comment'
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
posts_graph = posts.where(id: 1).graph(:user, :categories, 'comments.user.posts.categories').all
|
350
|
+
|
351
|
+
posts_graph.count.must_equal 1
|
352
|
+
|
353
|
+
posts_graph[0].user.must_equal users.find(1)
|
354
|
+
|
355
|
+
posts_graph[0].categories.must_equal [categories.find(1)]
|
356
|
+
|
357
|
+
posts_graph[0].comments.count.must_equal 3
|
358
|
+
posts_graph[0].comments.each_with_index do |comment, index|
|
359
|
+
i = index + 1
|
360
|
+
|
361
|
+
comment.post_id.must_equal 1
|
362
|
+
comment.user_id.must_equal i
|
363
|
+
|
364
|
+
comment.user.id.must_equal i
|
365
|
+
comment.user.name.must_equal "User #{i}"
|
366
|
+
|
367
|
+
comment.user.posts.count.must_equal 1
|
368
|
+
comment.user.posts[0].id.must_equal i
|
369
|
+
comment.user.posts[0].title.must_equal "Post #{i}"
|
370
|
+
comment.user.posts[0].user_id.must_equal i
|
371
|
+
|
372
|
+
comment.user.posts[0].categories.count.must_equal 1
|
373
|
+
comment.user.posts[0].categories[0].id.must_equal i
|
374
|
+
comment.user.posts[0].categories[0].name.must_equal "Category #{i}"
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
end
|
379
|
+
|
380
|
+
describe 'Schemas' do
|
381
|
+
|
382
|
+
let :stub_db do
|
383
|
+
stubs = Proc.new do |sql|
|
384
|
+
case sql
|
385
|
+
|
386
|
+
when 'SELECT * FROM custom_schema.users',
|
387
|
+
'SELECT * FROM custom_schema.users WHERE (id IN (2, 1))'
|
388
|
+
[
|
389
|
+
{id: 1},
|
390
|
+
{id: 2}
|
391
|
+
]
|
392
|
+
|
393
|
+
when 'SELECT * FROM custom_schema.posts',
|
394
|
+
'SELECT * FROM custom_schema.posts WHERE (user_id IN (1, 2))'
|
395
|
+
[
|
396
|
+
{id: 3, user_id: 1},
|
397
|
+
{id: 4, user_id: 2}
|
398
|
+
]
|
399
|
+
|
400
|
+
when 'SELECT * FROM custom_schema.comments WHERE (post_id IN (3, 4))'
|
401
|
+
[
|
402
|
+
{id: 5, user_id: 2, post_id: 3},
|
403
|
+
{id: 6, user_id: 1, post_id: 3},
|
404
|
+
{id: 7, user_id: 1, post_id: 4},
|
405
|
+
{id: 8, user_id: 2, post_id: 4}
|
406
|
+
]
|
407
|
+
|
408
|
+
else
|
409
|
+
nil
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
Sequel.mock(fetch: stubs, autoid: 1).tap do |mock|
|
414
|
+
get_schema_block = ->(table_name) { db.schema table_name }
|
415
|
+
mock.define_singleton_method(:schema_parse_table) do |table_name, opts|
|
416
|
+
get_schema_block.call table_name
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
let(:stub_users) { Users.new stub_db, :custom_schema }
|
422
|
+
let(:stub_posts) { Posts.new stub_db, :custom_schema }
|
423
|
+
let(:stub_comments) { Comments.new stub_db, :custom_schema }
|
424
|
+
|
425
|
+
it 'Insert' do
|
426
|
+
stub_users.insert name: 'User 1'
|
427
|
+
stub_db.sqls.must_equal [
|
428
|
+
'BEGIN',
|
429
|
+
"INSERT INTO custom_schema.users (name) VALUES ('User 1')",
|
430
|
+
'COMMIT'
|
431
|
+
]
|
432
|
+
end
|
433
|
+
|
434
|
+
it 'Insert with many to many relation' do
|
435
|
+
stub_posts.insert user_id: 1, title: 'Post 1', body: '...', categories: [2,3]
|
436
|
+
stub_db.sqls.must_equal [
|
437
|
+
'BEGIN',
|
438
|
+
"INSERT INTO custom_schema.posts (user_id, title, body) VALUES (1, 'Post 1', '...')",
|
439
|
+
'DELETE FROM custom_schema.categories_posts WHERE (post_id IN (1))',
|
440
|
+
'INSERT INTO custom_schema.categories_posts (post_id, category_id) VALUES (1, 2)',
|
441
|
+
'INSERT INTO custom_schema.categories_posts (post_id, category_id) VALUES (1, 3)',
|
442
|
+
'COMMIT'
|
443
|
+
]
|
444
|
+
end
|
445
|
+
|
446
|
+
it 'Update' do
|
447
|
+
stub_users.update 1, name: 'Updated name'
|
448
|
+
stub_db.sqls.must_equal [
|
449
|
+
'BEGIN',
|
450
|
+
"UPDATE custom_schema.users SET name = 'Updated name' WHERE (id = 1)",
|
451
|
+
'COMMIT'
|
452
|
+
]
|
453
|
+
end
|
454
|
+
|
455
|
+
it 'Delete' do
|
456
|
+
stub_users.delete 1
|
457
|
+
stub_db.sqls.must_equal ['DELETE FROM custom_schema.users WHERE (id = 1)']
|
458
|
+
end
|
459
|
+
|
460
|
+
it 'Chained query' do
|
461
|
+
stub_users.where(id: [1,2]).limit(1).order(:name).all
|
462
|
+
stub_db.sqls.must_equal ['SELECT * FROM custom_schema.users WHERE (id IN (1, 2)) ORDER BY name LIMIT 1']
|
463
|
+
end
|
464
|
+
|
465
|
+
it 'Graph' do
|
466
|
+
stub_posts.graph(:user, :categories, 'comments.user.posts.categories').all
|
467
|
+
stub_db.sqls.must_equal [
|
468
|
+
'SELECT * FROM custom_schema.posts',
|
469
|
+
'SELECT * FROM custom_schema.users WHERE (id IN (1, 2))',
|
470
|
+
'SELECT * FROM custom_schema.categories INNER JOIN custom_schema.categories_posts ON (custom_schema.categories_posts.category_id = custom_schema.categories.id) WHERE (custom_schema.categories_posts.post_id IN (3, 4))',
|
471
|
+
'SELECT * FROM custom_schema.comments WHERE (post_id IN (3, 4))',
|
472
|
+
'SELECT * FROM custom_schema.users WHERE (id IN (2, 1))',
|
473
|
+
'SELECT * FROM custom_schema.posts WHERE (user_id IN (1, 2))',
|
474
|
+
'SELECT * FROM custom_schema.categories INNER JOIN custom_schema.categories_posts ON (custom_schema.categories_posts.category_id = custom_schema.categories.id) WHERE (custom_schema.categories_posts.post_id IN (3, 4))'
|
475
|
+
]
|
476
|
+
end
|
477
|
+
|
478
|
+
it 'Named query' do
|
479
|
+
stub_posts.commented_by(1).all
|
480
|
+
stub_db.sqls.must_equal [
|
481
|
+
'SELECT DISTINCT custom_schema.posts.* FROM custom_schema.posts INNER JOIN custom_schema.comments ON (custom_schema.comments.post_id = custom_schema.posts.id) WHERE (custom_schema.comments.user_id = 1)'
|
482
|
+
]
|
483
|
+
end
|
484
|
+
|
485
|
+
it 'Custom query' do
|
486
|
+
stub_comments.posts_commented_by(2)
|
487
|
+
stub_db.sqls.must_equal [
|
488
|
+
'SELECT custom_schema.posts.* FROM custom_schema.comments INNER JOIN custom_schema.posts ON (custom_schema.posts.id = custom_schema.comments.post_id) WHERE (comments.user_id = 2)'
|
489
|
+
]
|
490
|
+
end
|
491
|
+
|
492
|
+
end
|
493
|
+
|
494
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'coverage_helper'
|
2
|
+
require 'rasti-db'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'minitest/colorin'
|
5
|
+
require 'pry-nav'
|
6
|
+
require 'logger'
|
7
|
+
require 'sequel/extensions/pg_hstore'
|
8
|
+
require 'sequel/extensions/pg_array'
|
9
|
+
require 'sequel/extensions/pg_json'
|
10
|
+
|
11
|
+
User = Rasti::DB::Model[:id, :name, :posts, :comments]
|
12
|
+
Post = Rasti::DB::Model[:id, :title, :body, :user_id, :user, :comments, :categories]
|
13
|
+
Comment = Rasti::DB::Model[:id, :text, :user_id, :user, :post_id, :post]
|
14
|
+
Category = Rasti::DB::Model[:id, :name, :posts]
|
15
|
+
|
16
|
+
|
17
|
+
class Users < Rasti::DB::Collection
|
18
|
+
one_to_many :posts
|
19
|
+
one_to_many :comments
|
20
|
+
end
|
21
|
+
|
22
|
+
class Posts < Rasti::DB::Collection
|
23
|
+
many_to_one :user
|
24
|
+
many_to_many :categories
|
25
|
+
one_to_many :comments
|
26
|
+
|
27
|
+
query :created_by, ->(user_id) { where user_id: user_id }
|
28
|
+
|
29
|
+
query :entitled do |title|
|
30
|
+
where title: title
|
31
|
+
end
|
32
|
+
|
33
|
+
query :commented_by do |user_id|
|
34
|
+
chainable do
|
35
|
+
dataset.join(with_schema(:comments), post_id: :id)
|
36
|
+
.where(with_schema(:comments, :user_id) => user_id)
|
37
|
+
.select_all(with_schema(:posts))
|
38
|
+
.distinct
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Comments < Rasti::DB::Collection
|
44
|
+
many_to_one :user
|
45
|
+
many_to_one :post
|
46
|
+
|
47
|
+
def posts_commented_by(user_id)
|
48
|
+
dataset.where(comments__user_id: user_id)
|
49
|
+
.join(with_schema(:posts), id: :post_id)
|
50
|
+
.select_all(with_schema(:posts))
|
51
|
+
.map { |row| Post.new row }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Categories < Rasti::DB::Collection
|
56
|
+
many_to_many :posts
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
Rasti::DB::TypeConverter::CONVERTIONS[:sqlite] = {
|
61
|
+
/integer/ => ->(value, match) { value.to_i }
|
62
|
+
}
|
63
|
+
|
64
|
+
|
65
|
+
class Minitest::Spec
|
66
|
+
|
67
|
+
DB_DRIVER = (RUBY_ENGINE == 'jruby') ? 'jdbc:sqlite::memory:' : {adapter: :sqlite}
|
68
|
+
|
69
|
+
let(:users) { Users.new db }
|
70
|
+
|
71
|
+
let(:posts) { Posts.new db }
|
72
|
+
|
73
|
+
let(:comments) { Comments.new db }
|
74
|
+
|
75
|
+
let(:categories) { Categories.new db }
|
76
|
+
|
77
|
+
let :db do
|
78
|
+
db = Sequel.connect DB_DRIVER
|
79
|
+
|
80
|
+
db.create_table :users do
|
81
|
+
primary_key :id
|
82
|
+
String :name, null: false, unique: true
|
83
|
+
end
|
84
|
+
|
85
|
+
db.create_table :posts do
|
86
|
+
primary_key :id
|
87
|
+
String :title, null: false, unique: true
|
88
|
+
String :body, null: false
|
89
|
+
foreign_key :user_id, :users, null: false, index: true
|
90
|
+
end
|
91
|
+
|
92
|
+
db.create_table :comments do
|
93
|
+
primary_key :id
|
94
|
+
String :text, null: false
|
95
|
+
foreign_key :user_id, :users, null: false, index: true
|
96
|
+
foreign_key :post_id, :posts, null: false, index: true
|
97
|
+
end
|
98
|
+
|
99
|
+
db.create_table :categories do
|
100
|
+
primary_key :id
|
101
|
+
String :name, null: false, unique: true
|
102
|
+
end
|
103
|
+
|
104
|
+
db.create_table :categories_posts do
|
105
|
+
foreign_key :category_id, :categories, null: false, index: true
|
106
|
+
foreign_key :post_id, :posts, null: false, index: true
|
107
|
+
primary_key [:category_id, :post_id]
|
108
|
+
end
|
109
|
+
|
110
|
+
db
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
data/spec/model_spec.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe 'Model' do
|
4
|
+
|
5
|
+
describe 'Attribues' do
|
6
|
+
|
7
|
+
it 'Valid definition' do
|
8
|
+
model = Rasti::DB::Model[:id, :name]
|
9
|
+
model.attributes.must_equal [:id, :name]
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'Invalid definition' do
|
13
|
+
error = proc { model = Rasti::DB::Model[:id, :name, :name] }.must_raise ArgumentError
|
14
|
+
error.message.must_equal 'Attribute name already exists'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'Accessors' do
|
18
|
+
post = Post.new id: 1, title: 'Title'
|
19
|
+
|
20
|
+
post.id.must_equal 1
|
21
|
+
post.title.must_equal 'Title'
|
22
|
+
|
23
|
+
[:body, :user, :comments].each do |attribute|
|
24
|
+
error = proc { post.send attribute }.must_raise Rasti::DB::Model::UninitializedAttributeError
|
25
|
+
error.message.must_equal "Uninitialized attribute #{attribute}"
|
26
|
+
end
|
27
|
+
|
28
|
+
proc { post.invalid_method }.must_raise NoMethodError
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
it 'Inheritance' do
|
35
|
+
subclass = Class.new(User) do
|
36
|
+
attribute :additional_attribute
|
37
|
+
end
|
38
|
+
|
39
|
+
subclass.attributes.must_equal (User.attributes + [:additional_attribute])
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'To String' do
|
43
|
+
|
44
|
+
it 'Class' do
|
45
|
+
User.to_s.must_equal 'User[id, name, posts, comments]'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'Instance' do
|
49
|
+
user = User.new id: 1, name: 'User 1'
|
50
|
+
user.to_s.must_equal '#<User[id: 1, name: "User 1"]>'
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'To Hash' do
|
56
|
+
post = Post.new id: 2,
|
57
|
+
title: 'Title',
|
58
|
+
body: 'body',
|
59
|
+
user_id: 1,
|
60
|
+
user: User.new(id: 1, name: 'User 1'),
|
61
|
+
comments: [Comment.new(id: 4, text: 'comment text', user_id: 5)]
|
62
|
+
|
63
|
+
post.to_h.must_equal id: 2,
|
64
|
+
title: 'Title',
|
65
|
+
body: 'body',
|
66
|
+
user_id: 1,
|
67
|
+
user: {id: 1, name: 'User 1'},
|
68
|
+
comments: [{id: 4, text: 'comment text', user_id: 5}]
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'Equality' do
|
72
|
+
assert User.new(id: 1, name: 'User 1') == User.new(id: 1, name: 'User 1')
|
73
|
+
refute User.new(id: 1, name: 'User 1') == User.new(id: 2, name: 'User 2')
|
74
|
+
|
75
|
+
assert User.new(id: 1, name: 'User 1').eql? User.new(id: 1, name: 'User 1')
|
76
|
+
refute User.new(id: 1, name: 'User 1').eql? User.new(id: 2, name: 'User 2')
|
77
|
+
|
78
|
+
assert_equal User.new(id: 1, name: 'User 1').hash, User.new(id: 1, name: 'User 1').hash
|
79
|
+
refute_equal User.new(id: 1, name: 'User 1').hash, User.new(id: 2, name: 'User 2').hash
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|