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.
@@ -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,5 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new [SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter]
5
+ SimpleCov.start
@@ -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
@@ -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