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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d4ecb77e79daf38768a10a5da26f7f1e3013734c864774e128ffb767d5d6d9a1
4
- data.tar.gz: 1f9a6de22160db7ac4deb411278f4bb53bb94ee0a58893a9089a5eb99fd061fa
3
+ metadata.gz: 95729d36d2f3e6f133212e3d2e4e94bbb741a60f1c68a85a2caf97d060dcf782
4
+ data.tar.gz: 261f8261a80d2b62a79fa92b87c86677f6d1e7dd9ab2689d3e325bb1160914e2
5
5
  SHA512:
6
- metadata.gz: 312f2143e4244dec12bdd6e40a815eeb9a2cf70af31bea3ef2c5211ae4a491dc8532931ca4d0ef4529979d579f2c17e3ade73fd09c3f9f75a0b79697e3c93200
7
- data.tar.gz: d53621c81d31e8b7e48b030762d5f58726756e3946da14a2774fd8c6239f96ccb87a4f8d4c533b862981a792a5c90a0755d22a66d6b5b5428d4df75d46ac8265
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
@@ -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
@@ -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
- exec("rackup #{ENV['RACKUP_FILE']} -p #{port}")
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
- exec("rerun -- rackup --port #{port} #{ENV['RACKUP_FILE']}")
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
@@ -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.7.0'
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
- ruBee is a fast and lightweight Ruby application server designed for minimalism and flexibility .
12
-
13
- The main philosophy of ruBee is to focus on Ruby language explicit implementation of the MVC web application.
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
- [![Video Title](https://img.youtube.com/vi/ko7H70s7qq0/0.jpg)](https://www.youtube.com/watch?v=ko7H70s7qq0)
18
-
19
- All great features are yet to come!
20
-
21
- ## Content:
17
+ [![Watch the demo](https://img.youtube.com/vi/ko7H70s7qq0/hqdefault.jpg)](https://www.youtube.com/watch?v=ko7H70s7qq0)
18
+ ## Content
22
19
 
23
- - [Installation](#Installation)
20
+ - [Installation](#installation)
24
21
  - [Run tests](#run-tests)
25
22
  - [Draw contract](#draw-contract)
26
- - [Model](#Model)
27
- - [Routing](#Routing)
28
- - [Database](#Database)
29
- - [Views](#Views)
30
- - [Hooks](#Hooks)
31
- - [JWT based authentification](#JWT-based-authentification)
32
- - [Rubee commands](#Rubee-commands)
33
- - [Generate commands](#Generate-commands)
34
- - [Migration commands](#Migration-commands)
35
- - [Rubee console](#Rubee-console)
36
- - [Testing](#Testing)
37
- - [Background jobs](#Background-jobs)
38
- - [Modular](#Modular application)
39
- - [Logger](#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
- - **Lightweight**: A minimal footprint that focuses on serving Ruby applications efficiently.
44
- - **Moduled** A modular approach to application development. Build modular monolith applications with ease by \
45
- attaching as many subprojects you need.
46
- - **Contract driven**: Define your API contracts in a simple, declarative manner.\
47
- Then generate the biolerplate files you need.
48
- - **Fast**: Optimized for speed, providing a quick response to requests. Everything is relative, I know!
49
- - **Rack**: Rack backed. All Rack api is available for integration.
50
- - **Databases**: Sqlite3, Postgres, Mysql and many more supported by sequel gem.
51
- - **Views**: Json, ERB and plain HTML and ..
52
- - **React** is supported out of the box as a rubee view
53
- - **Bundlable** Charge your ruBee with any gem you need and update your project with bundle.
54
- - **ORM** All models are natively ORM objects, however you can use it as a blueurpint for any datasources.
55
- - **Authentificatable** Add JWT authentification easily to any controller action.
56
- - **Hooks** Add logic before, after and around any action.
57
- - **Test** Run all or selected tests witin fast and beloved minitest.
58
- - **Asyncable** Add async adapter and pick any popular background job queue enginee
59
- - **Console** Start the interactive console and reload it on the fly
60
- - **Background jobs** Add async adapter and pick any popular background job queue engine
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+) is installed
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
- - [Back to content](#Content)
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
- ```bash
152
+ ```bash
132
153
  rubee db run:all
133
- ```
154
+ ```
134
155
 
135
- 5. Fill the generated files with the logic you need and run the server again!
136
- - [Back to content](#Content)
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
- #### Rubee::SequelObject base methods:
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
- - [Back to content](#Content)
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. You can also add any matched parameter denoted by a pair of `{ }` in the path of the route. Eg. `/path/to/{a_key}/somewhere`
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
- `route.http_method path, to: "controller#action", model { ...optional }`
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. You've seen above one possible way you can set up.
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 keys supported by us and Sequel to help generate your initial db files. Other supported attribute key types are:
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: 'key1', type: :primary},
362
- { name: 'key2', type: :string },
363
- { name: 'key3', type: :text },
364
- { name: 'key4', type: :integer },
365
- { name: 'key5', type: :date },
366
- { name: 'key6', type: :datetime },
367
- { name: 'key7', type: :time },
368
- { name: 'key8', type: :boolean },
369
- { name: 'key9', type: :bigint },
370
- { name: 'key10', type: :decimal },
371
- { name: 'key11', type: :foreign_key },
372
- { name: 'key12', type: :index },
373
- { name: 'key13', type: :unique }
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 [Sequel schema definition](https://github.com/jeremyevans/sequel/blob/master/doc/schema_modification.rdoc).
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
- `{name: 'key', type: :string, options: { size: 50, fixed: true } }`
430
+ ```ruby
431
+ {name: 'key', type: :string, options: { size: 50, fixed: true } }
432
+ ```
380
433
 
381
434
  Gets translated to:\
382
- `String :key, size: 50, fixed: true`
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 you can use it to generate your initial model files. If only a `path` and a `to:` are defined will only generate a controller and a corresponding view.
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
- `rubee generate get /apples` or `rubee gen get /apples`\
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
- `rubee generate patch /apples/{id}` or `rubee gen patch /apples/{id}`
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
- router.get '/admin/cabages', to: 'cabages#index',
474
- model: {
475
- name: 'cabage',
476
- attributes: [
477
- { name: 'id', type: :primary },
478
- { name: 'name', type: :string }
479
- ]
480
- },
481
- namespace: :admin # mandatory option for supporting namespacing
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
- - [Back to content](#Content)
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
- - [Back to content](#Content)
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
- - [Back to content](#Content)
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
- - [Back to content](#Content)
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
- - [Back to content](#Content)
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
- - [Back to content](#Content)
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.7.0
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.2.1
294
+ version: 3.4.1
294
295
  required_rubygems_version: !ruby/object:Gem::Requirement
295
296
  requirements:
296
297
  - - ">="