rasti-db 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,10 +14,11 @@ Rasti::DB.configure do |config|
14
14
  end
15
15
 
16
16
  User = Rasti::DB::Model[:id, :name, :posts, :comments, :person]
17
- Post = Rasti::DB::Model[:id, :title, :body, :user_id, :user, :comments, :categories]
17
+ Post = Rasti::DB::Model[:id, :title, :body, :user_id, :user, :comments, :categories, :language_id, :language]
18
18
  Comment = Rasti::DB::Model[:id, :text, :user_id, :user, :post_id, :post]
19
19
  Category = Rasti::DB::Model[:id, :name, :posts]
20
- Person = Rasti::DB::Model[:document_number, :first_name, :last_name, :birth_date, :user_id, :user]
20
+ Person = Rasti::DB::Model[:document_number, :first_name, :last_name, :birth_date, :user_id, :user, :languages]
21
+ Language = Rasti::DB::Model[:id, :name, :people]
21
22
 
22
23
 
23
24
  class Users < Rasti::DB::Collection
@@ -28,6 +29,7 @@ end
28
29
 
29
30
  class Posts < Rasti::DB::Collection
30
31
  many_to_one :user
32
+ many_to_one :language
31
33
  many_to_many :categories
32
34
  one_to_many :comments
33
35
 
@@ -39,8 +41,8 @@ class Posts < Rasti::DB::Collection
39
41
 
40
42
  query :commented_by do |user_id|
41
43
  chainable do
42
- dataset.join(with_schema(:comments), post_id: :id)
43
- .where(with_schema(:comments, :user_id) => user_id)
44
+ dataset.join(qualify(:comments), post_id: :id)
45
+ .where(Sequel[:comments][:user_id] => user_id)
44
46
  .select_all(:posts)
45
47
  .distinct
46
48
  end
@@ -53,7 +55,7 @@ class Comments < Rasti::DB::Collection
53
55
 
54
56
  def posts_commented_by(user_id)
55
57
  dataset.where(Sequel[:comments][:user_id] => user_id)
56
- .join(with_schema(:posts), id: :post_id)
58
+ .join(qualify(:posts, data_source_name: :default), id: :post_id)
57
59
  .select_all(:posts)
58
60
  .map { |row| Post.new row }
59
61
  end
@@ -70,24 +72,39 @@ class People < Rasti::DB::Collection
70
72
  set_model Person
71
73
 
72
74
  many_to_one :user
75
+ many_to_many :languages
76
+ end
77
+
78
+ class Languages < Rasti::DB::Collection
79
+ set_data_source_name :custom
80
+
81
+ many_to_many :people, collection: People, relation_data_source_name: :default
82
+ one_to_many :posts
73
83
  end
74
84
 
75
85
 
76
86
  class Minitest::Spec
77
87
 
78
- let(:users) { Users.new db }
88
+ let(:users) { Users.new environment }
79
89
 
80
- let(:posts) { Posts.new db }
90
+ let(:posts) { Posts.new environment }
81
91
 
82
- let(:comments) { Comments.new db }
92
+ let(:comments) { Comments.new environment }
83
93
 
84
- let(:categories) { Categories.new db }
94
+ let(:categories) { Categories.new environment }
85
95
 
86
- let(:people) { People.new db }
96
+ let(:people) { People.new environment }
87
97
 
88
- let :db do
89
- driver = (RUBY_ENGINE == 'jruby') ? 'jdbc:sqlite::memory:' : {adapter: :sqlite}
98
+ let(:languages) { Languages.new environment }
90
99
 
100
+ let(:driver) { (RUBY_ENGINE == 'jruby') ? 'jdbc:sqlite::memory:' : {adapter: :sqlite} }
101
+
102
+ let :environment do
103
+ Rasti::DB::Environment.new default: Rasti::DB::DataSource.new(db),
104
+ custom: Rasti::DB::DataSource.new(custom_db)
105
+ end
106
+
107
+ let :db do
91
108
  Sequel.connect(driver).tap do |db|
92
109
 
93
110
  db.create_table :users do
@@ -99,6 +116,7 @@ class Minitest::Spec
99
116
  primary_key :id
100
117
  String :title, null: false, unique: true
101
118
  String :body, null: false
119
+ Integer :language_id, null: false, index: true
102
120
  foreign_key :user_id, :users, null: false, index: true
103
121
  end
104
122
 
