ru.Bee 1.5.4 → 1.6.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 +4 -4
- data/bin/rubee +7 -2
- data/lib/config/base_configuration.rb +25 -7
- data/lib/db/create_addresses.rb +17 -0
- data/lib/package.json +1 -1
- data/lib/rubee/async/fiber_queue.rb +27 -0
- data/lib/rubee/async/thread_pool.rb +32 -34
- data/lib/rubee/autoload.rb +73 -0
- data/lib/rubee/configuration.rb +60 -0
- data/lib/rubee/extensions/hookable.rb +9 -2
- data/lib/rubee/generator.rb +152 -0
- data/lib/rubee/logger.rb +83 -0
- data/lib/rubee/models/sequel_object.rb +1 -2
- data/lib/rubee/router.rb +41 -0
- data/lib/rubee.rb +7 -314
- data/lib/tests/async/thread_async_test.rb +9 -5
- data/lib/tests/{auth_tokenable_test.rb → controllers/auth_tokenable_test.rb} +2 -2
- data/lib/tests/controllers/base_controller_test.rb +23 -0
- data/lib/tests/controllers/hookable_test.rb +220 -0
- data/lib/tests/{rubeeapp_test.rb → controllers/rubeeapp_test.rb} +2 -1
- data/lib/tests/example_models/address.rb +5 -0
- data/lib/tests/example_models/user.rb +1 -0
- data/lib/tests/logger_test.rb +76 -0
- data/lib/tests/{account_model_test.rb → models/account_model_test.rb} +1 -1
- data/lib/tests/{comment_model_test.rb → models/comment_model_test.rb} +13 -1
- data/lib/tests/models/db_objectable_test.rb +21 -0
- data/lib/tests/models/seralizable_test.rb +36 -0
- data/lib/tests/{user_model_test.rb → models/user_model_test.rb} +32 -1
- data/lib/tests/test.db +0 -0
- data/lib/tests/test_helper.rb +19 -2
- data/readme.md +77 -11
- metadata +19 -8
- data/lib/app/views/apples_.erb +0 -1
- data/lib/app/views/s_.erb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 400c70fb533f9935fb838941de26bd78875f64a62e1d86bed2a817904ca63a7d
|
4
|
+
data.tar.gz: 23fe0b3b9334a0c34b5fb671806a58dfa0e7f2aeb48f487fe988eec2354bcdc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2d8526cbce129652658679cc1edf861e33f8479b2c8e9e3849c640fc527dd6116dfe314fc7f1fa79f8d188655a1463320a701dc46f13166b870733ef1d3bc35
|
7
|
+
data.tar.gz: 386b45c69e6513448adf1ab10f6b9caf4cfc15d588b26f920dc6518489cbf6c9abc5f6404b007d65b6e9aaf71cb806cac391b3023156113e8f3e5958f3430868
|
data/bin/rubee
CHANGED
@@ -89,7 +89,7 @@ elsif command == 'project'
|
|
89
89
|
# Define blacklist
|
90
90
|
blacklist_files = %w[rubee.rb print_colors.rb version.rb config.ru test_helper.rb Gemfile.lock test.yml test.db
|
91
91
|
development.db production.db]
|
92
|
-
blacklist_dirs = %w[rubee tests .git .github .idea node_modules db]
|
92
|
+
blacklist_dirs = %w[rubee tests .git .github .idea node_modules db inits]
|
93
93
|
|
94
94
|
# Copy files, excluding blacklisted ones
|
95
95
|
Dir.glob("#{source_dir}/**/*", File::FNM_DOTMATCH).each do |file|
|
@@ -112,13 +112,18 @@ elsif command == 'project'
|
|
112
112
|
|
113
113
|
# create tests dir and copy test_helper.rb and user_model_test.rb
|
114
114
|
FileUtils.mkdir_p("#{target_dir}/tests")
|
115
|
-
FileUtils.
|
115
|
+
FileUtils.mkdir_p("#{target_dir}/tests/models")
|
116
|
+
FileUtils.mkdir_p("#{target_dir}/tests/controllers")
|
117
|
+
FileUtils.cp("#{source_dir}/tests/models/user_model_test.rb", "#{target_dir}/tests/models/user_model_test.rb")
|
116
118
|
|
117
119
|
# create db dir
|
118
120
|
FileUtils.mkdir_p("#{target_dir}/db")
|
119
121
|
FileUtils.cp("#{source_dir}/db/structure.rb", "#{target_dir}/db/structure.rb")
|
120
122
|
FileUtils.cp("#{source_dir}/db/create_users.rb", "#{target_dir}/db/create_users.rb")
|
121
123
|
|
124
|
+
# create inits dir
|
125
|
+
FileUtils.mkdir_p("#{target_dir}/inits")
|
126
|
+
|
122
127
|
# create a gemfile context
|
123
128
|
gemfile = <<~GEMFILE
|
124
129
|
source 'https://rubygems.org'
|
@@ -1,23 +1,41 @@
|
|
1
1
|
Rubee::Configuration.setup(env = :development) do |config|
|
2
2
|
config.database_url = { url: 'sqlite://db/development.db', env: }
|
3
|
-
config.thread_pool_limit = { env:, value: 5 }
|
4
3
|
|
5
|
-
|
6
|
-
# config.
|
4
|
+
## configure hybrid thread pooling params
|
5
|
+
# config.threads_limit = { env:, value: 4 }
|
6
|
+
# config.fibers_limit = { env:, value: 4 }
|
7
|
+
|
8
|
+
# Flag on react as a view
|
9
|
+
# config.react = { on: true, env: } # required if you want to use react
|
10
|
+
|
11
|
+
## configure logger
|
12
|
+
# config.logger = { logger: MyLogger, env: }
|
7
13
|
end
|
8
14
|
|
9
15
|
Rubee::Configuration.setup(env = :test) do |config|
|
10
16
|
config.database_url = { url: 'sqlite://db/test.db', env: }
|
11
|
-
config.thread_pool_limit = { env:, value: 5 }
|
12
17
|
|
13
|
-
|
18
|
+
## configure hybrid thread pooling params
|
19
|
+
# config.threads_limit = { env:, value: 4 }
|
20
|
+
# config.fibers_limit = { env:, value: 4 }
|
21
|
+
|
22
|
+
## Flag on react as a view
|
14
23
|
# config.react = { on: true, env: } # required if you want to use react
|
24
|
+
|
25
|
+
## configure logger
|
26
|
+
# config.logger = { logger: MyLogger, env: }
|
15
27
|
end
|
16
28
|
|
17
29
|
Rubee::Configuration.setup(env = :production) do |config|
|
18
30
|
config.database_url = { url: 'sqlite://db/production.db', env: }
|
19
|
-
config.thread_pool_limit = { env:, value: 5 }
|
20
31
|
|
21
|
-
|
32
|
+
## configure hybrid thread pooling params
|
33
|
+
# config.threads_limit = { env:, value: 4 }
|
34
|
+
# config.fibers_limit = { env:, value: 4 }
|
35
|
+
|
36
|
+
## Flag on react as a view
|
22
37
|
# config.react = { on: true, env: } # required if you want to use react
|
38
|
+
|
39
|
+
## configure logger
|
40
|
+
# config.logger = { logger: MyLogger, env: }
|
23
41
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class CreateAddresses
|
2
|
+
def call
|
3
|
+
return if Rubee::SequelObject::DB.tables.include?(:addresses)
|
4
|
+
|
5
|
+
Rubee::SequelObject::DB.create_table(:addresses) do
|
6
|
+
primary_key(:id)
|
7
|
+
String(:city)
|
8
|
+
String(:state)
|
9
|
+
String(:zip)
|
10
|
+
String(:street)
|
11
|
+
String(:apt)
|
12
|
+
foreign_key(:user_id, :users)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Address.create(street: '13th Ave', city: 'NY', state: 'NY', zip: '55555', user_id: User.all.first.id)
|
16
|
+
end
|
17
|
+
end
|
data/lib/package.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"scripts": {
|
3
3
|
"build": "node esbuild.config.js",
|
4
4
|
"watch": "node esbuild.config.js --watch",
|
5
|
-
"prepare": "npm install react react-dom react-router-dom esbuild-plugin-inline-css"
|
5
|
+
"prepare": "npm install esbuild react react-dom react-router-dom esbuild-plugin-inline-css"
|
6
6
|
},
|
7
7
|
"dependencies": {
|
8
8
|
"react": "^18.3.1",
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class FiberQueue
|
2
|
+
def initialize
|
3
|
+
@fibers = []
|
4
|
+
end
|
5
|
+
|
6
|
+
def add(task, args = {})
|
7
|
+
fiber = Fiber.new do
|
8
|
+
task.new.perform(**args)
|
9
|
+
rescue => e
|
10
|
+
puts "Fiber Error: #{e.message}"
|
11
|
+
end
|
12
|
+
@fibers << fiber
|
13
|
+
end
|
14
|
+
|
15
|
+
def fan_out!
|
16
|
+
while @fibers.any?(&:alive?)
|
17
|
+
@fibers.each do |fiber|
|
18
|
+
fiber.resume if fiber.alive?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def done?
|
24
|
+
@fibers.none?(&:alive?)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -3,58 +3,56 @@ require 'singleton'
|
|
3
3
|
module Rubee
|
4
4
|
class ThreadPool
|
5
5
|
include Singleton
|
6
|
-
|
6
|
+
THREADS_LIMIT = Rubee::Configuration.get_threads_limit || 4
|
7
|
+
FIBERS_LIMIT = Rubee::Configuration.get_fibers_limit || 4
|
7
8
|
|
8
9
|
def initialize
|
9
|
-
@
|
10
|
-
@
|
10
|
+
@tasks = Queue.new
|
11
|
+
@threads = []
|
11
12
|
@running = true
|
12
|
-
|
13
|
-
end
|
13
|
+
@mutex = Mutex.new
|
14
14
|
|
15
|
-
|
16
|
-
@queue << { task: task, args: args }
|
17
|
-
run_next
|
15
|
+
spawn_workers
|
18
16
|
end
|
19
17
|
|
20
|
-
def
|
21
|
-
@
|
22
|
-
run_next
|
18
|
+
def enqueue(task, args = {})
|
19
|
+
@tasks << [task, args]
|
23
20
|
end
|
24
21
|
|
25
22
|
def shutdown
|
26
23
|
@running = false
|
27
|
-
@
|
24
|
+
THREADS_LIMIT.times { @tasks << :shutdown } # Unblock threads
|
25
|
+
@threads.each(&:join)
|
28
26
|
end
|
29
27
|
|
30
28
|
private
|
31
29
|
|
32
|
-
def run_next
|
33
|
-
@workers.each do |fiber|
|
34
|
-
fiber.resume if fiber.alive? && !@queue.empty?
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
30
|
def spawn_workers
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
31
|
+
THREADS_LIMIT.times do
|
32
|
+
@threads << Thread.new do
|
33
|
+
while @running && (task = @tasks.pop)
|
34
|
+
break if task == :shutdown
|
35
|
+
|
36
|
+
fiber_queue = FiberQueue.new
|
37
|
+
fiber_queue.add(*task)
|
38
|
+
|
39
|
+
# pull more to fill the chunk
|
40
|
+
FIBERS_LIMIT.times do
|
41
|
+
next_task = begin
|
42
|
+
@mutex.synchronize { @tasks.pop(true) }
|
43
|
+
rescue
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
fiber_queue.add(*next_task) if next_task
|
47
|
+
end
|
48
|
+
|
49
|
+
until fiber_queue.done?
|
50
|
+
fiber_queue.fan_out!
|
53
51
|
end
|
52
|
+
|
53
|
+
sleep(0.05)
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
57
|
-
@workers << fiber
|
58
56
|
end
|
59
57
|
end
|
60
58
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Rubee
|
2
|
+
class Autoload
|
3
|
+
class << self
|
4
|
+
def call(black_list = [])
|
5
|
+
# autoload all rbs
|
6
|
+
root_directory = File.expand_path(File.join(__dir__, '..',))
|
7
|
+
priority_order_require(root_directory, black_list)
|
8
|
+
# ensure sequel object is connected
|
9
|
+
Rubee::SequelObject.reconnect!
|
10
|
+
|
11
|
+
Dir.glob(File.join(APP_ROOT, '**', '*.rb')).sort.each do |file|
|
12
|
+
base_name = File.basename(file)
|
13
|
+
|
14
|
+
unless base_name.end_with?('_test.rb') || (black_list + ['rubee.rb', 'test_helper.rb']).include?(base_name)
|
15
|
+
require_relative file
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def priority_order_require(root_directory, black_list)
|
21
|
+
# rubee inits
|
22
|
+
Dir[File.join(root_directory, 'inits/**', '*.rb')].each do |file|
|
23
|
+
require_relative file unless black_list.include?("#{file}.rb")
|
24
|
+
end
|
25
|
+
# app inits
|
26
|
+
Dir[File.join(APP_ROOT, 'inits/**', '*.rb')].each do |file|
|
27
|
+
require_relative file unless black_list.include?("#{file}.rb")
|
28
|
+
end
|
29
|
+
# rubee async
|
30
|
+
Dir[File.join(root_directory, 'rubee/async/**', '*.rb')].each do |file|
|
31
|
+
require_relative file unless black_list.include?("#{file}.rb")
|
32
|
+
end
|
33
|
+
# app config and routes
|
34
|
+
unless black_list.include?('base_configuration.rb')
|
35
|
+
require_relative File.join(APP_ROOT, LIB,
|
36
|
+
'config/base_configuration')
|
37
|
+
end
|
38
|
+
# This is necessary prerequisitedb init step
|
39
|
+
if !defined?(Rubee::SequelObject::DB) && (PROJECT_NAME == 'rubee')
|
40
|
+
Rubee::Configuration.setup(env = :test) do |config|
|
41
|
+
config.database_url = { url: 'sqlite://lib/tests/test.db', env: }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
require_relative File.join(APP_ROOT, LIB, 'config/routes') unless black_list.include?('routes.rb')
|
46
|
+
# rubee extensions
|
47
|
+
Dir[File.join(root_directory, 'rubee/extensions/**', '*.rb')].each do |file|
|
48
|
+
require_relative file unless black_list.include?("#{file}.rb")
|
49
|
+
end
|
50
|
+
# rubee controllers
|
51
|
+
Dir[File.join(root_directory, 'rubee/controllers/middlewares/**', '*.rb')].each do |file|
|
52
|
+
require_relative file unless black_list.include?("#{file}.rb")
|
53
|
+
end
|
54
|
+
Dir[File.join(root_directory, 'rubee/controllers/extensions/**', '*.rb')].each do |file|
|
55
|
+
require_relative file unless black_list.include?("#{file}.rb")
|
56
|
+
end
|
57
|
+
unless black_list.include?('base_controller.rb')
|
58
|
+
require_relative File.join(root_directory,
|
59
|
+
'rubee/controllers/base_controller')
|
60
|
+
end
|
61
|
+
# rubee models
|
62
|
+
unless black_list.include?('database_objectable.rb')
|
63
|
+
require_relative File.join(root_directory,
|
64
|
+
'rubee/models/database_objectable')
|
65
|
+
end
|
66
|
+
return if black_list.include?('sequel_object.rb')
|
67
|
+
|
68
|
+
require_relative File.join(root_directory,
|
69
|
+
'rubee/models/sequel_object')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Rubee
|
2
|
+
class Configuration
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
@configuraiton = {
|
6
|
+
development: {
|
7
|
+
database_url: '',
|
8
|
+
port: 7000,
|
9
|
+
},
|
10
|
+
production: {},
|
11
|
+
test: {},
|
12
|
+
}
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def setup(_env)
|
16
|
+
yield(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def database_url=(args)
|
20
|
+
@configuraiton[args[:env].to_sym][:database_url] = args[:url]
|
21
|
+
end
|
22
|
+
|
23
|
+
def async_adapter=(args)
|
24
|
+
@configuraiton[args[:env].to_sym][:async_adapter] = args[:async_adapter]
|
25
|
+
end
|
26
|
+
|
27
|
+
def threads_limit=(args)
|
28
|
+
@configuraiton[args[:env].to_sym][:thread_pool_limit] = args[:value]
|
29
|
+
end
|
30
|
+
|
31
|
+
def fibers_limit=(args)
|
32
|
+
@configuraiton[args[:env].to_sym][:fiber_pool_limit] = args[:value]
|
33
|
+
end
|
34
|
+
|
35
|
+
def logger=(args)
|
36
|
+
@configuraiton[args[:env].to_sym][:logger] = args[:logger]
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def react=(args)
|
41
|
+
@configuraiton[args[:env].to_sym][:react] ||= { on: false }
|
42
|
+
@configuraiton[args[:env].to_sym][:react].merge!(on: args[:on])
|
43
|
+
end
|
44
|
+
|
45
|
+
def react
|
46
|
+
@configuraiton[ENV['RACK_ENV']&.to_sym || :development][:react] || {}
|
47
|
+
end
|
48
|
+
|
49
|
+
def method_missing(method_name, *_args)
|
50
|
+
return unless method_name.to_s.start_with?('get_')
|
51
|
+
|
52
|
+
@configuraiton[ENV['RACK_ENV']&.to_sym || :development]&.[](method_name.to_s.delete_prefix('get_').to_sym)
|
53
|
+
end
|
54
|
+
|
55
|
+
def envs
|
56
|
+
@configuraiton.keys
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -39,9 +39,16 @@ module Rubee
|
|
39
39
|
define_method(method) do |*args, &block|
|
40
40
|
if conditions_met?(options[:if], options[:unless])
|
41
41
|
if handler.respond_to?(:call)
|
42
|
-
|
42
|
+
result = nil
|
43
|
+
handler.call do
|
44
|
+
result = super(*args, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
result
|
43
48
|
else
|
44
|
-
send(handler)
|
49
|
+
return send(handler) do
|
50
|
+
super(*args, &block)
|
51
|
+
end
|
45
52
|
end
|
46
53
|
else
|
47
54
|
super(*args, &block)
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module Rubee
|
2
|
+
class Generator
|
3
|
+
require_relative '../inits/charged_string'
|
4
|
+
using ChargedString
|
5
|
+
def initialize(model_name, model_attributes, controller_name, action_name, **options)
|
6
|
+
@model_name = model_name&.downcase
|
7
|
+
@model_attributes = model_attributes || []
|
8
|
+
@base_name = controller_name.to_s.gsub('Controller', '').downcase.to_s
|
9
|
+
color_puts("base_name: #{@base_name}", color: :gray)
|
10
|
+
@plural_name = @base_name.plural? ? @base_name : @base_name.pluralize
|
11
|
+
@action_name = action_name
|
12
|
+
@react = options[:react] || {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
generate_model if @model_name
|
17
|
+
generate_db_file if @model_name
|
18
|
+
generate_controller if @base_name && @action_name
|
19
|
+
generate_view if @base_name
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def generate_model
|
25
|
+
model_file = File.join(Rubee::APP_ROOT, Rubee::LIB, "app/models/#{@model_name}.rb")
|
26
|
+
if File.exist?(model_file)
|
27
|
+
puts "Model #{@model_name} already exists. Remove it if you want to regenerate"
|
28
|
+
return
|
29
|
+
end
|
30
|
+
|
31
|
+
content = <<~RUBY
|
32
|
+
class #{@model_name.capitalize} < Rubee::SequelObject
|
33
|
+
#{'attr_accessor ' + @model_attributes.map { |hash| ":#{hash[:name]}" }.join(', ') unless @model_attributes.empty?}
|
34
|
+
end
|
35
|
+
RUBY
|
36
|
+
|
37
|
+
File.open(model_file, 'w') { |file| file.write(content) }
|
38
|
+
color_puts("Model #{@model_name} created", color: :green)
|
39
|
+
end
|
40
|
+
|
41
|
+
def generate_controller
|
42
|
+
controller_file = File.join(Rubee::APP_ROOT, Rubee::LIB, "app/controllers/#{@base_name}_controller.rb")
|
43
|
+
if File.exist?(controller_file)
|
44
|
+
puts "Controller #{@base_name} already exists. Remove it if you want to regenerate"
|
45
|
+
return
|
46
|
+
end
|
47
|
+
|
48
|
+
content = <<~RUBY
|
49
|
+
class #{@base_name.capitalize}Controller < Rubee::BaseController
|
50
|
+
def #{@action_name}
|
51
|
+
response_with
|
52
|
+
end
|
53
|
+
end
|
54
|
+
RUBY
|
55
|
+
|
56
|
+
File.open(controller_file, 'w') { |file| file.write(content) }
|
57
|
+
color_puts("Controller #{@base_name} created", color: :green)
|
58
|
+
end
|
59
|
+
|
60
|
+
def generate_view
|
61
|
+
if @react[:view_name]
|
62
|
+
view_file = File.join(Rubee::APP_ROOT, Rubee::LIB, "app/views/#{@react[:view_name]}")
|
63
|
+
content = <<~JS
|
64
|
+
import React, { useEffect, useState } from "react";
|
65
|
+
// 1. Add your logic that fetches data
|
66
|
+
// 2. Do not forget to add respective react route
|
67
|
+
export function #{@react[:view_name].gsub(/\.(.*)+$/, '').capitalize}() {
|
68
|
+
|
69
|
+
return (
|
70
|
+
<div>
|
71
|
+
<h2>#{@react[:view_name]} view</h2>
|
72
|
+
</div>
|
73
|
+
);
|
74
|
+
}
|
75
|
+
JS
|
76
|
+
else
|
77
|
+
view_file = File.join(Rubee::APP_ROOT, Rubee::LIB, "app/views/#{@plural_name}_#{@action_name}.erb")
|
78
|
+
content = <<~ERB
|
79
|
+
<h1>#{@plural_name}_#{@action_name} View</h1>
|
80
|
+
ERB
|
81
|
+
end
|
82
|
+
|
83
|
+
name = @react[:view_name] || "#{@plural_name}_#{@action_name}"
|
84
|
+
|
85
|
+
if File.exist?(view_file)
|
86
|
+
puts "View #{name} already exists. Remove it if you want to regenerate"
|
87
|
+
return
|
88
|
+
end
|
89
|
+
|
90
|
+
File.open(view_file, 'w') { |file| file.write(content) }
|
91
|
+
color_puts("View #{name} created", color: :green)
|
92
|
+
end
|
93
|
+
|
94
|
+
def generate_db_file
|
95
|
+
db_file = File.join(Rubee::APP_ROOT, Rubee::LIB, "db/create_#{@plural_name}.rb")
|
96
|
+
if File.exist?(db_file)
|
97
|
+
puts "DB file for #{@plural_name} already exists. Remove it if you want to regenerate"
|
98
|
+
return
|
99
|
+
end
|
100
|
+
|
101
|
+
content = <<~RUBY
|
102
|
+
class Create#{@plural_name.capitalize}
|
103
|
+
def call
|
104
|
+
return if Rubee::SequelObject::DB.tables.include?(:#{@plural_name})
|
105
|
+
|
106
|
+
Rubee::SequelObject::DB.create_table(:#{@plural_name}) do
|
107
|
+
#{@model_attributes.map { |attribute| generate_sequel_schema(attribute) }.join("\n\t\t\t")}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
RUBY
|
112
|
+
|
113
|
+
File.open(db_file, 'w') { |file| file.write(content) }
|
114
|
+
color_puts("DB file for #{@plural_name} created", color: :green)
|
115
|
+
end
|
116
|
+
|
117
|
+
def generate_sequel_schema(attribute)
|
118
|
+
type = attribute[:type]
|
119
|
+
name = if attribute[:name].is_a?(Array)
|
120
|
+
attribute[:name].map { |nom| ":#{nom}" }.join(", ").prepend('[') + ']'
|
121
|
+
else
|
122
|
+
":#{attribute[:name]}"
|
123
|
+
end
|
124
|
+
table = attribute[:table] || 'replace_with_table_name'
|
125
|
+
options = attribute[:options] || {}
|
126
|
+
|
127
|
+
lookup_hash = {
|
128
|
+
primary: "primary_key #{name}",
|
129
|
+
string: "String #{name}",
|
130
|
+
text: "String #{name}, text: true",
|
131
|
+
integer: "Integer #{name}",
|
132
|
+
date: "Date #{name}",
|
133
|
+
datetime: "DateTime #{name}",
|
134
|
+
time: "Time #{name}",
|
135
|
+
boolean: "TrueClass #{name}",
|
136
|
+
bigint: "Bignum #{name}",
|
137
|
+
decimal: "BigDecimal #{name}",
|
138
|
+
foreign_key: "foreign_key #{name}, :#{table}",
|
139
|
+
index: "index #{name}",
|
140
|
+
unique: "unique #",
|
141
|
+
}
|
142
|
+
|
143
|
+
statement = lookup_hash[type.to_sym]
|
144
|
+
|
145
|
+
options.keys.each do |key|
|
146
|
+
statement += ", #{key}: '#{options[key]}'"
|
147
|
+
end
|
148
|
+
|
149
|
+
statement
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
data/lib/rubee/logger.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
module Rubee
|
2
|
+
class Logger
|
3
|
+
class << self
|
4
|
+
def warn(message:, **options, &block)
|
5
|
+
out.warn(message:, **options, &block)
|
6
|
+
end
|
7
|
+
|
8
|
+
def error(message:, **options, &block)
|
9
|
+
out.error(message:, **options, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def critical(message:, **options, &block)
|
13
|
+
out.critical(message:, **options, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def info(message:, **options, &block)
|
17
|
+
out.info(message:, **options, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def debug(object:, **options, &block)
|
21
|
+
out.debug(object:, **options, &block)
|
22
|
+
end
|
23
|
+
|
24
|
+
def out
|
25
|
+
Rubee::Configuration.get_logger || Stdout
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Stdout
|
31
|
+
class << self
|
32
|
+
def warn(message:, **options, &block)
|
33
|
+
log(:warn, message, options, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def error(message:, **options, &block)
|
37
|
+
log(:error, message, options, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def critical(message:, **options, &block)
|
41
|
+
log(:critical, message, options, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
def info(message:, **options, &block)
|
45
|
+
log(:info, message, options, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
def debug(object:, **options, &block)
|
49
|
+
log(:debug, object.inspect, options, &block)
|
50
|
+
end
|
51
|
+
|
52
|
+
def print_error(message)
|
53
|
+
color_puts(message, color: :red)
|
54
|
+
end
|
55
|
+
|
56
|
+
def print_info(message)
|
57
|
+
color_puts(message, color: :gray)
|
58
|
+
end
|
59
|
+
|
60
|
+
def print_warn(message)
|
61
|
+
color_puts(message, color: :yellow)
|
62
|
+
end
|
63
|
+
|
64
|
+
def print_debug(message)
|
65
|
+
color_puts(message)
|
66
|
+
end
|
67
|
+
|
68
|
+
def print_critical(message)
|
69
|
+
color_puts(message, color: :red, style: :blink)
|
70
|
+
end
|
71
|
+
|
72
|
+
def log(severity, message, options = {}, &block)
|
73
|
+
time = Time.now.strftime('%Y-%m-%d %H:%M:%S')
|
74
|
+
if options.any?
|
75
|
+
message = options.map { |k, v| "[#{k}: #{v}]" }.join << " #{message}"
|
76
|
+
end
|
77
|
+
send("print_#{severity}", "[#{time}] #{severity.upcase} #{message}")
|
78
|
+
|
79
|
+
block&.call(message, options) if block_given?
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -23,7 +23,7 @@ module Rubee
|
|
23
23
|
args = to_h.dup&.transform_keys(&:to_sym)
|
24
24
|
if args[:id]
|
25
25
|
begin
|
26
|
-
|
26
|
+
update(args)
|
27
27
|
rescue StandardError => _e
|
28
28
|
return false
|
29
29
|
end
|
@@ -107,7 +107,6 @@ module Rubee
|
|
107
107
|
# > comment.user
|
108
108
|
# > <user>
|
109
109
|
def owns_one(assoc, options = {})
|
110
|
-
Sequel::Model.one_to_one(assoc, **options)
|
111
110
|
fk_name ||= "#{name.to_s.downcase}_id"
|
112
111
|
define_method(assoc) do
|
113
112
|
Object.const_get(assoc.capitalize).where(fk_name.to_sym => id)&.first
|