ru.Bee 1.1.32 → 1.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '03808642660607dcc9ecbd0f6f2fbcfc510e48f28e4eb583a0aace626642142f'
4
- data.tar.gz: 11156690b45851b45f1ebeae3dff18ee8c9b44e2f3bef0a84d63a123f5e603a6
3
+ metadata.gz: 173d9793c002668ec637f531604481515d4a48b4482280248dfdb9c43e5d6684
4
+ data.tar.gz: d45bd460ef9db6c347f5b9bca7028fe403d2fb4d35b5ae8649efb2f1528f27f7
5
5
  SHA512:
6
- metadata.gz: 5b48a1ccc2b3c7c9f7a5eb9492f8fca77488d842599d1a38a6d64f2f2534e41d1e69d69de7aa6d045935c98578ad9b77b36ccedbbd72f3b4086b8855e8e87b4d
7
- data.tar.gz: 0c7067e04ddb2039b84a734a29ed743dcd187ea0ff8a21d076bd9c1c06d6413105c1c631b398c35186ee84c5a2d08c011cb24ed6b80bba0de57a3379f1d54d1b
6
+ metadata.gz: d2bb73fb7408c9261c3fb8f56d4b629805a9a0d04313ca81a6f68f3e19a5faff9c3901010e27dbce8d717161854a36e355dbdb26e81f56cee0c45f9490d43bf6
7
+ data.tar.gz: 1e241e252e183a725c1152d5ed9b81ef2a7d8fa1593de66361cd7164eaaab5a22678ddd8bc57957cfa5fd4a494bb135925d8c08c4a7835e6028489b1d2b2694f
data/bin/rubee CHANGED
@@ -160,7 +160,7 @@ elsif command == "test"
160
160
  color_puts "Running all tests ...", color: :yellow
161
161
  exec("ruby -Itest -e \"Dir.glob('.#{lib}/tests/**/*_test.rb').each { |file| require file }\"")
162
162
  end
163
- elsif ['generate', 'g'].include? command
163
+ elsif ['generate', 'gen'].include? command
164
164
  method, path = ARGV[1..2]
165
165
  ENV['RACK_ENV'] ||= 'development'
166
166
 
@@ -181,9 +181,9 @@ elsif command == "db"
181
181
  command, file_name = ARGV[1]&.split(':')
182
182
  if Rubee::PROJECT_NAME == 'rubee'
183
183
  Rubee::Configuration.setup(env=:test) do |config|
184
- config.database_url = { url: "sqlite://test.db", env: }
184
+ config.database_url = { url: "sqlite://lib/tests/test.db", env: }
185
185
  end
186
- Rubee::SequelObject.reconnect!
186
+ Rubee::SequelObject.reconnect! unless command == 'init'
187
187
  end
188
188
 
189
189
  def ensure_database_exists(db_url)
@@ -193,7 +193,7 @@ elsif command == "db"
193
193
  begin
194
194
  Sequel.connect(db_url)
195
195
  color_puts "Database #{ENV['RACK_ENV']} exists", color: :cyan
