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,122 @@
1
+ require 'minitest_helper'
2
+
3
+ describe 'Query' do
4
+
5
+ before do
6
+ 1.upto(10) { |i| db[:users].insert name: "User #{i}" }
7
+ db[:posts].insert user_id: 2, title: 'Sample post', body: '...'
8
+ db[:posts].insert user_id: 1, title: 'Another post', body: '...'
9
+ db[:posts].insert user_id: 4, title: 'Best post', body: '...'
10
+ end
11
+
12
+ let(:users_query) { Rasti::DB::Query.new Users, db[:users] }
13
+
14
+ let(:posts_query) { Rasti::DB::Query.new Posts, db[:posts] }
15
+
16
+ let(:comments_query) { Rasti::DB::Query.new Comments, db[:comments] }
17
+
18
+ it 'Count' do
19
+ users_query.count.must_equal 10
20
+ end
21
+
22
+ it 'All' do
23
+ users_query.all.must_equal db[:users].map { |u| User.new u }
24
+ end
25
+
26
+ it 'Raw' do
27
+ users_query.raw.must_equal db[:users].all
28
+ end
29
+
30
+ it 'Pluck' do
31
+ users_query.pluck(:name).must_equal db[:users].map { |u| u[:name] }
32
+ users_query.pluck(:id, :name).must_equal db[:users].map { |u| [u[:id], u[:name]] }
33
+ end
34
+
35
+ it 'Primary keys' do
36
+ users_query.primary_keys.must_equal db[:users].map { |u| u[:id] }
37
+ end
38
+
39
+ it 'Map' do
40
+ users_query.map { |u| u.name }.must_equal db[:users].map(:name)
41
+ end
42
+
43
+ it 'Where' do
44
+ users_query.where(id: 3).all.must_equal [User.new(id: 3, name: 'User 3')]
45
+ end
46
+
47
+ it 'Exclude' do
48
+ users_query.exclude(id: [1,2,3,4,5,6,7,8,9]).all.must_equal [User.new(id: 10, name: 'User 10')]
49
+ end
50
+
51
+ it 'And' do
52
+ users_query.where(id: [1,2]).and(name: 'User 2').all.must_equal [User.new(id: 2, name: 'User 2')]
53
+ end
54
+
55
+ it 'Or' do
56
+ users_query.where(id: 1).or(name: 'User 2').all.must_equal [
57
+ User.new(id: 1, name: 'User 1'),
58
+ User.new(id: 2, name: 'User 2')
59
+ ]
60
+ end
61
+
62
+ it 'Order' do
63
+ posts_query.order(:title).all.must_equal [
64
+ Post.new(id: 2, user_id: 1, title: 'Another post', body: '...'),
65
+ Post.new(id: 3, user_id: 4, title: 'Best post', body: '...'),
66
+ Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...')
67
+ ]
68
+ end
69
+
70
+ it 'Reverse order' do
71
+ posts_query.reverse_order(:title).all.must_equal [
72
+ Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...'),
73
+ Post.new(id: 3, user_id: 4, title: 'Best post', body: '...'),
74
+ Post.new(id: 2, user_id: 1, title: 'Another post', body: '...')
75
+ ]
76
+ end
77
+
78
+ it 'Limit and offset' do
79
+ users_query.limit(1).offset(1).all.must_equal [User.new(id: 2, name: 'User 2')]
80
+ end
81
+
82
+ it 'First' do
83
+ users_query.first.must_equal User.new(id: 1, name: 'User 1')
84
+ end
85
+
86
+ it 'Last' do
87
+ users_query.order(:id).last.must_equal User.new(id: 10, name: 'User 10')
88
+ end
89
+
90
+ it 'Graph' do
91
+ 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: '...')])
92
+ end
93
+
94
+ it 'Empty?' do
95
+ users_query.empty?.must_equal false
96
+ users_query.any?.must_equal true
97
+ end
98
+
99
+ it 'Any?' do
100
+ comments_query.empty?.must_equal true
101
+ comments_query.any?.must_equal false
102
+ end
103
+
104
+ it 'To String' do
105
+ users_query.where(id: [1,2,3]).order(:name).to_s.must_equal '#<Rasti::DB::Query: "SELECT * FROM `users` WHERE (`id` IN (1, 2, 3)) ORDER BY `name`">'
106
+ end
107
+
108
+ describe 'Named queries' do
109
+
110
+ it 'Respond to' do
111
+ posts_query.must_respond_to :created_by
112
+ posts_query.wont_respond_to :by_user
113
+ end
114
+
115
+ it 'Safe method missing' do
116
+ posts_query.created_by(1).first.must_equal Post.new(db[:posts][user_id: 1])
117
+ proc { posts_query.by_user(1) }.must_raise NoMethodError
118
+ end
119
+
120
+ end
121
+
122
+ end
@@ -0,0 +1,144 @@
1
+ require 'minitest_helper'
2
+
3
+ describe 'Relations' do
4
+
5
+ describe 'One to Many' do
6
+
7
+ describe 'Specification' do
8
+
9
+ it 'Implicit' do
10
+ relation = Rasti::DB::Relations::OneToMany.new :posts, Users
11
+
12
+ relation.target_collection_class.must_equal Posts
13
+ relation.foreign_key.must_equal :user_id
14
+ end
15
+
16
+ it 'Explicit' do
17
+ relation = Rasti::DB::Relations::OneToMany.new :articles, Users, collection: 'Posts',
18
+ foreign_key: :id_user
19
+
20
+ relation.target_collection_class.must_equal Posts
21
+ relation.foreign_key.must_equal :id_user
22
+ end
23
+
24
+ end
25
+
26
+ it 'Type' do
27
+ relation = Rasti::DB::Relations::OneToMany.new :posts, Users
28
+
29
+ relation.one_to_many?.must_equal true
30
+ relation.many_to_one?.must_equal false
31
+ relation.many_to_many?.must_equal false
32
+ end
33
+
34
+ it 'Graph' do
35
+ user_id = db[:users].insert name: 'User 1'
36
+ 1.upto(2) { |i| db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...' }
37
+ rows = db[:users].all
38
+
39
+ Users.relations[:posts].graph_to rows, db
40
+
41
+ rows[0][:posts].must_equal posts.where(user_id: user_id).all
42
+ end
43
+
44
+ end
45
+
46
+ describe 'Many to One' do
47
+
48
+ describe 'Specification' do
49
+
50
+ it 'Implicit' do
51
+ relation = Rasti::DB::Relations::ManyToOne.new :user, Posts
52
+
53
+ relation.target_collection_class.must_equal Users
54
+ relation.foreign_key.must_equal :user_id
55
+ end
56
+
57
+ it 'Explicit' do
58
+ relation = Rasti::DB::Relations::ManyToOne.new :publisher, Posts, collection: 'Users',
59
+ foreign_key: :publisher_id
60
+
61
+ relation.target_collection_class.must_equal Users
62
+ relation.foreign_key.must_equal :publisher_id
63
+ end
64
+
65
+ end
66
+
67
+ it 'Type' do
68
+ relation = Rasti::DB::Relations::ManyToOne.new :user, Posts
69
+
70
+ relation.one_to_many?.must_equal false
71
+ relation.many_to_one?.must_equal true
72
+ relation.many_to_many?.must_equal false
73
+ end
74
+
75
+ it 'Graph' do
76
+ user_id = db[:users].insert name: 'User 1'
77
+ db[:posts].insert user_id: user_id, title: 'Post 1', body: '...'
78
+ rows = db[:posts].all
79
+
80
+ Posts.relations[:user].graph_to rows, db
81
+
82
+ rows[0][:user].must_equal users.first
83
+ end
84
+
85
+ end
86
+
87
+ describe 'Many To Many' do
88
+
89
+ describe 'Specification' do
90
+
91
+ it 'Implicit' do
92
+ relation = Rasti::DB::Relations::ManyToMany.new :categories, Posts
93
+
94
+ relation.target_collection_class.must_equal Categories
95
+ relation.source_foreign_key.must_equal :post_id
96
+ relation.target_foreign_key.must_equal :category_id
97
+ relation.relation_collection_name.must_equal :categories_posts
98
+ end
99
+
100
+ it 'Explicit' do
101
+ relation = Rasti::DB::Relations::ManyToMany.new :tags, Posts, collection: 'Categories',
102
+ source_foreign_key: :article_id,
103
+ target_foreign_key: :tag_id,
104
+ relation_collection_name: :tags_articles
105
+
106
+ relation.target_collection_class.must_equal Categories
107
+ relation.source_foreign_key.must_equal :article_id
108
+ relation.target_foreign_key.must_equal :tag_id
109
+ relation.relation_collection_name.must_equal :tags_articles
110
+ end
111
+
112
+ end
113
+
114
+ it 'Type' do
115
+ relation = Rasti::DB::Relations::ManyToMany.new :categories, Posts
116
+
117
+ relation.one_to_many?.must_equal false
118
+ relation.many_to_one?.must_equal false
119
+ relation.many_to_many?.must_equal true
120
+ end
121
+
122
+ it 'Graph' do
123
+ user_id = db[:users].insert name: 'User 1'
124
+
125
+ 1.upto(2) { |i| db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...' }
126
+
127
+ 1.upto(4) { |i| db[:categories].insert name: "Category #{i}" }
128
+
129
+ db[:categories_posts].insert post_id: 1, category_id: 1
130
+ db[:categories_posts].insert post_id: 1, category_id: 2
131
+ db[:categories_posts].insert post_id: 2, category_id: 3
132
+ db[:categories_posts].insert post_id: 2, category_id: 4
133
+
134
+ rows = db[:posts].all
135
+
136
+ Posts.relations[:categories].graph_to rows, db
137
+
138
+ rows[0][:categories].must_equal categories.where(id: [1,2]).all
139
+ rows[1][:categories].must_equal categories.where(id: [3,4]).all
140
+ end
141
+
142
+ end
143
+
144
+ end
@@ -0,0 +1,98 @@
1
+ require 'minitest_helper'
2
+
3
+ describe 'Type Converter' do
4
+
5
+ it 'Apply convertion' do
6
+ type_converter = Rasti::DB::TypeConverter.new db, :users
7
+ type_converter.apply_to(id: '123', name: 'User 1').must_equal id: 123, name: 'User 1'
8
+ end
9
+
10
+ describe 'Postgres' do
11
+
12
+ let(:pg) do
13
+ Object.new.tap do |pg|
14
+ def pg.database_type
15
+ :postgres
16
+ end
17
+
18
+ def pg.schema(table_name, opts={})
19
+ [
20
+ [:hash, {db_type: 'hstore'}],
21
+ [:text_array, {db_type: 'text[]'}],
22
+ [:integer_array, {db_type: 'integer[]'}],
23
+ [:hstore_array, {db_type: 'hstore[]'}],
24
+ [:json, {db_type: 'json'}]
25
+ ]
26
+ end
27
+ end
28
+ end
29
+
30
+ let(:type_converter) { Rasti::DB::TypeConverter.new pg, :table_name }
31
+
32
+ it 'HStore' do
33
+ attributes = type_converter.apply_to hash: {key_1: 1, key_2: 2}
34
+
35
+ attributes[:hash].class.must_equal Sequel::Postgres::HStore
36
+ attributes[:hash].must_equal 'key_1' => '1', 'key_2' => '2'
37
+ end
38
+
39
+ it 'Empty hstore' do
40
+ attributes = type_converter.apply_to hash: {}
41
+
42
+ attributes[:hash].class.must_equal Sequel::Postgres::HStore
43
+ attributes[:hash].must_equal Hash.new
44
+ end
45
+
46
+ it 'Text array' do
47
+ attributes = type_converter.apply_to text_array: %w(a b c)
48
+
49
+ attributes[:text_array].class.must_equal Sequel::Postgres::PGArray
50
+ attributes[:text_array].array_type.must_equal 'text'
51
+ attributes[:text_array].must_equal %w(a b c)
52
+ end
53
+
54
+ it 'Integer array' do
55
+ attributes = type_converter.apply_to integer_array: [1,2,3]
56
+
57
+ attributes[:integer_array].class.must_equal Sequel::Postgres::PGArray
58
+ attributes[:integer_array].array_type.must_equal 'integer'
59
+ attributes[:integer_array].must_equal [1,2,3]
60
+ end
61
+
62
+ it 'Hstore array' do
63
+ attributes = type_converter.apply_to hstore_array: [{key: 0}, {key: 1}]
64
+
65
+ attributes[:hstore_array].class.must_equal Sequel::Postgres::PGArray
66
+ attributes[:hstore_array].array_type.must_equal 'hstore'
67
+
68
+ 2.times do |i|
69
+ attributes[:hstore_array][i].class.must_equal Sequel::Postgres::HStore
70
+ attributes[:hstore_array][i].must_equal 'key' => i.to_s
71
+ end
72
+ end
73
+
74
+ it 'Empty array' do
75
+ attributes = type_converter.apply_to integer_array: []
76
+
77
+ attributes[:integer_array].class.must_equal Sequel::Postgres::PGArray
78
+ attributes[:integer_array].array_type.must_equal 'integer'
79
+ attributes[:integer_array].must_equal []
80
+ end
81
+
82
+ it 'Json' do
83
+ attributes = type_converter.apply_to json: {key_1: {key_2: [3]}}
84
+
85
+ attributes[:json].class.must_equal Sequel::Postgres::JSONHash
86
+ attributes[:json].must_equal key_1: {key_2: [3]}
87
+ end
88
+
89
+ it 'Json array' do
90
+ attributes = type_converter.apply_to json: [{key_1: {key_2: [3]}}]
91
+
92
+ attributes[:json].class.must_equal Sequel::Postgres::JSONArray
93
+ attributes[:json].must_equal [{key_1: {key_2: [3]}}]
94
+ end
95
+
96
+ end
97
+
98
+ end
metadata ADDED
@@ -0,0 +1,231 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rasti-db
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Gabriel Naiman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sequel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.38'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.38'
27
+ - !ruby/object:Gem::Dependency
28
+ name: consty
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '11.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '11.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest-colorin
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.1'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: minitest-line
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.6'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.6'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.12'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.12'
125
+ - !ruby/object:Gem::Dependency
126
+ name: coveralls
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.8'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.8'
139
+ - !ruby/object:Gem::Dependency
140
+ name: pry-nav
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.2'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.2'
153
+ - !ruby/object:Gem::Dependency
154
+ name: sqlite3
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.3'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '1.3'
167
+ description: Database collections and relations
168
+ email:
169
+ - gabynaiman@gmail.com
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - ".coveralls.yml"
175
+ - ".gitignore"
176
+ - ".ruby-gemset"
177
+ - ".ruby-version"
178
+ - ".travis.yml"
179
+ - Gemfile
180
+ - LICENSE.txt
181
+ - README.md
182
+ - Rakefile
183
+ - lib/rasti-db.rb
184
+ - lib/rasti/db.rb
185
+ - lib/rasti/db/collection.rb
186
+ - lib/rasti/db/helpers.rb
187
+ - lib/rasti/db/model.rb
188
+ - lib/rasti/db/query.rb
189
+ - lib/rasti/db/relations.rb
190
+ - lib/rasti/db/type_converter.rb
191
+ - lib/rasti/db/version.rb
192
+ - rasti-db.gemspec
193
+ - spec/collection_spec.rb
194
+ - spec/coverage_helper.rb
195
+ - spec/minitest_helper.rb
196
+ - spec/model_spec.rb
197
+ - spec/query_spec.rb
198
+ - spec/relations_spec.rb
199
+ - spec/type_converter_spec.rb
200
+ homepage: https://github.com/gabynaiman/rasti-db
201
+ licenses:
202
+ - MIT
203
+ metadata: {}
204
+ post_install_message:
205
+ rdoc_options: []
206
+ require_paths:
207
+ - lib
208
+ required_ruby_version: !ruby/object:Gem::Requirement
209
+ requirements:
210
+ - - ">="
211
+ - !ruby/object:Gem::Version
212
+ version: '0'
213
+ required_rubygems_version: !ruby/object:Gem::Requirement
214
+ requirements:
215
+ - - ">="
216
+ - !ruby/object:Gem::Version
217
+ version: '0'
218
+ requirements: []
219
+ rubyforge_project:
220
+ rubygems_version: 2.5.1
221
+ signing_key:
222
+ specification_version: 4
223
+ summary: Database collections and relations
224
+ test_files:
225
+ - spec/collection_spec.rb
226
+ - spec/coverage_helper.rb
227
+ - spec/minitest_helper.rb
228
+ - spec/model_spec.rb
229
+ - spec/query_spec.rb
230
+ - spec/relations_spec.rb
231
+ - spec/type_converter_spec.rb