ru.Bee 1.5.3 → 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 +9 -4
- data/lib/config/base_configuration.rb +25 -4
- data/lib/config/routes.rb +0 -1
- data/lib/db/create_addresses.rb +17 -0
- data/lib/inits/charged_string.rb +6 -6
- data/lib/package.json +1 -1
- data/lib/rubee/async/fiber_queue.rb +27 -0
- data/lib/rubee/async/thread_pool.rb +28 -22
- 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 +5 -2
- data/lib/rubee/router.rb +41 -0
- data/lib/rubee.rb +7 -310
- data/lib/tests/async/thread_async_test.rb +36 -0
- 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/rubee_generator_test.rb +66 -62
- data/lib/tests/test.db +0 -0
- data/lib/tests/test_helper.rb +28 -0
- data/readme.md +77 -11
- metadata +20 -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
@@ -60,8 +60,8 @@ elsif command == 'react'
|
|
60
60
|
exec('npm run watch')
|
61
61
|
end
|
62
62
|
else
|
63
|
-
color_puts
|
64
|
-
exit
|
63
|
+
color_puts("Unknown command: #{command}", color: :red)
|
64
|
+
exit(1)
|
65
65
|
end
|
66
66
|
elsif command == 'project'
|
67
67
|
project_name = ARGV[1]
|
@@ -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,20 +1,41 @@
|
|
1
1
|
Rubee::Configuration.setup(env = :development) do |config|
|
2
2
|
config.database_url = { url: 'sqlite://db/development.db', env: }
|
3
3
|
|
4
|
-
|
5
|
-
# 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: }
|
6
13
|
end
|
7
14
|
|
8
15
|
Rubee::Configuration.setup(env = :test) do |config|
|
9
16
|
config.database_url = { url: 'sqlite://db/test.db', env: }
|
10
17
|
|
11
|
-
|
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
|
12
23
|
# config.react = { on: true, env: } # required if you want to use react
|
24
|
+
|
25
|
+
## configure logger
|
26
|
+
# config.logger = { logger: MyLogger, env: }
|
13
27
|
end
|
14
28
|
|
15
29
|
Rubee::Configuration.setup(env = :production) do |config|
|
16
30
|
config.database_url = { url: 'sqlite://db/production.db', env: }
|
17
31
|
|
18
|
-
|
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
|
19
37
|
# config.react = { on: true, env: } # required if you want to use react
|
38
|
+
|
39
|
+
## configure logger
|
40
|
+
# config.logger = { logger: MyLogger, env: }
|
20
41
|
end
|
data/lib/config/routes.rb
CHANGED
@@ -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/inits/charged_string.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module ChargedString
|
2
2
|
refine String do
|
3
3
|
def pluralize
|
4
|
-
if
|
4
|
+
if end_with?('y') && !%w[a e i o u].include?(self[-2])
|
5
5
|
"#{self[0..-2]}ies" # Replace "y" with "ies"
|
6
|
-
elsif
|
6
|
+
elsif end_with?('s', 'x', 'z', 'ch', 'sh')
|
7
7
|
"#{self}es" # Add "es" for certain endings
|
8
8
|
else
|
9
9
|
"#{self}s" # Default to adding "s"
|
@@ -11,7 +11,7 @@ module ChargedString
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def plural?
|
14
|
-
return true if
|
14
|
+
return true if end_with?('s') && !end_with?('ss')
|
15
15
|
|
16
16
|
false
|
17
17
|
end
|
@@ -21,11 +21,11 @@ module ChargedString
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def singularize
|
24
|
-
if
|
24
|
+
if end_with?('ies') && length > 3
|
25
25
|
"#{self[0..-4]}y" # Convert "ies" to "y"
|
26
|
-
elsif
|
26
|
+
elsif end_with?('es') && %w[s x z ch sh].any? { |ending| self[-(ending.length + 2)..-3] == ending }
|
27
27
|
self[0..-3] # Remove "es" for selfs like "foxes", "buses"
|
28
|
-
elsif
|
28
|
+
elsif end_with?('s') && length > 1
|
29
29
|
self[0..-2] # Remove "s" for regular plurals
|
30
30
|
else
|
31
31
|
self # Return as-is if no plural form is detected
|
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,48 +3,54 @@ require 'singleton'
|
|
3
3
|
module Rubee
|
4
4
|
class ThreadPool
|
5
5
|
include Singleton
|
6
|
-
THREADS_LIMIT =
|
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
|
@mutex = Mutex.new
|
13
|
-
spawn_workers
|
14
|
-
end
|
15
14
|
|
16
|
-
|
17
|
-
@queue << { task: task, args: args }
|
15
|
+
spawn_workers
|
18
16
|
end
|
19
17
|
|
20
|
-
def
|
21
|
-
@
|
18
|
+
def enqueue(task, args = {})
|
19
|
+
@tasks << [task, args]
|
22
20
|
end
|
23
21
|
|
24
22
|
def shutdown
|
25
23
|
@running = false
|
26
|
-
THREADS_LIMIT.times { @
|
27
|
-
@
|
24
|
+
THREADS_LIMIT.times { @tasks << :shutdown } # Unblock threads
|
25
|
+
@threads.each(&:join)
|
28
26
|
end
|
29
27
|
|
30
28
|
private
|
31
29
|
|
32
30
|
def spawn_workers
|
33
31
|
THREADS_LIMIT.times do
|
34
|
-
@
|
35
|
-
while @running
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
40
47
|
end
|
41
|
-
break if task == :stop
|
42
48
|
|
43
|
-
|
44
|
-
|
45
|
-
rescue StandardError => e
|
46
|
-
puts "ThreadPool Error: #{e.message}"
|
49
|
+
until fiber_queue.done?
|
50
|
+
fiber_queue.fan_out!
|
47
51
|
end
|
52
|
+
|
53
|
+
sleep(0.05)
|
48
54
|
end
|
49
55
|
end
|
50
56
|
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
|