196
- rescue => _
196
+ rescue Exception => e
197
197
  if File.exist?(db_path = db_url.sub(/^sqlite:\/\//, ''))
198
198
  color_puts "Database #{ENV['RACK_ENV']} exists", color: :cyan
199
199
  else
@@ -237,14 +237,22 @@ elsif command == "db"
237
237
  end
238
238
 
239
239
 
240
- if command == 'run'
240
+ if command == 'run'
241
241
  Rubee::Autoload.call
242
+ file_names = if file_name == 'all'
243
+ lib = Rubee::PROJECT_NAME == 'rubee' ? '/lib' : ''
244
+ Dir.glob(".#{lib}/db/*.rb").map { |file| File.basename(file, '.rb') }.select { |file| file != 'structure' }
245
+ else
246
+ [file_name]
247
+ end
242
248
  Rubee::Configuration.envs.each do |env|
243
249
  ENV['RACK_ENV'] = env.to_s
244
- color_puts "Run #{file_name} file for #{env} env", color: :cyan
245
- Object.const_get(file_name.split('_').map(&:capitalize).join).new.call
250
+ file_names.each do |file_name|
251
+ color_puts "Run #{file_name} file for #{env} env", color: :cyan
252
+ Object.const_get(file_name.split('_').map(&:capitalize).join).new.call
253
+ end
246
254
  end
247
- color_puts "Migration #{file_name} completed", color: :green
255
+ color_puts "Migration for #{file_name} completed", color: :green
248
256
  unless Rubee::PROJECT_NAME == 'rubee'
249
257
  color_puts "Regenerate schema file", color: :cyan
250
258
  generate_structure
@@ -261,15 +269,25 @@ elsif ['console'].include? command
261
269
  ENV['RACK_ENV'] ||= 'development'
262
270
 
263
271
  Rubee::Autoload.call
272
+ if Rubee::PROJECT_NAME == 'rubee'
273
+ Rubee::Configuration.setup(env=:test) do |config|
274
+ config.database_url = { url: "sqlite://lib/tests/test.db", env: }
275
+ end
276
+ Rubee::Autoload.call
277
+ Rubee::SequelObject.reconnect!
278
+ end
264
279
 
265
280
  def reload
266
- app_files = Dir["./#{APP_ROOT}/**/*.rb"]
281
+ app_files = Dir["./#{Rubee::APP_ROOT}/**/*.rb"]
267
282
  app_files.each { |file| load file }
268
283
  color_puts "Reloaded ..", color: :green
269
284
  end
270
-
271
- # Start IRB
272
- IRB.start
285
+ begin
286
+ # Start IRB
287
+ IRB.start
288
+ rescue Exception => e
289
+ IRB.start
290
+ end
273
291
  else
274
292
  color_puts "Unknown command: #{command}", color: :red
275
293
  end
@@ -47,6 +47,8 @@
47
47
  <img src="images/rubee.svg" alt="ruBee">
48
48
  <br/>
49
49
  <p>rubee homepage: <a href="https://github.com/nucleom42/rubee"><br/>https://github.com/nucleom42/rubee</a></p>
50
+ <br/>
51
+ <p>Version: <%= Rubee::VERSION %></p>
50
52
  </div>
51
53
  </body>
52
54
  </html>
@@ -0,0 +1,14 @@
1
+ class CreateAccounts
2
+ def call
3
+ unless Rubee::SequelObject::DB.tables.include?(:accounts)
4
+ Rubee::SequelObject::DB.create_table :accounts do
5
+ primary_key :id
6
+ String :addres
7
+ foreign_key :user_id, :users
8
+ end
9
+
10
+ Account.create(addres: "13th Ave, NY", user_id: User.all.first.id)
11
+ Account.create(addres: "14th Ave, NY", user_id: User.all.last.id)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ class CreateComments
2
+ def call
3
+ unless Rubee::SequelObject::DB.tables.include?(:comments)
4
+ Rubee::SequelObject::DB.create_table :comments do
5
+ primary_key :id
6
+ String :text
7
+ Integer :user_id
8
+ end
9
+
10
+ User.create(email: "ok@ok.com", password: "password")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ class CreatePosts
2
+ def call
3
+ unless Rubee::SequelObject::DB.tables.include?(:posts)
4
+ Rubee::SequelObject::DB.create_table :posts do
5
+ primary_key :id
6
+ foreign_key :user_id, :users
7
+ foreign_key :comment_id, :comments
8
+ end
9
+
10
+ Post.create(user_id: User.all.first.id, comment_id: Comment.all.first.id)
11
+ Post.create(user_id: User.all.last.id, comment_id: Comment.all.last.id)
12
+ end
13
+ end
14
+ end
data/lib/db/structure.rb CHANGED
@@ -30,5 +30,97 @@ STRUCTURE = {
30
30
  ruby_default: nil,
31
31
  max_length: 255
32
32
  }
33
+ },
34
+ accounts: {
35
+ id: {
36
+ generated: false,
37
+ allow_null: false,
38
+ default: nil,
39
+ db_type: "INTEGER",
40
+ primary_key: true,
41
+ auto_increment: true,
42
+ type: "integer",
43
+ ruby_default: nil
44
+ },
45
+ addres: {
46
+ generated: false,
47
+ allow_null: true,
48
+ default: nil,
49
+ db_type: "varchar(255)",
50
+ primary_key: false,
51
+ type: "string",
52
+ ruby_default: nil,
53
+ max_length: 255
54
+ },
55
+ user_id: {
56
+ generated: false,
57
+ allow_null: true,
58
+ default: nil,
59
+ db_type: "INTEGER",
60
+ primary_key: false,
61
+ type: "integer",
62
+ ruby_default: nil
63
+ }
64
+ },
65
+ posts: {
66
+ id: {
67
+ generated: false,
68
+ allow_null: false,
69
+ default: nil,
70
+ db_type: "INTEGER",
71
+ primary_key: true,
72
+ auto_increment: true,
73
+ type: "integer",
74
+ ruby_default: nil
75
+ },
76
+ user_id: {
77
+ generated: false,
78
+ allow_null: true,
79
+ default: nil,
80
+ db_type: "INTEGER",
81
+ primary_key: false,
82
+ type: "integer",
83
+ ruby_default: nil
84
+ },
85
+ comment_id: {
86
+ generated: false,
87
+ allow_null: true,
88
+ default: nil,
89
+ db_type: "INTEGER",
90
+ primary_key: false,
91
+ type: "integer",
92
+ ruby_default: nil
93
+ }
94
+ },
95
+ comments: {
96
+ id: {
97
+ generated: false,
98
+ allow_null: false,
99
+ default: nil,
100
+ db_type: "INTEGER",
101
+ primary_key: true,
102
+ auto_increment: true,
103
+ type: "integer",
104
+ ruby_default: nil
105
+ },
106
+ text: {
107
+ generated: false,
108
+ allow_null: true,
109
+ default: nil,
110
+ db_type: "varchar(255)",
111
+ primary_key: false,
112
+ type: "string",
113
+ ruby_default: nil,
114
+ max_length: 255
115
+ },
116
+ user_id: {
117
+ generated: false,
118
+ allow_null: true,
119
+ default: nil,
120
+ db_type: "INTEGER",
121
+ primary_key: false,
122
+ type: "integer",
123
+ ruby_default: nil
124
+ }
33
125
  }
34
126
  }