@@ -128,6 +146,23 @@ class Minitest::Spec
128
146
  foreign_key :user_id, :users, null: false, unique: true
129
147
  end
130
148
 
149
+ db.create_table :languages_people do
150
+ Integer :language_id, null: false, index: true
151
+ foreign_key :document_number, :people, type: String, null: false, index: true
152
+ primary_key [:language_id, :document_number]
153
+ end
154
+
155
+ end
156
+ end
157
+
158
+ let :custom_db do
159
+ Sequel.connect(driver).tap do |db|
160
+
161
+ db.create_table :languages do
162
+ primary_key :id
163
+ String :name, null: false, unique: true
164
+ end
165
+
131
166
  end
132
167
  end
133
168
 
data/spec/model_spec.rb CHANGED
@@ -10,7 +10,7 @@ describe 'Model' do
10
10
  end
11
11
 
12
12
  it 'Invalid definition' do
13
- error = proc { model = Rasti::DB::Model[:id, :name, :name] }.must_raise ArgumentError
13
+ error = proc { Rasti::DB::Model[:id, :name, :name] }.must_raise ArgumentError
14
14
  error.message.must_equal 'Attribute name already exists'
15
15
  end
16
16
 
@@ -82,6 +82,8 @@ describe 'Model' do
82
82
  it 'Merge' do
83
83
  user = User.new(id: 1, name: 'User 1')
84
84
  changed_user = user.merge(name: 'User 2')
85
+
86
+ user.must_equal User.new(id: 1, name: 'User 1')
85
87
  changed_user.must_equal User.new(id: 1, name: 'User 2')
86
88
  end
87
89
 
data/spec/query_spec.rb CHANGED
@@ -3,19 +3,23 @@ require 'minitest_helper'
3
3
  describe 'Query' do
4
4
 
5
5
  before do
6
+ custom_db[:languages].insert name: 'Spanish'
7
+
6
8
  1.upto(10) do |i|
7
9
  db[:users].insert name: "User #{i}"
8
10
 
9
11
  db[:people].insert user_id: i,
10
- document_number: i,
12
+ document_number: "document_#{i}",
11
13
  first_name: "Name #{i}",
12
14
  last_name: "Last Name #{i}",
13
- birth_date: Time.now
15
+ birth_date: Date.parse('2020-04-24')
16
+
17
+ db[:languages_people].insert language_id: 1, document_number: "document_#{i}"
14
18
  end
15
19
 
16
- db[:posts].insert user_id: 2, title: 'Sample post', body: '...'
17
- db[:posts].insert user_id: 1, title: 'Another post', body: '...'
18
- db[:posts].insert user_id: 4, title: 'Best post', body: '...'
20
+ db[:posts].insert user_id: 2, title: 'Sample post', body: '...', language_id: 1
21
+ db[:posts].insert user_id: 1, title: 'Another post', body: '...', language_id: 1
22
+ db[:posts].insert user_id: 4, title: 'Best post', body: '...', language_id: 1
19
23
 
20
24
  1.upto(3) { |i| db[:categories].insert name: "Category #{i}" }
21
25
 
@@ -30,11 +34,13 @@ describe 'Query' do
30
34
  db[:categories_posts].insert post_id: 3, category_id: 3
31
35
  end
32
36
 
33
- let(:users_query) { Rasti::DB::Query.new collection_class: Users, dataset: db[:users] }
37
+ let(:users_query) { Rasti::DB::Query.new collection_class: Users, dataset: db[:users], environment: environment }
34
38
 
35
- let(:posts_query) { Rasti::DB::Query.new collection_class: Posts, dataset: db[:posts] }
39
+ let(:posts_query) { Rasti::DB::Query.new collection_class: Posts, dataset: db[:posts], environment: environment }
36
40
 
37
- let(:comments_query) { Rasti::DB::Query.new collection_class: Comments, dataset: db[:comments] }
41
+ let(:comments_query) { Rasti::DB::Query.new collection_class: Comments, dataset: db[:comments], environment: environment }
42
+
43
+ let(:languages_query) { Rasti::DB::Query.new collection_class: Languages, dataset: custom_db[:languages], environment: environment }
38
44
 
39
45
  it 'Count' do
40
46
  users_query.count.must_equal 10
@@ -62,7 +68,7 @@ describe 'Query' do
62
68
  end
63
69
 
64
70
  it 'Exclude attributes' do
