ru.Bee 1.10.0 → 1.11
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/cli/test.rb +57 -1
- data/lib/rubee/extensions/hookable.rb +9 -41
- data/lib/rubee.rb +1 -1
- data/lib/tests/controllers/hookable_test.rb +56 -0
- data/lib/tests/test.db +0 -0
- data/readme.md +52 -20
- 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: b13412e9ba012f30b62abd7a994f6b4ed927be61a5e8d24503b63d5fe0d2b1d1
|
4
|
+
data.tar.gz: adea3313785a63c6bbd9c502d51885c8a8325344a2b0976bfcc0e0aa3e5d5532
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d13cb1aabdd86f70109a496fecd67b135b5f364d6bb3ec7d0e1c5423b1bc5a8f73fcb127a7e3fda6a3b84b83d11d2fdc5acd19ec37a6665aae0dc260a29ac1a4
|
7
|
+
data.tar.gz: ebee546824550e812aea3e15fe19ef43d7538be4b8c6fd560d555e667e3477e55bc85d52d1bf57602d15e1439981f20f16a2c80a0a6abe6f748f0b59dbe1f568
|
data/lib/rubee/cli/test.rb
CHANGED
@@ -9,15 +9,71 @@ module Rubee
|
|
9
9
|
def test(argv)
|
10
10
|
ENV['RACK_ENV'] = 'test'
|
11
11
|
file_name = argv[1] # Get the first argument
|
12
|
+
line = argv[2]&.start_with?('--line=') ? argv[2].split('=')[1] : nil
|
12
13
|
lib = Rubee::PROJECT_NAME == 'rubee' ? '/lib' : ''
|
13
|
-
if file_name
|
14
|
+
if file_name && !line
|
14
15
|
color_puts("Running #{file_name} test ...", color: :yellow)
|
15
16
|
exec("ruby -Itest -e \"require '.#{lib}/tests/#{file_name}'\"")
|
17
|
+
elsif file_name && line
|
18
|
+
color_puts("Running #{file_name} test at line #{line} ...", color: :yellow)
|
19
|
+
test_name = find_test_at_line(".#{lib}/tests/#{file_name}", line)
|
20
|
+
exec("ruby -Itest .#{lib}/tests/#{file_name} -n #{test_name}")
|
16
21
|
else
|
17
22
|
color_puts('Running all tests ...', color: :yellow)
|
18
23
|
exec("ruby -Itest -e \"Dir.glob('.#{lib}/tests/**/*_test.rb').each { |file| require file }\"")
|
19
24
|
end
|
20
25
|
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def find_test_at_line(file, line)
|
30
|
+
source = File.read(file).lines
|
31
|
+
name = nil
|
32
|
+
kind = nil
|
33
|
+
|
34
|
+
# 1. Look backwards from the line
|
35
|
+
source[0...line.to_i].reverse_each do |l|
|
36
|
+
if l =~ /^\s*def\s+(test_\w+)/
|
37
|
+
name = ::Regexp.last_match(1)
|
38
|
+
kind = :method
|
39
|
+
break
|
40
|
+
elsif l =~ /^\s*describe\s+['"](.*)['"]/
|
41
|
+
name = ::Regexp.last_match(1)
|
42
|
+
kind = :spec
|
43
|
+
break
|
44
|
+
elsif l =~ /^\s*it\s+['"](.*)['"]/
|
45
|
+
name = ::Regexp.last_match(1)
|
46
|
+
kind = :spec
|
47
|
+
break
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# 2. If nothing was found, fallback to first def/it in the file
|
52
|
+
if name.nil?
|
53
|
+
source.each do |l|
|
54
|
+
if l =~ /^\s*def\s+(test_\w+)/
|
55
|
+
name = ::Regexp.last_match(1)
|
56
|
+
kind = :method
|
57
|
+
break
|
58
|
+
elsif l =~ /^\s*describe\s+['"](.*)['"]/
|
59
|
+
name = ::Regexp.last_match(1)
|
60
|
+
kind = :spec
|
61
|
+
break
|
62
|
+
elsif l =~ /^\s*it\s+['"](.*)['"]/
|
63
|
+
name = ::Regexp.last_match(1)
|
64
|
+
kind = :spec
|
65
|
+
break
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# 3. Return correct `-n` filter
|
71
|
+
if kind == :spec
|
72
|
+
"/#{Regexp.escape(name)}/"
|
73
|
+
else
|
74
|
+
name
|
75
|
+
end
|
76
|
+
end
|
21
77
|
end
|
22
78
|
end
|
23
79
|
end
|
@@ -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
|
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'
|
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/test.db
CHANGED
Binary file
|
data/readme.md
CHANGED
@@ -148,6 +148,8 @@ rubee start_dev --jit=yjit
|
|
148
148
|
rubee test
|
149
149
|
# or you can specify specific test file
|
150
150
|
rubee test models/user_model_test.rb
|
151
|
+
# you can run specicfc line in the test file
|
152
|
+
rubee test models/user_model_test.rb --line=12
|
151
153
|
```
|
152
154
|
[Back to content](#content)
|
153
155
|
|
@@ -164,7 +166,9 @@ rubee test models/user_model_test.rb
|
|
164
166
|
attributes: [
|
165
167
|
{ name: 'id', type: :primary },
|
166
168
|
{ name: 'colour', type: :string },
|
167
|
-
{ name: 'weight', type: :integer }
|
169
|
+
{ name: 'weight', type: :integer },
|
170
|
+
{ name: 'created', type: :datetime },
|
171
|
+
{ name: 'updated', type: :datetime },
|
168
172
|
]
|
169
173
|
}
|
170
174
|
end
|
@@ -251,7 +255,7 @@ irb(main):015> user = User.new(email: "llo@ok.com", password: 543)
|
|
251
255
|
|
252
256
|
Save record in db
|
253
257
|
```Ruby
|
254
|
-
=> #<User:0x000000010cda23b8 @email="llo@ok.com", @password=543>
|
258
|
+
=> #<User:0x000000010cda23b8 @email="llo@ok.com", @password=543, @created="2025-09-28 22:03:07.011332 -0400", @updated="2025-09-28 22:03:07.011332 -0400">
|
255
259
|
irb(main):018> user.save
|
256
260
|
=> true
|
257
261
|
```
|
@@ -259,7 +263,7 @@ irb(main):018> user.save
|
|
259
263
|
Update record with new value
|
260
264
|
```Ruby
|
261
265
|
irb(main):019> user.update(email: "update@email.com")
|
262
|
-
=> #<User:0x000000010c39b298 @email="update@email.com", @id=3, @password="543">
|
266
|
+
=> #<User:0x000000010c39b298 @email="update@email.com", @id=3, @password="543" @created="2025-09-28 22:03:07.011332 -0400", @updated="2025-09-28 22:03:07.011332 -0400">
|
263
267
|
```
|
264
268
|
|
265
269
|
Check whether it includes id
|
@@ -273,13 +277,13 @@ irb(main):016> user.persisted?
|
|
273
277
|
Get the record from the database
|
274
278
|
```Ruby
|
275
279
|
irb(main):011> user = User.last
|
276
|
-
=> #<User:0x000000010ccea178 @email="ok23@ok.com", @id=2, @password="123">
|
280
|
+
=> #<User:0x000000010ccea178 @email="ok23@ok.com", @id=2, @password="123", @created="2025-09-28 22:03:07.011332 -0400", @updated="2025-09-28 22:03:07.011332 -0400">
|
277
281
|
irb(main):012> user.email = "new@ok.com"
|
278
282
|
=> "new@ok.com"
|
279
283
|
irb(main):013> user
|
280
|
-
=> #<User:0x000000010ccea178 @email="new@ok.com", @id=2, @password="123">
|
284
|
+
=> #<User:0x000000010ccea178 @email="new@ok.com", @id=2, @password="123", @created="2025-09-28 22:03:07.011332 -0400", @updated="2025-09-28 22:03:07.011332 -0400">
|
281
285
|
irb(main):014> user.reload
|
282
|
-
=> #<User:0x000000010c488548 @email="ok23@ok.com", @id=2, @password="123"> # not persited data was updated from db
|
286
|
+
=> #<User:0x000000010c488548 @email="ok23@ok.com", @id=2, @password="123", @created="2025-09-28 22:03:07.011332 -0400", @updated="2025-09-28 22:03:07.011332 -0400"> # not persited data was updated from db
|
283
287
|
```
|
284
288
|
|
285
289
|
Assign attributes without persisiting it to db
|
@@ -297,24 +301,24 @@ irb(main):005> User.where(email: "ok23@ok.com")
|
|
297
301
|
Get all record
|
298
302
|
```Ruby
|
299
303
|
irb(main):001> User.all
|
300
|
-
=> [#<User:0x000000010c239a30 @email="ok@ok.com", @id=1, @password="password">]
|
304
|
+
=> [#<User:0x000000010c239a30 @email="ok@ok.com", @id=1, @password="password", @created="2025-09-28 22:03:07.011332 -0400", @updated="2025-09-28 22:03:07.011332 -0400">]
|
301
305
|
```
|
302
306
|
Find by id
|
303
307
|
```Ruby
|
304
308
|
irb(main):002> user = User.find 1
|
305
|
-
=> #<User:0x000000010c2f7cd8 @email="ok@ok.com", @id=1, @password="password">
|
309
|
+
=> #<User:0x000000010c2f7cd8 @email="ok@ok.com", @id=1, @password="password", @created="2025-09-28 22:03:07.011332 -0400", @updated="2025-09-28 22:03:07.011332 -0400">
|
306
310
|
```
|
307
311
|
|
308
312
|
Get last record
|
309
313
|
```Ruby
|
310
314
|
irb(main):003> User.last
|
311
|
-
=> #<User:0x000000010c2f7cd8 @email="ok@ok.com", @id=1, @password="password">
|
315
|
+
=> #<User:0x000000010c2f7cd8 @email="ok@ok.com", @id=1, @password="password", @created="2025-09-28 22:03:07.011332 -0400", @updated="2025-09-28 22:03:07.011332 -0400">
|
312
316
|
```
|
313
317
|
|
314
318
|
Create new persited record
|
315
319
|
```Ruby
|
316
320
|
irb(main):004> User.create(email: "ok23@ok.com", password: 123)
|
317
|
-
=> #<User:0x000000010c393818 @email="ok23@ok.com", @id=2, @password=123>
|
321
|
+
=> #<User:0x000000010c393818 @email="ok23@ok.com", @id=2, @password=123, @created="2025-09-28 22:03:07.011332 -0400", @updated="2025-09-28 22:03:07.011332 -0400">
|
318
322
|
```
|
319
323
|
|
320
324
|
Destroy record and all related records
|
@@ -326,7 +330,7 @@ irb(main):021> user.destroy(cascade: true)
|
|
326
330
|
Destroy all records one by one
|
327
331
|
```Ruby
|
328
332
|
irb(main):022> User.destroy_all
|
329
|
-
=> [#<User:0x000000010d42df98 @email="ok@ok.com", @id=1, @password="password">, #<User:0x000000010d42de80 @email="ok23@ok.com", @id=2, @password="123"
|
333
|
+
=> [#<User:0x000000010d42df98 @email="ok@ok.com", @id=1, @password="password", @created="2025-09-28 22:03:07.011332 -0400", @updated="2025-09-28 22:03:07.011332 -0400">, #<User:0x000000010d42de80 @email="ok23@ok.com", @id=2, @password="123", @created="2025-09-28 22:03:07.011332 -0400", @updated="2025-09-28 22:03:07.011332 -0400">>
|
330
334
|
irb(main):023> User.all
|
331
335
|
=> []
|
332
336
|
```
|
@@ -335,19 +339,19 @@ Use complex queries chains and when ready serialize it back to Rubee object.
|
|
335
339
|
```Ruby
|
336
340
|
# user model
|
337
341
|
class User < Rubee::SequelObject
|
338
|
-
attr_accessor :id, :email, :password
|
342
|
+
attr_accessor :id, :email, :password, :created, :updated
|
339
343
|
owns_many :comments, over: :posts
|
340
344
|
end
|
341
345
|
|
342
346
|
# comment model
|
343
347
|
class Comment < Rubee::SequelObject
|
344
|
-
attr_accessor :id, :text, :user_id
|
348
|
+
attr_accessor :id, :text, :user_id, :created, :updated
|
345
349
|
owns_many :users, over: :posts
|
346
350
|
end
|
347
351
|
|
348
|
-
# join post
|
352
|
+
# join post modenl
|
349
353
|
class Post < Rubee::SequelObject
|
350
|
-
attr_accessor :id, :user_id, :comment_id
|
354
|
+
attr_accessor :id, :user_id, :comment_id, :created, :updated
|
351
355
|
holds :comment
|
352
356
|
holds :user
|
353
357
|
end
|
@@ -362,11 +366,11 @@ irb(main):005> post = Post.new(user_id: user.id, comment_id: comment.id)
|
|
362
366
|
irb(main):006> post.save
|
363
367
|
=> true
|
364
368
|
irb(main):007> comment
|
365
|
-
=> #<Comment:0x000000012281a650 @id=21, @text="test">
|
369
|
+
=> #<Comment:0x000000012281a650 @id=21, @text="test", @created=2025-09-28 22:03:07.011332 -0400, @updated=2025-09-28 22:03:07.011332 -0400>
|
366
370
|
irb(main):008> result = Comment.dataset.join(:posts, comment_id: :id)
|
367
371
|
irb(main):009> .where(comment_id: Comment.where(text: "test").last.id)
|
368
372
|
irb(main):010> .then { |dataset| Comment.serialize(dataset) }
|
369
|
-
=> [#<Comment:0x0000000121889998 @id=30, @text="test", @user_id=702>]
|
373
|
+
=> [#<Comment:0x0000000121889998 @id=30, @text="test", @user_id=702, @created=2025-09-28 22:03:07.011332 -0400, @updated=2025-09-28 22:03:07.011332 -0400>]
|
370
374
|
```
|
371
375
|
This is recommended when you want to run one query and serialize it back to Rubee object only once.
|
372
376
|
So it may safe some resources.
|
@@ -432,7 +436,9 @@ Rubee::Router.draw do |router|
|
|
432
436
|
attributes: [
|
433
437
|
{ name: 'id', type: :primary },
|
434
438
|
{ name: 'colour', type: :string },
|
435
|
-
{ name: 'weight', type: :integer }
|
439
|
+
{ name: 'weight', type: :integer },
|
440
|
+
{ name: 'created', type: :datetime },
|
441
|
+
{ name: 'updated', type: :datetime },
|
436
442
|
]
|
437
443
|
}
|
438
444
|
end
|
@@ -527,7 +533,9 @@ Rubee::Router.draw do |router|
|
|
527
533
|
attributes: [
|
528
534
|
{ name: 'id', type: :primary },
|
529
535
|
{ name: 'colour', type: :string },
|
530
|
-
{ name: 'weight', type: :integer }
|
536
|
+
{ name: 'weight', type: :integer },
|
537
|
+
{ name: 'created', type: :datetime },
|
538
|
+
{ name: 'updated', type: :datetime },
|
531
539
|
]
|
532
540
|
}
|
533
541
|
end
|
@@ -571,7 +579,9 @@ Rubee::Router.draw do |router|
|
|
571
579
|
name: 'cabage',
|
572
580
|
attributes: [
|
573
581
|
{ name: 'id', type: :primary },
|
574
|
-
{ name: 'name', type: :string }
|
582
|
+
{ name: 'name', type: :string },
|
583
|
+
{ name: 'created', type: :datetime },
|
584
|
+
{ name: 'updated', type: :datetime },
|
575
585
|
]
|
576
586
|
},
|
577
587
|
namespace: :admin # mandatory option for supporting namespacing
|
@@ -804,6 +814,28 @@ after log around
|
|
804
814
|
127.0.0.1 - - [17/Feb/2025:11:42:14 -0500] "GET /apples HTTP/1.1" 401 - 0.0359
|
805
815
|
```
|
806
816
|
|
817
|
+
Starting from ver 1.11 hooks are able to be pinned to class methods.
|
818
|
+
|
819
|
+
```ruby
|
820
|
+
class AnyClass
|
821
|
+
before :print_world, :print_hello, instance_methods: true # you can useinstance method as a handler
|
822
|
+
|
823
|
+
class << self
|
824
|
+
def print_world
|
825
|
+
puts "world!"
|
826
|
+
end
|
827
|
+
|
828
|
+
def print_hello
|
829
|
+
puts "hello!"
|
830
|
+
end
|
831
|
+
end
|
832
|
+
end
|
833
|
+
```
|
834
|
+
```bash
|
835
|
+
hello!
|
836
|
+
world!
|
837
|
+
```
|
838
|
+
|
807
839
|
[Back to content](#content)
|
808
840
|
|
809
841
|
## JWT based authentification
|