@@ -1,5 +1,5 @@
1
1
  unless defined?(Rubee)
2
- require_relative '../../../../ee.rb'
2
+ require_relative '../../../../rubee.rb'
3
3
  Rubee::Autoload.call
4
4
  end
5
5
 
@@ -0,0 +1,52 @@
1
+ module Rubee
2
+ module DatabaseObjectable
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ base.include InstanceMethods
6
+ base.prepend Initializer
7
+
8
+ base.include Rubee::Hookable
9
+ base.include Rubee::Serializable
10
+ end
11
+
12
+ module ClassMethods
13
+ def pluralize_class_name
14
+ pluralize(self.name.downcase)
15
+ end
16
+
17
+ def pluralize(word)
18
+ if word.end_with?('y') && !%w[a e i o u].include?(word[-2])
19
+ word[0..-2] + 'ies' # Replace "y" with "ies"
20
+ elsif word.end_with?('s', 'x', 'z', 'ch', 'sh')
21
+ word + 'es' # Add "es" for certain endings
22
+ else
23
+ word + 's' # Default to adding "s"
24
+ end
25
+ end
26
+
27
+ def singularize(word)
28
+ if word.end_with?('ies') && word.length > 3
29
+ word[0..-4] + 'y' # Convert "ies" to "y"
30
+ elsif word.end_with?('es') && %w[s x z ch sh].any? { |ending| word[-(ending.length + 2)..-3] == ending }
31
+ word[0..-3] # Remove "es" for words like "foxes", "buses"
32
+ elsif word.end_with?('s') && word.length > 1
33
+ word[0..-2] # Remove "s" for regular plurals
34
+ else
35
+ word # Return as-is if no plural form is detected
36
+ end
37
+ end
38
+
39
+ def accessor_names
40
+ instance_methods(false)
41
+ .select { |m| method_defined?("#{m}=") } # Check if setter exists
42
+ end
43
+ end
44
+
45
+ module InstanceMethods
46
+ end
47
+
48
+ module Initializer
49
+ end
50
+ end
51
+ end
52
+
@@ -1,9 +1,21 @@
1
1
  module Rubee