65
- posts_query.exclude_attributes(:body).all.must_equal db[:posts].select(:id, :user_id, :title).map { |r| Post.new r }
71
+ posts_query.exclude_attributes(:body).all.must_equal db[:posts].select(:id, :user_id, :title, :language_id).map { |r| Post.new r }
66
72
  end
67
73
 
68
74
  it 'All attributes' do
@@ -70,35 +76,57 @@ describe 'Query' do
70
76
  end
71
77
 
72
78
  it 'Select graph attributes' do
73
- person = Person.new db[:people].where(document_number: 2).select(:first_name, :last_name, :user_id).first
79
+ language = Language.new custom_db[:languages].where(id: 1).select(:id).first
80
+
81
+ person = Person.new db[:people].where(document_number: 'document_2').select(:document_number, :user_id).first.merge(languages: [language])
74
82
 
75
83
  user = User.new db[:users].where(id: 2).select(:id).first.merge(person: person)
76
84
 
77
- post = Post.new db[:posts].where(id: 1).first.merge(user: user)
85
+ categories = db[:categories].where(id: [1,2]).select(:id).map { |c| Category.new c }
86
+
87
+ post = Post.new db[:posts].where(id: 1).first.merge(user: user, categories: categories)
88
+
89
+ selected_attributes = {
90
+ user: [:id],
91
+ 'user.person' => [:document_number, :user_id],
92
+ 'user.person.languages' => [:id],
93
+ categories: [:id]
94
+ }
78
95
 
79
96
  posts_query.where(id: 1)
80
- .graph('user.person')
81
- .select_graph_attributes(user: [:id], 'user.person' => [:first_name, :last_name, :user_id])
97
+ .graph(*selected_attributes.keys)
98
+ .select_graph_attributes(selected_attributes)
82
99
  .all
83
100
  .must_equal [post]
84
101
  end
85
102
 
86
103
  it 'Exclude graph attributes' do
87
- person = Person.new db[:people].where(document_number: 2).select(:document_number, :last_name, :user_id).first
104
+ language = Language.new custom_db[:languages].where(id: 1).select(:id).first
105
+
106
+ person = Person.new db[:people].where(document_number: 'document_2').select(:document_number, :user_id).first.merge(languages: [language])
88
107
 
89
108
  user = User.new db[:users].where(id: 2).select(:id).first.merge(person: person)
90
109
 
91
- post = Post.new db[:posts].where(id: 1).first.merge(user: user)
110
+ categories = db[:categories].where(id: [1,2]).select(:id).map { |c| Category.new c }
111
+
112
+ post = Post.new db[:posts].where(id: 1).first.merge(user: user, categories: categories)
113
+
114
+ excluded_attributes = {
115
+ user: [:name],
116
+ 'user.person' => [:first_name, :last_name, :birth_date],
117
+ 'user.person.languages' => [:name],
118
+ categories: [:name]
119
+ }
92
120
 
93
121
  posts_query.where(id: 1)
94
- .graph('user.person')
95
- .exclude_graph_attributes(user: [:name], 'user.person' => [:first_name, :birth_date])
122
+ .graph(*excluded_attributes.keys)
123
+ .exclude_graph_attributes(excluded_attributes)
96
124
  .all
97
125
  .must_equal [post]
98
126
  end
99
127
 
100
128
  it 'All graph attributes' do
101
- person = Person.new db[:people].where(document_number: 2).first
129
+ person = Person.new db[:people].where(document_number: 'document_2').first
102
130
 
103
131
  user = User.new db[:users].where(id: 2).select(:id).first.merge(person: person)
104
132
 
@@ -141,17 +169,17 @@ describe 'Query' do
141
169
 
142
170
  it 'Order' do
143
171
  posts_query.order(:title).all.must_equal [
144
- Post.new(id: 2, user_id: 1, title: 'Another post', body: '...'),
145
- Post.new(id: 3, user_id: 4, title: 'Best post', body: '...'),
146
- Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...')
172
+ Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1),
173
+ Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
174
+ Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...', language_id: 1)
147
175
  ]
148
176
  end
149
177
 
150
178
  it 'Reverse order' do
151
179
  posts_query.reverse_order(:title).all.must_equal [
152
- Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...'),
153
- Post.new(id: 3, user_id: 4, title: 'Best post', body: '...'),
154
- Post.new(id: 2, user_id: 1, title: 'Another post', body: '...')
180
+ Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...', language_id: 1),
181
+ Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
182
+ Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1)
155
183
  ]
