ru.Bee 1.10.1 → 1.11.1
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/rubee/extensions/hookable.rb +9 -41
- data/lib/rubee/models/sequel_object.rb +7 -5
- data/lib/rubee.rb +1 -1
- data/lib/tests/controllers/hookable_test.rb +56 -0
- data/lib/tests/logger_test.rb +0 -6
- data/lib/tests/models/user_model_test.rb +2 -2
- data/lib/tests/test.db +0 -0
- data/readme.md +51 -7
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b6c1764a41eaa86619270fbaf3077cb5fc55b8d9c6b4f4edac37c2ac7f584fb7
|
|
4
|
+
data.tar.gz: e298000985901fea481a623fd1a08759b6be441251dba2efd78d0120f1ee16f1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d11f20305783059eef64fa35530e2c6861ff708db527e6ff628b8d735b833d3ec565ce7bbeb4faa9ac0fb98d7868007c8c8728804ecd07adf37a49fc7f665c20
|
|
7
|
+
data.tar.gz: 91b9a63e9bc18c4be04d6e11b097607c01733921b6ba9e33134ea0ee07780fbdf4352083e76f901f741856048732f2a55b8998451a735260aa61da05df80644c
|
|
@@ -7,16 +7,6 @@ module Rubee
|
|
|
7
7
|
|
|
8
8
|
module ClassMethods
|
|
9
9
|
def before(*methods, handler, **options)
|
|
10
|
-
if options[:class_methods]
|
|
11
|
-
methods.each do |method|
|
|
12
|
-
define_method(method) do |*args, &block|
|
|
13
|
-
self.class.send(method, *args, &block)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
private(method)
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
10
|
methods.each do |method|
|
|
21
11
|
hook = Module.new do
|
|
22
12
|
define_method(method) do |*args, &block|
|
|
@@ -28,21 +18,11 @@ module Rubee
|
|
|
28
18
|
end
|
|
29
19
|
end
|
|
30
20
|
|
|
31
|
-
prepend(hook)
|
|
21
|
+
options[:class_methods] ? singleton_class.prepend(hook) : prepend(hook)
|
|
32
22
|
end
|
|
33
23
|
end
|
|
34
24
|
|
|
35
25
|
def after(*methods, handler, **options)
|
|
36
|
-
if options[:class_methods]
|
|
37
|
-
methods.each do |method|
|
|
38
|
-
define_method(method) do |*args, &block|
|
|
39
|
-
self.class.send(method, *args, &block)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
private(method)
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
26
|
methods.each do |method|
|
|
47
27
|
hook = Module.new do
|
|
48
28
|
define_method(method) do |*args, &block|
|
|
@@ -56,21 +36,11 @@ module Rubee
|
|
|
56
36
|
end
|
|
57
37
|
end
|
|
58
38
|
|
|
59
|
-
prepend(hook)
|
|
39
|
+
options[:class_methods] ? singleton_class.prepend(hook) : prepend(hook)
|
|
60
40
|
end
|
|
61
41
|
end
|
|
62
42
|
|
|
63
43
|
def around(*methods, handler, **options)
|
|
64
|
-
if options[:class_methods]
|
|
65
|
-
methods.each do |method|
|
|
66
|
-
define_method(method) do |*args, &block|
|
|
67
|
-
self.class.send(method, *args, &block)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
private(method)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
44
|
methods.each do |method|
|
|
75
45
|
hook = Module.new do
|
|
76
46
|
define_method(method) do |*args, &block|
|
|
@@ -93,17 +63,9 @@ module Rubee
|
|
|
93
63
|
end
|
|
94
64
|
end
|
|
95
65
|
|
|
96
|
-
prepend(hook)
|
|
66
|
+
options[:class_methods] ? singleton_class.prepend(hook) : prepend(hook)
|
|
97
67
|
end
|
|
98
68
|
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
module InstanceMethods
|
|
102
|
-
private
|
|
103
|
-
|
|
104
|
-
def handle_class_method
|
|
105
|
-
self.class.send(name, *args, &block)
|
|
106
|
-
end
|
|
107
69
|
|
|
108
70
|
def conditions_met?(if_condition = nil, unless_condition = nil)
|
|
109
71
|
return true if if_condition.nil? && unless_condition.nil?
|
|
@@ -128,5 +90,11 @@ module Rubee
|
|
|
128
90
|
if_condition_result && !unless_condition_result
|
|
129
91
|
end
|
|
130
92
|
end
|
|
93
|
+
|
|
94
|
+
module InstanceMethods
|
|
95
|
+
def conditions_met?(if_condition = nil, unless_condition = nil)
|
|
96
|
+
self.class.conditions_met?(if_condition, unless_condition)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
131
99
|
end
|
|
132
100
|
end
|
|
@@ -4,7 +4,7 @@ module Rubee
|
|
|
4
4
|
using ChargedString
|
|
5
5
|
using ChargedHash
|
|
6
6
|
|
|
7
|
-
before :
|
|
7
|
+
before :update, :save, :set_timestamps
|
|
8
8
|
|
|
9
9
|
def destroy(cascade: false, **_options)
|
|
10
10
|
if cascade
|
|
@@ -43,13 +43,15 @@ module Rubee
|
|
|
43
43
|
true
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
def assign_attributes(args={})
|
|
47
|
-
self.class.dataset.columns do |attr|
|
|
48
|
-
|
|
46
|
+
def assign_attributes(args = {})
|
|
47
|
+
self.class.dataset.columns.each do |attr|
|
|
48
|
+
if args[attr.to_sym]
|
|
49
|
+
send("#{attr}=", args[attr.to_sym])
|
|
50
|
+
end
|
|
49
51
|
end
|
|
50
52
|
end
|
|
51
53
|
|
|
52
|
-
def update(args={})
|
|
54
|
+
def update(args = {})
|
|
53
55
|
assign_attributes(args)
|
|
54
56
|
args.merge!(updated:)
|
|
55
57
|
found_hash = self.class.dataset.where(id:)
|
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.11.1'
|
|
20
20
|
|
|
21
21
|
require_relative 'rubee/router'
|
|
22
22
|
require_relative 'rubee/logger'
|
|
@@ -54,6 +54,11 @@ class TestHookable
|
|
|
54
54
|
before :prep_unless_condition, :set_value
|
|
55
55
|
after :set_unless_condition, :set_glue, unless: :value_red
|
|
56
56
|
|
|
57
|
+
# Check class methods
|
|
58
|
+
before :before_print_hello, :print_world, class_methods: true
|
|
59
|
+
after :after_print_hello, :print_world, class_methods: true
|
|
60
|
+
around :around_print_hello, :around_print_world, class_methods: true
|
|
61
|
+
|
|
57
62
|
def after_around_before; end
|
|
58
63
|
|
|
59
64
|
def before_around_after; end
|
|
@@ -82,6 +87,31 @@ class TestHookable
|
|
|
82
87
|
value == 'red'
|
|
83
88
|
end
|
|
84
89
|
|
|
90
|
+
class << self
|
|
91
|
+
def before_print_hello
|
|
92
|
+
puts 'hello'
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def after_print_hello
|
|
96
|
+
puts 'hello'
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def around_print_hello
|
|
100
|
+
puts 'hello'
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def print_world
|
|
104
|
+
puts 'world'
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def around_print_world
|
|
108
|
+
puts 'world1'
|
|
109
|
+
res = yield
|
|
110
|
+
puts 'world2'
|
|
111
|
+
res
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
85
115
|
private
|
|
86
116
|
|
|
87
117
|
def set_value
|
|
@@ -217,4 +247,30 @@ describe 'Hookable Controller' do
|
|
|
217
247
|
_(hookable.glue).must_be_nil
|
|
218
248
|
end
|
|
219
249
|
end
|
|
250
|
+
|
|
251
|
+
describe 'class methods' do
|
|
252
|
+
it 'calls before print hello hook' do
|
|
253
|
+
output = capture_io do
|
|
254
|
+
TestHookable.before_print_hello
|
|
255
|
+
end.first # capture_io returns [stdout, stderr]
|
|
256
|
+
|
|
257
|
+
_(output).must_equal("world\nhello\n")
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it 'calls after print hello hook' do
|
|
261
|
+
output = capture_io do
|
|
262
|
+
TestHookable.after_print_hello
|
|
263
|
+
end.first # capture_io returns [stdout, stderr]
|
|
264
|
+
|
|
265
|
+
_(output).must_equal("hello\nworld\n")
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
it 'calls around print hello hook' do
|
|
269
|
+
output = capture_io do
|
|
270
|
+
TestHookable.around_print_hello
|
|
271
|
+
end.first # capture_io returns [stdout, stderr]
|
|
272
|
+
|
|
273
|
+
_(output).must_equal("world1\nhello\nworld2\n")
|
|
274
|
+
end
|
|
275
|
+
end
|
|
220
276
|
end
|
data/lib/tests/logger_test.rb
CHANGED
|
@@ -19,14 +19,12 @@ end
|
|
|
19
19
|
describe 'Rubee::Logger' do
|
|
20
20
|
describe 'logger' do
|
|
21
21
|
it 'exists' do
|
|
22
|
-
puts "logger exists"
|
|
23
22
|
_(Rubee::Logger).wont_be_nil
|
|
24
23
|
end
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
describe '.warn' do
|
|
28
27
|
it 'output message' do
|
|
29
|
-
puts "warn output message"
|
|
30
28
|
output = capture_stdout { Rubee::Logger.warn(message: 'test') }
|
|
31
29
|
|
|
32
30
|
assert_includes(output, "WARN test")
|
|
@@ -35,7 +33,6 @@ describe 'Rubee::Logger' do
|
|
|
35
33
|
|
|
36
34
|
describe '.info' do
|
|
37
35
|
it 'output message' do
|
|
38
|
-
puts "info output message"
|
|
39
36
|
output = capture_stdout { Rubee::Logger.info(message: 'test') }
|
|
40
37
|
|
|
41
38
|
assert_includes(output, "INFO test")
|
|
@@ -52,7 +49,6 @@ describe 'Rubee::Logger' do
|
|
|
52
49
|
|
|
53
50
|
describe '.critical' do
|
|
54
51
|
it 'output message' do
|
|
55
|
-
puts "critical output message"
|
|
56
52
|
output = capture_stdout { Rubee::Logger.critical(message: 'test') }
|
|
57
53
|
|
|
58
54
|
assert_includes(output, "CRITICAL test")
|
|
@@ -61,7 +57,6 @@ describe 'Rubee::Logger' do
|
|
|
61
57
|
|
|
62
58
|
describe '.debug' do
|
|
63
59
|
it 'output message' do
|
|
64
|
-
puts "debug output message"
|
|
65
60
|
output = capture_stdout { Rubee::Logger.debug(object: User.new(email: 'ok@ok.com', password: 123)) }
|
|
66
61
|
|
|
67
62
|
assert_includes(output, "DEBUG #<User:")
|
|
@@ -70,7 +65,6 @@ describe 'Rubee::Logger' do
|
|
|
70
65
|
|
|
71
66
|
describe 'when custom logger defined in the configuration' do
|
|
72
67
|
it 'uses custom logger' do
|
|
73
|
-
puts "CUSTOM INFO test"
|
|
74
68
|
Rubee::Configuration.setup(env = :test) { _1.logger = { logger: CustomLogger, env: } }
|
|
75
69
|
|
|
76
70
|
output = capture_stdout { Rubee::Logger.info(message: 'test') }
|
|
@@ -140,14 +140,14 @@ describe 'User model' do
|
|
|
140
140
|
end
|
|
141
141
|
end
|
|
142
142
|
|
|
143
|
-
describe 'when udpate existing user with no
|
|
143
|
+
describe 'when udpate existing user with no arguments' do
|
|
144
144
|
it 'update updated field' do
|
|
145
145
|
user = User.new(email: 'ok-test@test.com', password: '123')
|
|
146
146
|
user.save
|
|
147
147
|
updated_field_before_update = user.updated
|
|
148
148
|
|
|
149
149
|
user.update
|
|
150
|
-
_(user.updated > updated_field_before_update).must_equal(true)
|
|
150
|
+
_(user.reload.updated > updated_field_before_update).must_equal(true)
|
|
151
151
|
end
|
|
152
152
|
end
|
|
153
153
|
end
|
data/lib/tests/test.db
CHANGED
|
Binary file
|
data/readme.md
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
# <img src="lib/images/rubee.svg" alt="RUBEE" height="40"> ... RUBEE
|
|
10
10
|
|
|
11
|
-
Rubee is a Ruby-based framework designed to streamline the development of modular monolith applications. \
|
|
11
|
+
Rubee is a Ruby-based web framework designed to streamline the development of modular monolith web applications. \
|
|
12
|
+
Under the hood, it leverages the power of Ruby and Rack backed by Puma, offering a clean, efficient, and flexible architecture. \
|
|
12
13
|
It offers a structured approach to building scalable, maintainable, and React-ready projects, \
|
|
13
14
|
making it an ideal choice for developers seeking a balance between monolithic simplicity and modular flexibility.
|
|
14
15
|
|
|
@@ -24,8 +25,8 @@ Want to explore how it built? https://github.com/nucleom42/rubee-site
|
|
|
24
25
|
## Stress tested
|
|
25
26
|
|
|
26
27
|
```bash
|
|
27
|
-
wrk -t4 -c100 -d30s https://rubee.
|
|
28
|
-
Running 30s test @ https://rubee.
|
|
28
|
+
wrk -t4 -c100 -d30s https://rubee.dedyn.io/docs
|
|
29
|
+
Running 30s test @ https://rubee.dedyn.io/docs
|
|
29
30
|
4 threads and 100 connections
|
|
30
31
|
Thread Stats Avg Stdev Max +/- Stdev
|
|
31
32
|
Latency 304.95ms 33.22ms 551.86ms 90.38%
|
|
@@ -44,6 +45,24 @@ Transfer/sec: 140.07KB
|
|
|
44
45
|
|
|
45
46
|
This demonstrates RUBEE’s efficient architecture and suitability for lightweight deployments — even on low-power hardware.
|
|
46
47
|
|
|
48
|
+
## Comparison
|
|
49
|
+
Here below is a **short web frameworks comparison** built with Ruby, so you can evaluate your choice with RUBEE.
|
|
50
|
+
|
|
51
|
+
**Disclaimer:**
|
|
52
|
+
The comparison is based on a very generic and subjective information open in the Internet and is not a real benchmark. The comparison is aimed to give you a general idea of the differences between the frameworks and Rubee and not to compare the frameworks directly.
|
|
53
|
+
|
|
54
|
+
| Feature / Framework | **Rubee** | Rails | Sinatra | Hanami | Padrino | Grape |
|
|
55
|
+
|---------------------|-----------|-------|---------|--------|---------|-------|
|
|
56
|
+
| **React readiness** | Built-in React integration (route generator can scaffold React components that fetch data via controllers) | React via webpacker/importmap, but indirect | No direct React support | Can integrate React | Can integrate via JS pipelines | API-focused, no React support |
|
|
57
|
+
| **Routing style** | Explicit, file-based routes with clear JSON/HTML handling | DSL, routes often implicit inside controllers | Explicit DSL, inline in code | Declarative DSL | Rails-like DSL | API-oriented DSL |
|
|
58
|
+
| **Modularity** | Lightweight core, pluggable projects | One project by default, but can be extended with repsecrive gem | Very modular (small DSL) | Designed for modularity | Semi-modular, still Rails-like | Modular (mount APIs) |
|
|
59
|
+
| **Startup / Load speed** | Very fast (minimal boot time, designed for modern Ruby) | Not very fast, especially on large apps | Very fast | Medium (slower than Sinatra, faster than Rails) | Similar to Rails (heavier) | Fast |
|
|
60
|
+
| **Ecosystem** | 🌱 Early-stage, focused on modern simplicity, but easily expandable over bundler | Huge ecosystem, gems, community | Large ecosystem, many gems work | Small, growing | Small, less active | Small, niche |
|
|
61
|
+
| **Learning curve** | Simple, explicit, minimal DSL | Steep (lots of conventions & magic) | Very low (DSL fits in one file) | Medium, more concepts (repositories, entities) | Similar to Rails, easier in parts | Low (API-only) |
|
|
62
|
+
| **Customizability** | High (explicit over implicit, hooks & generators) | Limited without monkey-patching | Very high (you control flow) | High, modular architecture | Medium | High (designed for APIs) |
|
|
63
|
+
| **Target use case** | Modern full-stack apps with React frontends or APIs, may be well suite if you prefer modular monolith over microservices | Large, full-stack, mature apps | Small apps, microservices | Modular apps, DDD | Rails-like but modular | APIs & microservices |
|
|
64
|
+
| **Early adopters support** | Personal early adopters support via fast extending and fixing | Not available | Not known | Not known | Not known | Not known |
|
|
65
|
+
|
|
47
66
|
## Content
|
|
48
67
|
|
|
49
68
|
- [Installation](#installation)
|
|
@@ -64,16 +83,16 @@ This demonstrates RUBEE’s efficient architecture and suitability for lightweig
|
|
|
64
83
|
- [Modular](#modualar-application)
|
|
65
84
|
- [Logger](#logger)
|
|
66
85
|
|
|
67
|
-
You can read it on the demo [site](https://rubee.dedyn.io/)
|
|
86
|
+
You can read it on the demo: [site](https://rubee.dedyn.io/)
|
|
68
87
|
|
|
69
|
-
🚧 The doc site is on
|
|
70
|
-
Please refer to
|
|
88
|
+
🚧 The doc site is on update mode now. We are working on it.
|
|
89
|
+
Please refer to the documentation shown below.
|
|
71
90
|
|
|
72
91
|
## Features
|
|
73
92
|
|
|
74
93
|
Lightweight – A minimal footprint focused on serving Ruby applications efficiently.
|
|
75
94
|
<br>
|
|
76
|
-
Modular – A modular approach to application development. Build modular
|
|
95
|
+
Modular – A modular approach to application development. Build modular monolith app with ease by attaching
|
|
77
96
|
as many subprojects as you need.
|
|
78
97
|
<br>
|
|
79
98
|
Contract-driven – Define your API contracts in a simple, declarative way, then generate all the boilerplate you need.
|
|
@@ -148,6 +167,8 @@ rubee start_dev --jit=yjit
|
|
|
148
167
|
rubee test
|
|
149
168
|
# or you can specify specific test file
|
|
150
169
|
rubee test models/user_model_test.rb
|
|
170
|
+
# you can run specicfc line in the test file
|
|
171
|
+
rubee test models/user_model_test.rb --line=12
|
|
151
172
|
```
|
|
152
173
|
[Back to content](#content)
|
|
153
174
|
|
|
@@ -812,6 +833,29 @@ after log around
|
|
|
812
833
|
127.0.0.1 - - [17/Feb/2025:11:42:14 -0500] "GET /apples HTTP/1.1" 401 - 0.0359
|
|
813
834
|
```
|
|
814
835
|
|
|
836
|
+
Starting from ver 1.11 hooks are able to be pinned to class methods.
|
|
837
|
+
|
|
838
|
+
```ruby
|
|
839
|
+
class AnyClass
|
|
840
|
+
include Rubee::Hookable
|
|
841
|
+
before :print_world, :print_hello, class_methods: true # you can use class method as a handler
|
|
842
|
+
|
|
843
|
+
class << self
|
|
844
|
+
def print_world
|
|
845
|
+
puts "world!"
|
|
846
|
+
end
|
|
847
|
+
|
|
848
|
+
def print_hello
|
|
849
|
+
puts "hello!"
|
|
850
|
+
end
|
|
851
|
+
end
|
|
852
|
+
end
|
|
853
|
+
```
|
|
854
|
+
```bash
|
|
855
|
+
hello!
|
|
856
|
+
world!
|
|
857
|
+
```
|
|
858
|
+
|
|
815
859
|
[Back to content](#content)
|
|
816
860
|
|
|
817
861
|
## JWT based authentification
|