2
- class SequelObject < DatabaseObject
3
- DB = Sequel.connect(Rubee::Configuration.get_database_url) rescue nil
4
-
5
- def destroy
6
- self.class.connection.where(id:).delete
2
+ class SequelObject
3
+ include Rubee::DatabaseObjectable
4
+
5
+ def destroy(cascade: false, **options)
6
+ if cascade
7
+ # find all tables with foreign key
8
+ tables_with_fk = DB.tables.select do |table|
9
+ DB.foreign_key_list(table).any? { |fk| fk[:table] == self.class.pluralize_class_name.to_sym }
10
+ end
11
+ # destroy related records
12
+ tables_with_fk.each do |table|
13
+ fk_name ||= "#{self.class.name.to_s.downcase}_id".to_sym
14
+ target_klass = Object.const_get(self.class.singularize(table.to_s).capitalize)
15
+ target_klass.where(fk_name => id).map(&:destroy)
16
+ end
17
+ end
18
+ self.class.dataset.where(id:).delete
7
19
  end
8
20
 
9
21
  def save
@@ -28,7 +40,7 @@ module Rubee
28
40
 
29
41
  def update(args = {})
30
42
  assign_attributes(args)
31
- found_hash = self.class.connection.where(id:)
43
+ found_hash = self.class.dataset.where(id:)
32
44
  return self.class.find(id) if found_hash&.update(**args)
33
45
 
34
46
  false
@@ -44,46 +56,122 @@ module Rubee
44
56
 
45
57
  class << self
46
58
  def last
47
- found_hash = connection.order(:id).last
59
+ found_hash = dataset.order(:id).last
60
+ return self.new(**found_hash) if found_hash
61
+
62
+ nil
63
+ end
64
+
65
+ def first
66
+ found_hash = dataset.order(:id).first
48
67
  return self.new(**found_hash) if found_hash
49
68
 
50
69
  nil
51
70
  end
52
71
 
72
+ # ## User
73
+ # owns_many :comments
74
+ # > user.comments
75
+ # > [<comment1>, <comment2>]
76
+ def owns_many(assoc, fk_name: nil, over: nil, **options)
77
+ singularized_assoc_name = singularize(assoc.to_s)
78
+ fk_name ||= "#{self.name.to_s.downcase}_id"
79
+
80
+ define_method(assoc) do
81
+ klass = Object.const_get(singularized_assoc_name.capitalize)
82
+ if over
83
+ sequel_dataset = klass
84
+ .join(over.to_sym, "#{singularized_assoc_name}_id".to_sym => :id)
85
+ .where(fk_name.to_sym => id)
86
+ self.class.serialize(sequel_dataset, klass)
87
+ else
88
+ klass.where(fk_name.to_sym => id)
89
+ end
90
+ end
91
+ end
92
+
93
+ # ## Comment
94
+ # owns_one :user
95
+ # > comment.user
96
+ # > <user>
97
+ def owns_one(assoc, options={})
98
+ Sequel::Model.one_to_one(assoc, **options)
99
+ fk_name ||= "#{self.name.to_s.downcase}_id"
100
+ define_method(assoc) do
101
+ Object.const_get(assoc.capitalize).where(fk_name.to_sym => id)&.first
102
+ end
103
+ end
104
+
105
+ # ## Account
106
+ # holds :user
107
+ # > account.user
108
+ # > <user>
109
+ def holds(assoc, fk_name: nil, **options)
110
+ fk_name ||= "#{assoc.to_s.downcase}_id"
111
+ define_method(assoc) do
112
+ target_klass = Object.const_get(assoc.capitalize)
113
+ target_klass.find(self.send(fk_name))
114
+ end
115
+ end
116
+
53
117
  def reconnect!
118
+ return if defined?(DB) && !DB.nil?
119
+
54
120
  const_set(:DB, Sequel.connect(Rubee::Configuration.get_database_url))
55
121
  end
56
122
 
57
- def connection
58
- @connection ||= DB[pluralize_class_name.to_sym]
123
+ def dataset
124
+ @dataset ||= DB[pluralize_class_name.to_sym]
125
+ rescue Exception => _
126
+ reconnect!
127
+ retry
59
128
  end
60
129
 
61
130
  def all
62
- connection.map do |record_hash|
131
+ dataset.map do |record_hash|
63
132
  self.new(**record_hash)
64
133
  end
65
134
  end
66
135
 
67
136
  def find(id)
68
- found_hash = connection.where(id:)&.first
137
+ found_hash = dataset.where(id:)&.first
69
138
  return self.new(**found_hash) if found_hash
70
139
 
71
140
  nil
