ru.Bee 1.7.0 → 1.9.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/lib/config/base_configuration.rb +15 -0
- data/lib/rubee/autoload.rb +4 -0
- data/lib/rubee/cli/server.rb +26 -3
- data/lib/rubee/configuration.rb +15 -0
- data/lib/rubee/models/db_tools.rb +36 -0
- data/lib/rubee/models/sequel_object.rb +6 -2
- data/lib/rubee.rb +1 -1
- data/lib/tests/models/user_model_test.rb +26 -1
- data/lib/tests/test.db +0 -0
- data/readme.md +168 -97
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95729d36d2f3e6f133212e3d2e4e94bbb741a60f1c68a85a2caf97d060dcf782
|
4
|
+
data.tar.gz: 261f8261a80d2b62a79fa92b87c86677f6d1e7dd9ab2689d3e325bb1160914e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95f59f4ee8cbce2e45ff8fa6563ed3c565a8a3fe5fe7954fae249aa75af3db98fb65ee0a801f55189ad80650b2dbabb86746c3100a9a53b05eae37c3d33a18b5
|
7
|
+
data.tar.gz: 27b6af04508c9438fb838946024ffef66f8b41808de3f503c7dc6e872a7642e3e749028b71eeb77cb97657e6988d0067a1622f1654a775c3007eb4c335aee7d4
|
@@ -10,6 +10,11 @@ Rubee::Configuration.setup(env = :development) do |config|
|
|
10
10
|
|
11
11
|
## configure logger
|
12
12
|
# config.logger = { logger: MyLogger, env: }
|
13
|
+
|
14
|
+
## configure db write retries
|
15
|
+
# config.db_max_retries = { env:, value: 3 }
|
16
|
+
# config.db_retry_delay = { env:, value: 0.1 }
|
17
|
+
# config.db_busy_timeout = { env:, value: 2000 }
|
13
18
|
end
|
14
19
|
|
15
20
|
Rubee::Configuration.setup(env = :test) do |config|
|
@@ -24,6 +29,11 @@ Rubee::Configuration.setup(env = :test) do |config|
|
|
24
29
|
|
25
30
|
## configure logger
|
26
31
|
# config.logger = { logger: MyLogger, env: }
|
32
|
+
|
33
|
+
## configure db write retries
|
34
|
+
# config.db_max_retries = { env:, value: 3 }
|
35
|
+
# config.db_retry_delay = { env:, value: 0.1 }
|
36
|
+
# config.db_busy_timeout = { env:, value: 2000 }
|
27
37
|
end
|
28
38
|
|
29
39
|
Rubee::Configuration.setup(env = :production) do |config|
|
@@ -38,4 +48,9 @@ Rubee::Configuration.setup(env = :production) do |config|
|
|
38
48
|
|
39
49
|
## configure logger
|
40
50
|
# config.logger = { logger: MyLogger, env: }
|
51
|
+
|
52
|
+
## configure db write retries
|
53
|
+
# config.db_max_retries = { env:, value: 3 }
|
54
|
+
# config.db_retry_delay = { env:, value: 0.1 }
|
55
|
+
# config.db_busy_timeout = { env:, value: 2000 }
|
41
56
|
end
|
data/lib/rubee/autoload.rb
CHANGED
@@ -76,6 +76,10 @@ module Rubee
|
|
76
76
|
|
77
77
|
require_relative File.join(root_directory,
|
78
78
|
'rubee/models/sequel_object')
|
79
|
+
return if black_list.include?('db_tools.rb')
|
80
|
+
|
81
|
+
require_relative File.join(root_directory,
|
82
|
+
'rubee/models/db_tools')
|
79
83
|
|
80
84
|
Dir[File.join(root_directory, 'rubee/cli/**', '*.rb')].each do |file|
|
81
85
|
require_relative file
|
data/lib/rubee/cli/server.rb
CHANGED
@@ -17,22 +17,27 @@ LOGO
|
|
17
17
|
|
18
18
|
def start(argv)
|
19
19
|
_, port = argv.first&.split(':')
|
20
|
+
jit = argv[1]
|
20
21
|
|
21
22
|
port ||= '7000'
|
22
23
|
print_logo
|
23
24
|
color_puts("Starting takeoff of ruBee server on port #{port}...", color: :yellow)
|
24
|
-
|
25
|
+
command = "#{jit_prefix(jit)}rackup #{ENV['RACKUP_FILE']} -p #{port}"
|
26
|
+
color_puts(command, color: :gray)
|
27
|
+
exec(command)
|
25
28
|
end
|
26
29
|
|
27
30
|
def start_dev(argv)
|
28
31
|
_, port = argv.first&.split(':')
|
32
|
+
jit = argv[1]
|
29
33
|
|
30
34
|
port ||= '7000'
|
31
35
|
print_logo
|
32
36
|
|
33
37
|
color_puts("Starting takeoff of ruBee server on port #{port} in dev mode...", color: :yellow)
|
34
|
-
|
35
|
-
|
38
|
+
command = "rerun -- #{jit_prefix_dev(jit)}rackup --port #{port} #{ENV['RACKUP_FILE']}"
|
39
|
+
color_puts(command, color: :gray)
|
40
|
+
exec(command)
|
36
41
|
end
|
37
42
|
|
38
43
|
def stop(_argv)
|
@@ -46,6 +51,24 @@ LOGO
|
|
46
51
|
def print_logo
|
47
52
|
puts "\e[36m#{LOGO % Rubee::VERSION}\e[0m" # Cyan color
|
48
53
|
end
|
54
|
+
|
55
|
+
def jit_prefix(key)
|
56
|
+
case key
|
57
|
+
when 'yjit'
|
58
|
+
"ruby --yjit -S "
|
59
|
+
else
|
60
|
+
""
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def jit_prefix_dev(key)
|
65
|
+
case key
|
66
|
+
when 'yjit'
|
67
|
+
"ruby --yjit -S "
|
68
|
+
else
|
69
|
+
""
|
70
|
+
end
|
71
|
+
end
|
49
72
|
end
|
50
73
|
end
|
51
74
|
end
|
data/lib/rubee/configuration.rb
CHANGED
@@ -51,6 +51,21 @@ module Rubee
|
|
51
51
|
@configuraiton[args[:app].to_sym][args[:env].to_sym][:fiber_pool_limit] = args[:value]
|
52
52
|
end
|
53
53
|
|
54
|
+
def db_max_retries=(args)
|
55
|
+
args[:app] ||= :app
|
56
|
+
@configuraiton[args[:app].to_sym][args[:env].to_sym][:db_max_retries] = args[:value]
|
57
|
+
end
|
58
|
+
|
59
|
+
def db_retry_delay=(args)
|
60
|
+
args[:app] ||= :app
|
61
|
+
@configuraiton[args[:app].to_sym][args[:env].to_sym][:db_retry_delay] = args[:value]
|
62
|
+
end
|
63
|
+
|
64
|
+
def db_busy_timeout=(args)
|
65
|
+
args[:app] ||= :app
|
66
|
+
@configuraiton[args[:app].to_sym][args[:env].to_sym][:db_busy_timeout] = args[:value]
|
67
|
+
end
|
68
|
+
|
54
69
|
def logger=(args)
|
55
70
|
args[:app] ||= :app
|
56
71
|
@configuraiton[args[:app].to_sym][args[:env].to_sym][:logger] = args[:logger]
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Rubee
|
2
|
+
module DBTools
|
3
|
+
MAX_RETRIES = Rubee::Configuration.get_db_max_retries || 3
|
4
|
+
DELAY = Rubee::Configuration.get_db_retry_delay || 0.1
|
5
|
+
BUSY_TIMEOUT = Rubee::Configuration.get_db_busy_timeout || 2000
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def with_retry
|
9
|
+
retries = 0
|
10
|
+
begin
|
11
|
+
yield
|
12
|
+
rescue Sequel::DatabaseError => e
|
13
|
+
# Applicable for msqlite only, however it can be extended in the future
|
14
|
+
if Rubee::SequelObject::DB.adapter_scheme == :sqlite &&
|
15
|
+
e.cause.is_a?(SQLite3::BusyException) && retries < MAX_RETRIES
|
16
|
+
retries += 1
|
17
|
+
sleep(DELAY)
|
18
|
+
retry
|
19
|
+
else
|
20
|
+
raise e
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_prerequisites!
|
26
|
+
# Necessary changes to make sqlite be none blocking
|
27
|
+
if Rubee::SequelObject::DB.adapter_scheme == :sqlite
|
28
|
+
# WAL mode allows concurrent reads and non-blocking writes.
|
29
|
+
Rubee::SequelObject::DB.execute("PRAGMA journal_mode = WAL")
|
30
|
+
# Wait 2000ms for a write lock.
|
31
|
+
Rubee::SequelObject::DB.execute("PRAGMA busy_timeout = #{BUSY_TIMEOUT}")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -50,7 +50,7 @@ module Rubee
|
|
50
50
|
def update(args = {})
|
51
51
|
assign_attributes(args)
|
52
52
|
found_hash = self.class.dataset.where(id:)
|
53
|
-
return self.class.find(id) if found_hash&.update(**args)
|
53
|
+
return self.class.find(id) if Rubee::DBTools.with_retry { found_hash&.update(**args) }
|
54
54
|
|
55
55
|
false
|
56
56
|
end
|
@@ -130,6 +130,10 @@ module Rubee
|
|
130
130
|
return if defined?(DB) && !DB.nil?
|
131
131
|
|
132
132
|
const_set(:DB, Sequel.connect(Rubee::Configuration.get_database_url))
|
133
|
+
|
134
|
+
Rubee::DBTools.set_prerequisites!
|
135
|
+
|
136
|
+
true
|
133
137
|
end
|
134
138
|
|
135
139
|
def dataset
|
@@ -169,7 +173,7 @@ module Rubee
|
|
169
173
|
end
|
170
174
|
|
171
175
|
def create(attrs)
|
172
|
-
out_id = dataset.insert(**attrs)
|
176
|
+
out_id = Rubee::DBTools.with_retry { dataset.insert(**attrs) }
|
173
177
|
new(**attrs.merge(id: out_id))
|
174
178
|
end
|
175
179
|
|
data/lib/rubee.rb
CHANGED
@@ -16,7 +16,7 @@ module Rubee
|
|
16
16
|
JS_DIR = File.join(APP_ROOT, LIB, 'js') unless defined?(JS_DIR)
|
17
17
|
CSS_DIR = File.join(APP_ROOT, LIB, 'css') unless defined?(CSS_DIR)
|
18
18
|
ROOT_PATH = File.expand_path(File.join(__dir__, '..')) unless defined?(ROOT_PATH)
|
19
|
-
VERSION = '1.
|
19
|
+
VERSION = '1.9.0'
|
20
20
|
|
21
21
|
require_relative 'rubee/router'
|
22
22
|
require_relative 'rubee/logger'
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require_relative '../test_helper'
|
2
|
-
|
3
2
|
describe 'User model' do
|
4
3
|
describe '.create' do
|
5
4
|
after do
|
@@ -68,6 +67,32 @@ describe 'User model' do
|
|
68
67
|
_(User.all.count).must_equal(initial_count)
|
69
68
|
end
|
70
69
|
end
|
70
|
+
|
71
|
+
describe 'locking model' do
|
72
|
+
before do
|
73
|
+
User.destroy_all(cascade: true)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'triggers save two times' do
|
77
|
+
t1 = Thread.new do
|
78
|
+
User::DB.transaction do
|
79
|
+
user2 = User.new(email: 'holding-lock2@example.com', password: '125')
|
80
|
+
sleep(0.5)
|
81
|
+
user2.save
|
82
|
+
end
|
83
|
+
end
|
84
|
+
sleep(0.1)
|
85
|
+
t2 = Thread.new do
|
86
|
+
user1 = User.new(email: 'holding-lock@example.com', password: '123')
|
87
|
+
user1.save
|
88
|
+
end
|
89
|
+
|
90
|
+
t1.join
|
91
|
+
t2.join
|
92
|
+
|
93
|
+
_(User.all.count).must_equal(2)
|
94
|
+
end
|
95
|
+
end
|
71
96
|
end
|
72
97
|
|
73
98
|
describe '.update' do
|
data/lib/tests/test.db
CHANGED
Binary file
|
data/readme.md
CHANGED
@@ -8,56 +8,67 @@
|
|
8
8
|
|
9
9
|
# <img src="lib/images/rubee.svg" alt="ruBee" height="40"> ... ruBee
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
Rubee is a Ruby-based framework designed to streamline the development of modular monolith applications. \
|
12
|
+
It offers a structured approach to building scalable, maintainable, and React-ready projects, \
|
13
|
+
making it an ideal choice for developers seeking a balance between monolithic simplicity and modular flexibility.
|
14
14
|
|
15
15
|
Want to get a quick API server up and runing? You can do it for real quick!
|
16
16
|
<br />
|
17
|
-
[](https://www.youtube.com/watch?v=ko7H70s7qq0)
|
18
|
+
## Content
|
22
19
|
|
23
|
-
- [Installation](#
|
20
|
+
- [Installation](#installation)
|
24
21
|
- [Run tests](#run-tests)
|
25
22
|
- [Draw contract](#draw-contract)
|
26
|
-
- [Model](#
|
27
|
-
- [Routing](#
|
28
|
-
- [Database](#
|
29
|
-
- [Views](#
|
30
|
-
- [Hooks](#
|
31
|
-
- [JWT based authentification](#
|
32
|
-
- [Rubee commands](#
|
33
|
-
- [Generate commands](#
|
34
|
-
- [Migration commands](#
|
35
|
-
- [Rubee console](#
|
36
|
-
- [Testing](#
|
37
|
-
- [Background jobs](#
|
38
|
-
- [Modular](#
|
39
|
-
- [Logger](#
|
23
|
+
- [Model](#model)
|
24
|
+
- [Routing](#routing)
|
25
|
+
- [Database](#database)
|
26
|
+
- [Views](#views)
|
27
|
+
- [Hooks](#hooks)
|
28
|
+
- [JWT based authentification](#jwt-based-authentification)
|
29
|
+
- [Rubee commands](#rubee-commands)
|
30
|
+
- [Generate commands](#generate-commands)
|
31
|
+
- [Migration commands](#migration-commands)
|
32
|
+
- [Rubee console](#rubee-console)
|
33
|
+
- [Testing](#testing)
|
34
|
+
- [Background jobs](#background-jobs)
|
35
|
+
- [Modular](#modualar-application)
|
36
|
+
- [Logger](#logger)
|
40
37
|
|
41
38
|
## Features
|
42
39
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
40
|
+
🐝 Lightweight – A minimal footprint focused on serving Ruby applications efficiently.
|
41
|
+
<br>
|
42
|
+
🧩 Modular – A modular approach to application development. Build modular monoliths with ease by attaching \
|
43
|
+
as many subprojects as you need.
|
44
|
+
<br>
|
45
|
+
📜 Contract-driven – Define your API contracts in a simple, declarative way, then generate all the boilerplate you need.
|
46
|
+
<br>
|
47
|
+
⚡ Fast – Optimized for speed, providing quick responses. (Everything is relative, we know! 😄)
|
48
|
+
<br>
|
49
|
+
🧱 Rack-powered – Built on Rack. The full Rack API is available for easy integration.
|
50
|
+
<br>
|
51
|
+
🗄️ Databases – Supports SQLite3, PostgreSQL, MySQL, and more via the Sequel gem.
|
52
|
+
<br>
|
53
|
+
🖼️ Views – JSON, ERB, and plain HTML out of the box.
|
54
|
+
<br>
|
55
|
+
⚛️ React Ready – React is supported as a first-class Rubee view engine.
|
56
|
+
<br>
|
57
|
+
📦 Bundlable – Charge your Rubee app with any gem you need. Update effortlessly via Bundler.
|
58
|
+
<br>
|
59
|
+
🧬 ORM-agnostic – Models are native ORM objects, but you can use them as blueprints for any data source.
|
60
|
+
<br>
|
61
|
+
🔐 Authenticatable – Easily add JWT authentication to any controller action.
|
62
|
+
<br>
|
63
|
+
🪝 Hooks – Add logic before, after, or around any controller action.
|
64
|
+
<br>
|
65
|
+
🧪 Testable – Run all or selected tests using fast, beloved Minitest.
|
66
|
+
<br>
|
67
|
+
👷 Asyncable – Plug in async adapters and use any popular background job engine.
|
68
|
+
<br>
|
69
|
+
⌨️ Console – Start an interactive console and reload on the fly.
|
70
|
+
<br>
|
71
|
+
⚙️ Background Jobs – Schedule and process background jobs using your preferred async stack.
|
61
72
|
|
62
73
|
## Installation
|
63
74
|
|
@@ -69,16 +80,17 @@ gem install ru.Bee
|
|
69
80
|
2. Create your first project
|
70
81
|
```bash
|
71
82
|
rubee project my_project
|
83
|
+
|
72
84
|
cd my_project
|
73
85
|
```
|
74
|
-
- [Back to content](#Content)
|
75
86
|
|
87
|
+
[Back to content](#content)
|
76
88
|
|
77
89
|
3. Install dependencies
|
78
90
|
|
79
91
|
***Prerequisites***<br />
|
80
92
|
Make sure:
|
81
|
-
**Ruby** language (3
|
93
|
+
**Ruby** language (3.1>) is installed
|
82
94
|
**Bundler** is installed
|
83
95
|
|
84
96
|
```bash
|
@@ -87,7 +99,12 @@ bundle install
|
|
87
99
|
|
88
100
|
4. Run ruBee server. Default port is 7000
|
89
101
|
```bash
|
90
|
-
rubee start
|
102
|
+
rubee start # or rubee start_dev for development
|
103
|
+
|
104
|
+
# Sarting from veriosn 1.8.0, you can also start you rubee server with yjit compiler and enjoy speed boost.
|
105
|
+
rubee start --yjit
|
106
|
+
# Option is available for dev environment too
|
107
|
+
rubee start_dev --yjit
|
91
108
|
```
|
92
109
|
|
93
110
|
5. Open your browser and go to http://localhost:7000
|
@@ -95,10 +112,13 @@ rubee start
|
|
95
112
|
## Run tests
|
96
113
|
```bash
|
97
114
|
rubee test
|
115
|
+
# or you can specify specific test file
|
116
|
+
rubee test models/user_model_test.rb
|
98
117
|
```
|
99
|
-
|
118
|
+
[Back to content](#content)
|
100
119
|
|
101
120
|
## Draw contract
|
121
|
+
|
102
122
|
1. Add the routes to the routes.rb
|
103
123
|
```ruby
|
104
124
|
Rubee::Router.draw do |router|
|
@@ -115,6 +135,7 @@ rubee test
|
|
115
135
|
}
|
116
136
|
end
|
117
137
|
```
|
138
|
+
|
118
139
|
2. generate the files
|
119
140
|
```bash
|
120
141
|
rubee generate get /apples
|
@@ -128,17 +149,17 @@ This will generate the following files
|
|
128
149
|
```
|
129
150
|
|
130
151
|
3. Run the initial db migration
|
131
|
-
|
152
|
+
```bash
|
132
153
|
rubee db run:all
|
133
|
-
|
154
|
+
```
|
134
155
|
|
135
|
-
|
136
|
-
|
156
|
+
4. Fill the generated files with the logic you need and run the server again!
|
157
|
+
|
158
|
+
[Back to content](#content)
|
137
159
|
|
138
160
|
## Model
|
139
161
|
Model in ruBee is just simple ruby object that can be serilalized in the view
|
140
162
|
in the way it required (ie json).
|
141
|
-
|
142
163
|
Here below is a simple example on how it can be used by rendering json from in memory object
|
143
164
|
|
144
165
|
```ruby
|
@@ -160,6 +181,7 @@ Just make sure Serializable module included in the target class.
|
|
160
181
|
attr_accessor :id, :colour, :weight
|
161
182
|
end
|
162
183
|
```
|
184
|
+
|
163
185
|
However, you can simply turn it to ORM object by extending database class Rubee::SequelObject.
|
164
186
|
This one is already serializable and charged with hooks.
|
165
187
|
```Ruby
|
@@ -182,9 +204,10 @@ So in the controller you would need to query your target object now.
|
|
182
204
|
end
|
183
205
|
end
|
184
206
|
```
|
185
|
-
- [Back to content](#Content)
|
186
207
|
|
187
|
-
|
208
|
+
[Back to content](#content)
|
209
|
+
|
210
|
+
#### Rubee::SequelObject base methods
|
188
211
|
|
189
212
|
Initiate new record in memory
|
190
213
|
```Ruby
|
@@ -313,10 +336,32 @@ irb(main):010> .then { |dataset| Comment.serialize(dataset) }
|
|
313
336
|
```
|
314
337
|
This is recommended when you want to run one query and serialize it back to Rubee object only once.
|
315
338
|
So it may safe some resources.
|
316
|
-
|
339
|
+
|
340
|
+
[Back to content](#content)
|
341
|
+
|
342
|
+
## Mysqlite production ready
|
343
|
+
Starting from verison 1.9.0 main issue for using sqlite - write db lock is resolved!
|
344
|
+
If you feel comfortable you can play with retry configuration parameters:
|
345
|
+
|
346
|
+
```ruby
|
347
|
+
## configure db write retries
|
348
|
+
config.db_max_retries = { env:, value: 3 } # set it to 0 to disable or increase if needed
|
349
|
+
config.db_retry_delay = { env:, value: 0.1 }
|
350
|
+
config.db_busy_timeout = { env:, value: 1000 } # this is busy timeout in ms, before raising bussy error
|
351
|
+
```
|
352
|
+
|
353
|
+
For Rubee model class persist methods create and update retry will be added automatically. However, \
|
354
|
+
if you want to do it with Sequel dataset you need to do it yourself:
|
355
|
+
|
356
|
+
```ruby
|
357
|
+
Rubee::DBTools.with_retry { User.dataset.insert(email: "test@ok.com", password: "123") }
|
358
|
+
```
|
359
|
+
[Back to content](#content)
|
317
360
|
|
318
361
|
## Routing
|
319
|
-
Rubee uses explicit routes. In the routes.rb yout can define routes for any of the main HTTP methods.
|
362
|
+
Rubee uses explicit routes. In the routes.rb yout can define routes for any of the main HTTP methods. \
|
363
|
+
You can also add any matched parameter denoted by a pair of `{ }` in the path of the route. \
|
364
|
+
Eg. `/path/to/{a_key}/somewhere`
|
320
365
|
|
321
366
|
### Routing methods
|
322
367
|
``` ruby
|
@@ -334,10 +379,14 @@ end
|
|
334
379
|
```
|
335
380
|
|
336
381
|
As you see above every route is set up as:\
|
337
|
-
|
382
|
+
```ruby
|
383
|
+
route.{http_method} {path}, to: "{controller}#{action}",
|
384
|
+
model { ...optional }, namespace { ...optional }, react { ...optional }
|
385
|
+
```
|
338
386
|
|
339
387
|
### Defining Model attributes in routes
|
340
|
-
One of Rubee's unique traits is where we can define our models for generation.
|
388
|
+
One of Rubee's unique traits is where we can define our models for generation. \
|
389
|
+
You've seen above one possible way you can set up.
|
341
390
|
|
342
391
|
```ruby
|
343
392
|
Rubee::Router.draw do |router|
|
@@ -355,41 +404,52 @@ Rubee::Router.draw do |router|
|
|
355
404
|
end
|
356
405
|
```
|
357
406
|
|
358
|
-
There are many other
|
407
|
+
There are many other types supported by us and Sequel to help generate your initial db files. \
|
408
|
+
Other supported attribute key types are:
|
359
409
|
``` ruby
|
360
410
|
[
|
361
|
-
{ name: '
|
362
|
-
{ name: '
|
363
|
-
{ name: '
|
364
|
-
{ name: '
|
365
|
-
{ name: '
|
366
|
-
{ name: '
|
367
|
-
{ name: '
|
368
|
-
{ name: '
|
369
|
-
{ name: '
|
370
|
-
{ name: '
|
371
|
-
{ name: '
|
372
|
-
{ name: '
|
373
|
-
{ name: '
|
411
|
+
{ name: 'id', type: :primary},
|
412
|
+
{ name: 'name', type: :string },
|
413
|
+
{ name: 'description', type: :text },
|
414
|
+
{ name: 'quntity', type: :integer },
|
415
|
+
{ name: 'created', type: :date },
|
416
|
+
{ name: 'modified', type: :datetime },
|
417
|
+
{ name: 'exists', type: :time },
|
418
|
+
{ name: 'active', type: :boolean },
|
419
|
+
{ name: 'hash', type: :bigint },
|
420
|
+
{ name: 'price', type: :decimal },
|
421
|
+
{ name: 'item_id', type: :foreign_key },
|
422
|
+
{ name: 'item_id_index', type: :index },
|
423
|
+
{ name: 'item_id_unique', type: :unique }
|
374
424
|
]
|
375
425
|
```
|
376
|
-
Every attribute can have a set of options passed based on their related
|
426
|
+
Every attribute can have a set of options passed based on their related \
|
427
|
+
[Sequel schema definition](https://github.com/jeremyevans/sequel/blob/master/doc/schema_modification.rdoc).
|
377
428
|
|
378
429
|
An example of this would be for the type string: \
|
379
|
-
|
430
|
+
```ruby
|
431
|
+
{name: 'key', type: :string, options: { size: 50, fixed: true } }
|
432
|
+
```
|
380
433
|
|
381
434
|
Gets translated to:\
|
382
|
-
|
435
|
+
```
|
436
|
+
rubyString :key, size: 50, fixed: true
|
437
|
+
```
|
383
438
|
|
384
439
|
### Generation from routes
|
385
|
-
As long as you have a `{ model: 'something' }` passed to your given route
|
440
|
+
As long as you have a `{ model: 'something' }` passed to your given route, \
|
441
|
+
you can use it to generate your initial model files. If only a `path` and a `to:` are defined will only generate \
|
442
|
+
a controller and a corresponding view.
|
386
443
|
|
387
444
|
To generate based on a get route for the path /apples:\
|
388
|
-
|
445
|
+
```ruby
|
446
|
+
rubee generate get /apples # or rubee gen get /apples
|
447
|
+
```
|
389
448
|
|
390
449
|
To generate base on a patch request for the path /apples/{id}:\
|
391
|
-
|
392
|
-
|
450
|
+
```ruby
|
451
|
+
rubee generate patch /apples/{id} # or rubee gen patch /apples/{id}
|
452
|
+
```
|
393
453
|
|
394
454
|
Example:
|
395
455
|
```ruby
|
@@ -413,6 +473,7 @@ Rubee::Router.draw do |router|
|
|
413
473
|
router.get "/apples", to: "apples#index", model: { name: 'apple' }
|
414
474
|
end
|
415
475
|
```
|
476
|
+
|
416
477
|
Will generate:
|
417
478
|
```bash
|
418
479
|
./app/controllers/apples_controller.rb # Controller with respective action
|
@@ -446,15 +507,16 @@ Will generate:
|
|
446
507
|
./db/create_apples.rb # Database migration file needed for creating repsective table
|
447
508
|
```
|
448
509
|
|
510
|
+
|
449
511
|
### Modualar application
|
450
512
|
|
451
513
|
You can also use ruBee to create modular applications.\
|
452
514
|
And attach as many subprojects you need.
|
453
515
|
Main philosophy of attach functinality is to keep the main project clean and easy to maintain. It will still\
|
454
|
-
share data with the main app. So where to define a border between main app and subprojects is up to developer.
|
516
|
+
share data with the main app. So where to define a border between the main app and subprojects is up to developer.
|
455
517
|
Howerver by attching new subproject you will get a new folder and files configured and namespaced respectively.
|
456
518
|
|
457
|
-
So if you need to extend your main app with a separate project you can do it easily in ruBee.
|
519
|
+
So if you need to extend your main app with a separate project, you can do it easily in ruBee.
|
458
520
|
1. Attach new subrpoject
|
459
521
|
|
460
522
|
```bash
|
@@ -470,17 +532,18 @@ files will be created there.
|
|
470
532
|
Rubee::Router.draw do |router|
|
471
533
|
...
|
472
534
|
# draw the contract
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
535
|
+
router.get '/admin/cabages', to: 'cabages#index',
|
536
|
+
model: {
|
537
|
+
name: 'cabage',
|
538
|
+
attributes: [
|
539
|
+
{ name: 'id', type: :primary },
|
540
|
+
{ name: 'name', type: :string }
|
541
|
+
]
|
542
|
+
},
|
543
|
+
namespace: :admin # mandatory option for supporting namespacing
|
482
544
|
end
|
483
545
|
```
|
546
|
+
|
484
547
|
3. Run gen command
|
485
548
|
|
486
549
|
```bash
|
@@ -501,6 +564,7 @@ This will generate the bolierplate files:
|
|
501
564
|
```bash
|
502
565
|
rubee db run:create_cabages
|
503
566
|
```
|
567
|
+
|
504
568
|
5. Fill the views and controller with the content
|
505
569
|
|
506
570
|
```ruby
|
@@ -518,7 +582,7 @@ end
|
|
518
582
|
rubee start # or rubee start_dev for development
|
519
583
|
```
|
520
584
|
|
521
|
-
|
585
|
+
[Back to content](#content)
|
522
586
|
|
523
587
|
## Views
|
524
588
|
View in ruBee is just a plain html/erb/react file that can be rendered from the controller.
|
@@ -567,6 +631,7 @@ Prerequisites: Node and NPM are required
|
|
567
631
|
```bash
|
568
632
|
rubee react prepare # this will install react related node modules
|
569
633
|
```
|
634
|
+
|
570
635
|
2. Make sure you have configured react in the configuration file
|
571
636
|
|
572
637
|
```ruby
|
@@ -600,7 +665,7 @@ Rubee::Router.draw do |router|
|
|
600
665
|
router.get('/', to: 'welcome#show') # override it for your app
|
601
666
|
|
602
667
|
router.get('/api/users', to: 'user#index', react: { view_name: 'users.tsx' })
|
603
|
-
# Please note /api/users is the backend endpoint
|
668
|
+
# Please note /api/users here is the backend endpoint
|
604
669
|
# For rendering generated /app/views/users.tsx file, you need to update react routes
|
605
670
|
end
|
606
671
|
```
|
@@ -654,7 +719,7 @@ function Users() {
|
|
654
719
|
}
|
655
720
|
|
656
721
|
```
|
657
|
-
|
722
|
+
[Back to content](#content)
|
658
723
|
|
659
724
|
## Object hooks
|
660
725
|
|
@@ -697,10 +762,11 @@ after index2
|
|
697
762
|
after log around
|
698
763
|
127.0.0.1 - - [17/Feb/2025:11:42:14 -0500] "GET /apples HTTP/1.1" 401 - 0.0359
|
699
764
|
```
|
700
|
-
- [Back to content](#Content)
|
701
765
|
|
766
|
+
[Back to content](#content)
|
702
767
|
|
703
768
|
## JWT based authentification
|
769
|
+
|
704
770
|
Charge you rpoject with token based authentification system and customize it for your needs.
|
705
771
|
include AuthTokenable module to your controller and authentificate any action you need.
|
706
772
|
|
@@ -748,7 +814,8 @@ class UsersController < Rubee::BaseController
|
|
748
814
|
end
|
749
815
|
end
|
750
816
|
```
|
751
|
-
|
817
|
+
|
818
|
+
[Back to content](#content)
|
752
819
|
|
753
820
|
## Rubee commands
|
754
821
|
```bash
|
@@ -783,7 +850,8 @@ rubee console # start the console
|
|
783
850
|
rubee test # run all tests
|
784
851
|
rubee test auth_tokenable_test.rb # run specific tests
|
785
852
|
```
|
786
|
-
|
853
|
+
|
854
|
+
[Back to content](#content)
|
787
855
|
|
788
856
|
|
789
857
|
If you want to run any ruBee command within a specific ENV make sure you added it before a command.
|
@@ -850,6 +918,7 @@ end
|
|
850
918
|
```ruby
|
851
919
|
TestAsyncRunnner.new.perform_async(options: {"email"=> "new@new.com", "password"=> "123"})
|
852
920
|
```
|
921
|
+
|
853
922
|
### Default engine is ThreadAsync
|
854
923
|
However it is not yet recommended for production. Use it with cautions!
|
855
924
|
1. Do not define any adapter in the /config/base_configuration.rb file, so default ThreadAsync will be taken.
|
@@ -866,7 +935,8 @@ end
|
|
866
935
|
|
867
936
|
TestAsyncRunnner.new.perform_async(options: {"email"=> "new@new.com", "password"=> "123"})
|
868
937
|
```
|
869
|
-
|
938
|
+
|
939
|
+
[Back to content](#content)
|
870
940
|
|
871
941
|
### Logger
|
872
942
|
|
@@ -913,7 +983,8 @@ When you trigger the controller action, the logs will look like this:
|
|
913
983
|
[2025-04-26 12:32:33] INFO [method: show][class_name: WelcomeController] Execution Time: 0.000655 seconds
|
914
984
|
[2025-04-26 12:32:33] DEBUG [method: show][class_name: WelcomeController] #<User:0x000000012c5c63e0 @id=4545, @email="ok@op.com", @password="123">
|
915
985
|
```
|
916
|
-
|
986
|
+
|
987
|
+
[Back to content](#content)
|
917
988
|
|
918
989
|
### Contributing
|
919
990
|
|
@@ -924,4 +995,4 @@ Have an idea or you wnat to discuss something?
|
|
924
995
|
Please open a [discussion](https://github.com/nucleom42/rubee/discussions)
|
925
996
|
|
926
997
|
## License
|
927
|
-
This project is released under the MIT License.
|
998
|
+
This project is released under the [MIT License](https://github.com/nucleom42/rubee/blob/main/LICENSE).
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ru.Bee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleg Saltykov
|
@@ -255,6 +255,7 @@ files:
|
|
255
255
|
- lib/rubee/generator.rb
|
256
256
|
- lib/rubee/logger.rb
|
257
257
|
- lib/rubee/models/database_objectable.rb
|
258
|
+
- lib/rubee/models/db_tools.rb
|
258
259
|
- lib/rubee/models/sequel_object.rb
|
259
260
|
- lib/rubee/router.rb
|
260
261
|
- lib/tests/async/thread_async_test.rb
|
@@ -290,7 +291,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
290
291
|
requirements:
|
291
292
|
- - ">="
|
292
293
|
- !ruby/object:Gem::Version
|
293
|
-
version: 3.
|
294
|
+
version: 3.4.1
|
294
295
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
295
296
|
requirements:
|
296
297
|
- - ">="
|