156
184
  end
157
185
 
@@ -168,7 +196,32 @@ describe 'Query' do
168
196
  end
169
197
 
170
198
  it 'Graph' do
171
- users_query.graph(:posts).where(id: 1).first.must_equal User.new(id: 1, name: 'User 1', posts: [Post.new(id: 2, user_id: 1, title: 'Another post', body: '...')])
199
+ users_query.graph(:posts).where(id: 1).first.must_equal User.new(id: 1, name: 'User 1', posts: [Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1)])
200
+ end
201
+
202
+ it 'Graph with multiple data sources' do
203
+ language = Language.new id: 1, name: 'Spanish'
204
+
205
+ person = Person.new user_id: 2,
206
+ document_number: 'document_2',
207
+ first_name: 'Name 2',
208
+ last_name: 'Last Name 2',
209
+ birth_date: Date.parse('2020-04-24'),
210
+ languages: [language]
211
+
212
+ user = User.new id: 2,
213
+ name: 'User 2',
214
+ person: person
215
+
216
+ post = Post.new id: 1,
217
+ user_id: 2,
218
+ user: user,
219
+ title: 'Sample post',
220
+ body: '...',
221
+ language_id: 1,
222
+ language: language
223
+
224
+ posts_query.where(id: 1).graph(:language, 'user.person.languages').first.must_equal post
172
225
  end
173
226
 
174
227
  it 'Any?' do
@@ -208,26 +261,44 @@ describe 'Query' do
208
261
  end
209
262
 
210
263
  it 'Many to One' do
211
- posts_query.join(:user).where(name: 'User 4').all.must_equal [Post.new(id: 3, user_id: 4, title: 'Best post', body: '...')]
264
+ posts_query.join(:user).where(name: 'User 4').all.must_equal [Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1)]
212
265
  end
213
266
 
214
267
  it 'One to One' do
215
- users_query.join(:person).where(document_number: 1).all.must_equal [User.new(id: 1, name: 'User 1')]
268
+ users_query.join(:person).where(document_number: 'document_1').all.must_equal [User.new(id: 1, name: 'User 1')]
216
269
  end
217
270
 
218
271
  it 'Many to Many' do
219
272
  posts_query.join(:categories).where(name: 'Category 3').order(:id).all.must_equal [
220
- Post.new(id: 2, user_id: 1, title: 'Another post', body: '...'),
221
- Post.new(id: 3, user_id: 4, title: 'Best post', body: '...'),
273
+ Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1),
274
+ Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
222
275
  ]
223
276
  end
224
277
 
225
278
  it 'Nested' do
226
279
  posts_query.join('categories', 'comments.user.person')
227
280
  .where(Sequel[:categories][:name] => 'Category 2')
228
- .where(Sequel[:comments__user__person][:document_number] => 7)
281
+ .where(Sequel[:comments__user__person][:document_number] => 'document_7')
229
282
  .all