72
141
  end
73
142
 
74
143
  def where(args)
75
- connection.where(**args).map do |record_hash|
144
+ dataset.where(**args).map do |record_hash|
145
+ self.new(**record_hash)
146
+ end
147
+ end
148
+
149
+ def order(*args)
150
+ dataset.order(*args).map do |record_hash|
76
151
  self.new(**record_hash)
77
152
  end
78
153
  end
79
154
 
155
+ def join(assoc, args)
156
+ dataset.join(assoc, **args)
157
+ end
158
+
80
159
  def create(attrs)
81
- out_id = connection.insert(**attrs)
160
+ out_id = dataset.insert(**attrs)
82
161
  self.new(**(attrs.merge(id: out_id)))
83
162
  end
84
163
 
85
- def destroy_all
86
- all.each(&:destroy)
164
+ def destroy_all(cascade: false)
165
+ all.each{ |record| record.destroy(cascade:) }
166
+ end
167
+
168
+ def serialize(suquel_dataset, klass = nil)
169
+ klass ||= self
170
+ suquel_dataset.map do |record_hash|
171
+ target_klass_fields = DB[pluralize(klass.name.downcase).to_sym].columns
172
+ klass_attributes = record_hash.filter{ target_klass_fields.include? _1 }
173
+ klass.new(**klass_attributes)
174
+ end
87
175
  end
88
176
  end
89
177
  end
data/lib/rubee.rb CHANGED
@@ -8,7 +8,7 @@ module Rubee
8
8
  APP_ROOT = File.expand_path(Dir.pwd) unless defined?(APP_ROOT)
9
9
  IMAGE_DIR = File.join(APP_ROOT, 'images') unless defined?(IMAGE_DIR)
10
10
  PROJECT_NAME = File.basename(APP_ROOT) unless defined?(PROJECT_NAME)
11
- VERSION = '1.1.32'
11
+ VERSION = '1.2.0'
12
12
 
13
13
  class Application
14
14
  include Singleton
@@ -123,6 +123,8 @@ module Rubee
123
123
  # autoload all rbs
124
124
  root_directory = File.dirname(__FILE__)
125
125
  priority_order_require(root_directory, black_list)
126
+ # ensure sequel object is connected
127
+ Rubee::SequelObject.reconnect!
126
128
 
127
129
  Dir.glob(File.join(APP_ROOT, '**', '*.rb')).sort.each do |file|
128
130
  base_name = File.basename(file)
@@ -149,6 +151,15 @@ module Rubee
149
151
  # app config and routes
150
152
  lib = PROJECT_NAME == 'rubee' ? 'lib/' : ''
151
153
  require_relative File.join(APP_ROOT, lib, "config/base_configuration") unless black_list.include?('base_configuration.rb')
154
+ # This is necessary prerequisitedb init step
155
+ unless defined?(Rubee::SequelObject::DB)
156
+ if PROJECT_NAME == 'rubee'
157
+ Rubee::Configuration.setup(env=:test) do |config|
158
+ config.database_url = { url: "sqlite://lib/tests/test.db", env: }
159
+ end
160
+ end
161
+ end
162
+
152
163
  require_relative File.join(APP_ROOT, lib, "config/routes") unless black_list.include?('routes.rb')
153
164
  # rubee extensions
154
165
  Dir[File.join(root_directory, "rubee/extensions/**", '*.rb')].each do |file|
@@ -163,7 +174,7 @@ module Rubee
163
174
  end
164
175
  require_relative File.join(root_directory, "rubee/controllers/base_controller") unless black_list.include?('base_controller.rb')
165
176
  # rubee models
166
- require_relative File.join(root_directory, "rubee/models/database_object") unless black_list.include?('database_object.rb')
177
+ require_relative File.join(root_directory, "rubee/models/database_objectable") unless black_list.include?('database_objectable.rb')
167
178
  require_relative File.join(root_directory, "rubee/models/sequel_object") unless black_list.include?('sequel_object.rb')
168
179
  end
169
180
  end
