rasti-db 1.5.0 → 2.0.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.
@@ -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}")