230
- .must_equal [Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...')]
283
+ .must_equal [Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...', language_id: 1)]
284
+ end
285
+
286
+ describe 'Multiple data sources' do
287
+
288
+ it 'One to Many' do
289
+ error = proc { languages_query.join(:posts).all }.must_raise RuntimeError
290
+ error.message.must_equal 'Invalid join of multiple data sources: custom.languages > default.posts'
291
+ end
292
+
293
+ it 'Many to One' do
294
+ error = proc { posts_query.join(:language).all }.must_raise RuntimeError
295
+ error.message.must_equal 'Invalid join of multiple data sources: default.posts > custom.languages'
296
+ end
297
+
298
+ it 'Many to Many' do
299
+ error = proc { languages_query.join(:people).all }.must_raise RuntimeError
300
+ error.message.must_equal 'Invalid join of multiple data sources: custom.languages > default.people'
301
+ end
231
302
  end
232
303
 
233
304
  end
@@ -254,13 +325,13 @@ describe 'Query' do
254
325
  end
255
326
 
256
327
  it 'Filter to 2nd order relation' do
257
- posts_query.nql('comments.user.person.document_number = 7')
328
+ posts_query.nql('comments.user.person.document_number = document_7')
258
329
  .pluck(:id)
259
330
  .must_equal [1]
260
331
  end
261
332
 
262
333
  it 'Filter combined' do
263
- posts_query.nql('(categories.id = 1 | categories.id = 3) & comments.user.person.document_number = 2')
334
+ posts_query.nql('(categories.id = 1 | categories.id = 3) & comments.user.person.document_number = document_2')
264
335
  .pluck(:id)
265
336
  .must_equal [2]
266
337
  end
@@ -30,14 +30,19 @@ describe 'Relations' do
30
30
  relation.many_to_one?.must_equal false
31
31
  relation.many_to_many?.must_equal false
32
32
  relation.one_to_one?.must_equal false
33
+
34
+ relation.from_one?.must_equal true
35
+ relation.from_many?.must_equal false
36
+ relation.to_one?.must_equal false
37
+ relation.to_many?.must_equal true
33
38
  end
34
39
 
35
40
  it 'Graph' do
36
41
  user_id = db[:users].insert name: 'User 1'
37
- 1.upto(2) { |i| db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...' }
42
+ 1.upto(2) { |i| db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...', language_id: 1 }
38
43
  rows = db[:users].all
39
44
 
40
- Users.relations[:posts].fetch_graph rows, db
45
+ Users.relations[:posts].fetch_graph environment, rows
41
46
 
42
47
  rows[0][:posts].must_equal posts.where(user_id: user_id).all
43
48
  end
@@ -72,14 +77,19 @@ describe 'Relations' do
72
77
  relation.many_to_one?.must_equal true
73
78
  relation.many_to_many?.must_equal false
74
79
  relation.one_to_one?.must_equal false
80
+
81
+ relation.from_one?.must_equal false
82
+ relation.from_many?.must_equal true
83
+ relation.to_one?.must_equal true
84
+ relation.to_many?.must_equal false
75
85
  end
76
86
 
77
87
  it 'Graph' do
78
88
  user_id = db[:users].insert name: 'User 1'
79
- db[:posts].insert user_id: user_id, title: 'Post 1', body: '...'
89
+ db[:posts].insert user_id: user_id, title: 'Post 1', body: '...', language_id: 1
80
90
  rows = db[:posts].all
81
91
 
82
- Posts.relations[:user].fetch_graph rows, db
92
+ Posts.relations[:user].fetch_graph environment, rows
83
93
 
84
94
  rows[0][:user].must_equal users.first
85
95
  end
@@ -120,12 +130,17 @@ describe 'Relations' do
120
130
  relation.many_to_one?.must_equal false
121
131
  relation.many_to_many?.must_equal true
122
132
  relation.one_to_one?.must_equal false
133
+
134
+ relation.from_one?.must_equal false
135
+ relation.from_many?.must_equal true
136
+ relation.to_one?.must_equal false
137
+ relation.to_many?.must_equal true
123
138
  end
124
139
 
125
140
  it 'Graph' do
126
141
  user_id = db[:users].insert name: 'User 1'
127
142
 
128
- 1.upto(2) { |i| db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...' }
143
+ 1.upto(2) { |i| db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...', language_id: 1 }
129
144
 
130
145
  1.upto(4) { |i| db[:categories].insert name: "Category #{i}" }
131
146
 
@@ -136,7 +151,7 @@ describe 'Relations' do
136
151
 
137
152
  rows = db[:posts].all
138
153
 
139
- Posts.relations[:categories].fetch_graph rows, db
154
+ Posts.relations[:categories].fetch_graph environment, rows
140
155
 
141
156
  rows[0][:categories].must_equal categories.where(id: [1,2]).all
142
157
  rows[1][:categories].must_equal categories.where(id: [3,4]).all
@@ -172,6 +187,11 @@ describe 'Relations' do
172
187
  relation.many_to_one?.must_equal false
173
188
  relation.many_to_many?.must_equal false
174
189
  relation.one_to_one?.must_equal true
190
+
191
+ relation.from_one?.must_equal true
192
+ relation.from_many?.must_equal false
193
+ relation.to_one?.must_equal true
194
+ relation.to_many?.must_equal false
175
195
  end
176
196
 
177
197
  it 'Graph' do
@@ -186,7 +206,7 @@ describe 'Relations' do
186
206
 
187
207
  rows = db[:users].all
188
208
 
189
- Users.relations[:person].fetch_graph rows, db
209
+ Users.relations[:person].fetch_graph environment, rows
190
210
 
191
211
  2.times do |i|
192
212
  rows[i][:person].must_equal people.find("document_#{i}")