@@ -0,0 +1,19 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe 'Account model' do
4
+ describe 'holds :user' do
5
+ after do
6
+ Account.destroy_all cascade: true
7
+ end
8
+
9
+ describe 'when it holds user_id' do
10
+ it 'returns associated User record' do
11
+ user = User.new(email: "ok-test@test.com", password: "123")
12
+ user.save
13
+ account = Account.new(user_id: user.id, addres: "test")
14
+ account.save
15
+ _(account.user.id).must_equal user.id
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe 'Comment model' do
4
+ describe 'owns_many :users, over: :posts' do
5
+ before do
6
+ comment = Comment.new(text: "test")
7
+ comment.save
8
+ user = User.new(email: "ok-test@test.com", password: "123")
9
+ user.save
10
+ post = Post.new(user_id: user.id, comment_id: comment.id)
11
+ post.save
12
+ end
13
+
14
+ after do
15
+ Comment.destroy_all cascade: true
16
+ end
17
+
18
+ describe 'when there are associated comment records' do
19
+ it 'returns all records' do
20
+ _(Comment.where(text: "test").last.users.count).must_equal 1
21
+ _(Comment.where(text: "test").last.users.first.email).must_equal "ok-test@test.com"
22
+ end
23
+ end
24
+
25
+ describe 'sequel dataset query' do
26
+ it 'returns all records' do
27
+ result = Comment.dataset.join(:posts, comment_id: :id)
28
+ .where(comment_id: Comment.where(text: "test").last.id)
29
+ .then { |dataset| Comment.serialize(dataset) }
30
+
31
+ _(result.first.text).must_equal "test"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,4 @@
1
+ class Account < Rubee::SequelObject
2
+ attr_accessor :id, :addres, :user_id
3
+ holds :user
4
+ end
@@ -0,0 +1,4 @@
1
+ class Comment < Rubee::SequelObject
2
+ attr_accessor :id, :text, :user_id
3
+ owns_many :users, over: :posts
4
+ end
@@ -0,0 +1,5 @@
1
+ class Post < Rubee::SequelObject
2
+ attr_accessor :id, :user_id, :comment_id
3
+ holds :comment
4
+ holds :user
5
+ end
@@ -0,0 +1,4 @@
1
+ class User < Rubee::SequelObject
2
+ attr_accessor :id, :email, :password
3
+ owns_many :accounts, cascade: true
4
+ end
Binary file
@@ -7,7 +7,7 @@ require_relative '../../lib/rubee'
7
7
 
8
8
  Rubee::Autoload.call
9
9
  Rubee::Configuration.setup(env=:test) do |config|
10
- config.database_url = { url: "sqlite://test.db", env: }
10
+ config.database_url = { url: "sqlite://lib/tests/test.db", env: }
11
11
  end
12
12
  Rubee::SequelObject.reconnect!
13
13
 
@@ -3,7 +3,7 @@ require_relative 'test_helper'
3
3
  describe 'User model' do
4
4
  describe ".create" do
5
5
  after do
6
- User.destroy_all
6
+ User.destroy_all cascade: true
7
7
  end
8
8
 
9
9
  describe 'when data is valid' do
@@ -26,7 +26,7 @@ describe 'User model' do
26
26
 
27
27
  describe '.save' do
28
28
  after do
29
- User.destroy_all
29
+ User.destroy_all cascade: true
30
30
  end
31
31
 
32
32
  describe 'when data is valid' do
@@ -57,4 +57,174 @@ describe 'User model' do
57
57
  end
58
58
  end
59
59
  end
60
+
61
+ describe '.update' do
62
+ after do
63
+ User.destroy_all cascade: true
64
+ end
65
+
66
+ describe 'when data is valid' do
67
+ it 'persists to db' do
68
+ user = User.new(email: "ok-test@test.com", password: "123")
69
+ user.save
70
+ user.update(password: "1234")
71
+
72
+ _(user.reload.password).must_equal "1234"
73
+ end
74
+ end
75
+ end
76
+
77
+ describe '.destroy' do
78
+ after do
79
+ User.destroy_all cascade: true
80
+ end
81
+
82
+ describe 'when there is no related recrods' do
83
+ it 'delete the record' do
84
+ user = User.new(email: "ok-test@test.com", password: "123")
85
+ user.save
86
+ user.destroy
87
+
88
+ assert_nil user.reload
89
+ end
90
+ end
91
+
92
+ describe 'when there are related recrods' do
93
+ it 'does not delete the record' do
94
+ user = User.new(email: "ok-test@test.com", password: "123")
95
+ user.save
96
+ Account.new(user_id: user.id, addres: "test").save
97
+ user.destroy rescue nil
98
+
99
+ _(user.reload.id).must_equal user.id
100
+ end
101
+ end
102
+
103
+ describe 'when there are related recrods but passed cascade=true' do
104
+ it 'deletes the record' do
105
+ user = User.new(email: "ok-test@test.com", password: "123")
106
+ user.save
107
+ Account.new(user_id: user.id, addres: "test").save
108
+ user.destroy cascade: true
109
+
110
+ assert_nil user.reload
111
+ end
112
+ end
113
+ end
114
+
115
+ describe '.find' do
116
+ after do
117
+ User.destroy_all cascade: true
118
+ end
119
+
120
+ describe 'when trhere is a record' do
121
+ it 'returns a record' do
122
+ user = User.new(email: "ok-test@test.com", password: "123")
123
+ user.save
124
+ _(User.find(user.id).email).must_equal user.email
125
+ end
126
+ end
127
+
128
+ describe 'when there is no record' do
129
+ it 'returns nil' do
130
+ assert_nil User.find(1)
131
+ end
132
+ end
133
+ end
134
+
135
+ describe '.all' do
136
+ after do
137
+ User.destroy_all cascade: true
138
+ end
139
+
140
+ describe 'when there are records' do
141
+ it 'returns all records' do
142
+ user = User.new(email: "ok-test@test.com", password: "123")
143
+ user2 = User.new(email: "ok-test2@test.com", password: "123")
144
+ user.save
145
+ user2.save
146
+ _(User.all.count).must_equal 2
147
+ end
148
+ end
149
+ end
150
+
151
+ describe '.where' do
152
+ after do
153
+ User.destroy_all cascade: true
154
+ end
155
+
156
+ describe 'when there are records' do
157
+ it 'returns all records' do
158
+ user = User.new(email: "ok-test@test.com", password: "123")
159
+ user2 = User.new(email: "ok-test2@test.com", password: "123")
160
+ user.save
161
+ user2.save
162
+ _(User.where(email: "ok-test2@test.com").count).must_equal 1
163
+ end
164
+ end
165
+ end
166
+
167
+ describe '.first' do
168
+ after do
169
+ User.destroy_all cascade: true
170
+ end
171
+
172
+ describe 'when there are records' do
173
+ it 'returns first record' do
174
+ user = User.new(email: "ok-test@test.com", password: "123")
175
+ user2 = User.new(email: "ok-test2@test.com", password: "123")
176
+ user.save
177
+ user2.save
178
+ _(User.first.email).must_equal user.email
179
+ end
180
+ end
181
+ end
182
+
183
+ describe '.last' do
184
+ after do
185
+ User.destroy_all cascade: true
186
+ end
187
+
188
+ describe 'when there are records' do
189
+ it 'returns last record' do
190
+ user = User.new(email: "ok-test@test.com", password: "123")
191
+ user2 = User.new(email: "ok-test2@test.com", password: "123")
192
+ user.save
193
+ user2.save
194
+ _(User.last.email).must_equal user2.email
195
+ end
196
+ end
197
+ end
198
+
199
+ describe '.order' do
200
+ after do
201
+ User.destroy_all cascade: true
202
+ end
203
+
204
+ describe 'when there are records' do
205
+ it 'returns ordered records' do
206
+ user = User.new(email: "abc@test.com", password: "123")
207
+ user2 = User.new(email: "defg@test.com", password: "123")
208
+ user.save
209
+ user2.save
210
+ _(User.order(:email).first.email).must_equal user.email
211
+ end
212
+ end
213
+ end
214
+
215
+ describe 'owns_many' do
216
+ after do
217
+ User.destroy_all cascade: true
218
+ end
219
+
220
+ describe 'when there are associated account records' do
221
+ it 'returns all records' do
222
+ user = User.new(email: "ok-test@test.com", password: "123")
223
+ user.save
224
+ account = Account.new(user_id: user.id, addres: "test")
225
+ account.save
226
+ _(user.accounts.count).must_equal 1
227
+ end
228
+ end
229
+ end
60
230
  end
data/readme.md CHANGED
@@ -107,7 +107,7 @@ Here below is a simple example on how it can be used by rendering json from in m
107
107
 
108
108
  def show
109
109
  # in memory example
110
- apples = [Apple.new(colour: 'red', weight: '1lb'), Apple.new(colour: 'green', weight: '1lb')]
110
+ apples = [Apple.new(colour: 'red', weight: '1lb'), Apple.new(colour: 'green', weight: '1lb')]
111
111
  apple = apples.find { |apple| apple.colour = params[:colour] }
112
112
 
113
113
  response_with object: apple, type: :json
@@ -128,6 +128,24 @@ However, you can simply turn it to ORM object by extending database class.
128
128
  attr_accessor :id, :colour, :weight
129
129
  end
130
130
  ```
131
+ Rubee::SequelObject methods:
132
+
133
+ - `apple.save`
134
+ - `apple.destroy(cascade: true)` # default false
135
+ - `apple.destroy_all`
136
+ - `apple.update(colour: 'red')`
137
+ - `apple.persisted?`
138
+ - `apple.reload`
139
+ - `apple.assign_attributes(colour: 'red', weight: '1lb')`
140
+ - `Apple.last`
141
+ - `Apple.where(colour: 'red')`
142
+ - `Apple.last`
143
+ - `Apple.all`
144
+ - `Apple.create(colour: 'red', weight: '1lb')`
145
+ - `Apple.destroy_all`
146
+ - `Apple.serialize`
147
+ - `Apple.serialize(Apple.dataset.joins(:trees).where(tree: { colour: 'brown' }))`
148
+ ...
131
149
 
132
150
  So in the controller you would need to query your target object now.
133
151
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ru.Bee
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.32
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oleg Saltykov
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-22 00:00:00.000000000 Z
10
+ date: 2025-03-31 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: bundler
@@ -47,9 +47,11 @@ files:
47
47
  - lib/config.ru
48
48
  - lib/config/base_configuration.rb
49
49
  - lib/config/routes.rb
50
+ - lib/db/create_accounts.rb
51
+ - lib/db/create_comments.rb
52
+ - lib/db/create_posts.rb
50
53
  - lib/db/create_users.rb
51
54
  - lib/db/structure.rb
52
- - lib/db/test.db
53
55
  - lib/images/rubee.svg
54
56
  - lib/inits/print_colors.rb
55
57
  - lib/rubee.rb
@@ -63,10 +65,17 @@ files:
63
65
  - lib/rubee/controllers/middlewares/auth_token_middleware.rb
64
66
  - lib/rubee/extensions/hookable.rb
65
67
  - lib/rubee/extensions/serializable.rb
66
- - lib/rubee/models/database_object.rb
68
+ - lib/rubee/models/database_objectable.rb
67
69
  - lib/rubee/models/sequel_object.rb
70
+ - lib/tests/account_model_test.rb
68
71
  - lib/tests/auth_tokenable_test.rb
72
+ - lib/tests/comment_model_test.rb
73
+ - lib/tests/example_models/account.rb
74
+ - lib/tests/example_models/comment.rb
75
+ - lib/tests/example_models/post.rb
76
+ - lib/tests/example_models/user.rb
69
77
  - lib/tests/rubeeapp_test.rb
78
+ - lib/tests/test.db
70
79
  - lib/tests/test_helper.rb
71
80
  - lib/tests/user_model_test.rb
72
81
  - readme.md
@@ -1,50 +0,0 @@
1
- module Rubee
2
- class DatabaseObject
3
- include Serializable
4
- include Hookable
5
-
6
- def destroy
7
- end
8
-
9
- def save
10
- end
11
-
12
- def update(args = {})
13
- end
14
-
15
- def reload
16
- end
17
-
18
- class << self
19
- def last
20
- end
21
-
22
- def connection
23
- end
24
-
25
- def all
26
- end
27
-
28
- def find(id)
29
- end
30
-
31
- def where(args)
32
- end
33
-
34
- def create(attrs)
35
- end
36
-
37
- def pluralize_class_name
38
- word = self.name.downcase
39
- # Basic pluralization rules
40
- if word.end_with?('y') && !%w[a e i o u].include?(word[-2])
41
- word[0..-2] + 'ies' # Replace "y" with "ies"
42
- elsif word.end_with?('s', 'x', 'z', 'ch', 'sh')
43
- word + 'es' # Add "es" for certain endings
44
- else
45
- word + 's' # Default to adding "s"
46
- end
47
- end
48
- end
49
- end
50
- end