rage-rb 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/Gemfile +3 -0
- data/README.md +76 -6
- data/lib/rage/application.rb +3 -1
- data/lib/rage/cli.rb +5 -4
- data/lib/rage/configuration.rb +10 -0
- data/lib/rage/controller/api.rb +122 -10
- data/lib/rage/fiber.rb +29 -0
- data/lib/rage/fiber_scheduler.rb +12 -0
- data/lib/rage/router/backend.rb +3 -2
- data/lib/rage/router/dsl.rb +5 -0
- data/lib/rage/setup.rb +1 -0
- data/lib/rage/templates/config-application.rb +3 -1
- data/lib/rage/templates/config-environments-development.rb +7 -0
- data/lib/rage/templates/config-environments-production.rb +7 -0
- data/lib/rage/templates/config-environments-test.rb +7 -0
- data/lib/rage/version.rb +1 -1
- data/lib/rage-rb.rb +17 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3aacbd2e65fda6a0e7a7f7a24e67f718e55fd66bd3e0a6c6d3a1a319294be44b
|
4
|
+
data.tar.gz: 40d3d2225cf40bf0f125884afd99a86b47b34f6dddce5fdeea0a9b5239fdfd0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 288d8f707d78901e9c209cc3af075bcf3c37c7ef0ff4c24355702bd3898ab2e041afc5ab028e4cbe09e26a95f7297e01af03430ac6f126fd5d6cfa0b772f0e5e
|
7
|
+
data.tar.gz: 5c70306e1901176e5da774dcb153e21c382359825a2527a7de97ce75772dfdf6a510ac3ffba05486b684b55634a4173596d9469306571acf58ffff274a6185c9
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--exclude lib/rage/templates --markup markdown --no-private
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
<p align="center"><img height="200" src="https://github.com/rage-rb/rage/assets/2270393/d0f0834f-50e4-4b1b-a564-1f241c4ec149" /></p>
|
2
|
+
|
1
3
|
# Rage
|
2
4
|
|
3
5
|
[![Gem Version](https://badge.fury.io/rb/rage-rb.svg)](https://badge.fury.io/rb/rage-rb)
|
@@ -5,16 +7,14 @@
|
|
5
7
|
|
6
8
|
Inspired by [Deno](https://deno.com) and built on top of [Iodine](https://github.com/rage-rb/iodine), this is a Ruby web framework that is based on the following design principles:
|
7
9
|
|
8
|
-
* **Rails compatible API** - Rails' API is clean, straightforward, and simply makes sense.
|
10
|
+
* **Rails compatible API** - Rails' API is clean, straightforward, and simply makes sense. It was one of the reasons why Rails was so successful in the past.
|
9
11
|
|
10
|
-
* **High performance** - some think performance is not a major metric for a framework, but
|
12
|
+
* **High performance** - some think performance is not a major metric for a framework, but it's not true. Poor performance is a risk, and in today's world, companies refuse to use risky technologies.
|
11
13
|
|
12
|
-
* **API-only** - the only technology we should be using to create web UI is JavaScript.
|
14
|
+
* **API-only** - the only technology we should be using to create web UI is JavaScript. Check out [Vite](https://vitejs.dev) if you don't know where to start.
|
13
15
|
|
14
16
|
* **Acceptance of modern Ruby** - the framework includes a fiber scheduler, which means your code never blocks while waiting on IO.
|
15
17
|
|
16
|
-
This framework results from reflecting on [Ruby's declining popularity](https://survey.stackoverflow.co/2023/#most-popular-technologies-language) and attempting to answer why this is happening and what we, as a community, could be doing differently.
|
17
|
-
|
18
18
|
## Installation
|
19
19
|
|
20
20
|
Install the gem:
|
@@ -40,6 +40,76 @@ $ rage s
|
|
40
40
|
|
41
41
|
Start coding!
|
42
42
|
|
43
|
+
## Getting Started
|
44
|
+
|
45
|
+
This gem is designed to be a drop-in replacement for Rails in API mode. Public API is mostly expected to match Rails, however, sometimes it's a little bit more strict.
|
46
|
+
|
47
|
+
Check out in-depth API docs for more information:
|
48
|
+
|
49
|
+
- [Controller API](https://rage-rb.github.io/rage/RageController/API.html)
|
50
|
+
- [Routing API](https://rage-rb.github.io/rage/Rage/Router/DSL/Handler.html)
|
51
|
+
- [Fiber API](https://rage-rb.github.io/rage/Fiber.html)
|
52
|
+
|
53
|
+
Also, see the [changelog](https://github.com/rage-rb/rage/blob/master/CHANGELOG.md) and [upcoming-releases](https://github.com/rage-rb/rage#upcoming-releases) for currently supported and planned features.
|
54
|
+
|
55
|
+
### Example
|
56
|
+
|
57
|
+
A sample controller could look like this:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
require "net/http"
|
61
|
+
|
62
|
+
class PagesController < RageController::API
|
63
|
+
rescue_from SocketError do |_|
|
64
|
+
render json: { message: "error" }, status: 500
|
65
|
+
end
|
66
|
+
|
67
|
+
before_action :set_metadata
|
68
|
+
|
69
|
+
def show
|
70
|
+
page = Net::HTTP.get(URI("https://httpbin.org/json"))
|
71
|
+
render json: { page: page, metadata: @metadata }
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def set_metadata
|
77
|
+
@metadata = { format: "json", time: Time.now.to_i }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
Apart from `RageController::API` as a parent class, this is mostly a regular Rails controller. However, the main difference is under the hood - Rage runs every request in a separate fiber. During the call to `Net::HTTP.get`, the fiber is automatically paused, enabling the server to process other requests. Once the HTTP request is finished, the fiber will be resumed, potentially allowing to process hundreds of requests simultaneously.
|
83
|
+
|
84
|
+
To make this controller work, we would also need to update `config/routes.rb`. In this case, the file would look the following way:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
Rage.routes.draw do
|
88
|
+
get "page", to: "pages#show"
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
:information_source: **Note**: Rage will automatically pause a fiber and continue to process other fibers on HTTP, PostgreSQL, and MySQL calls. Calls to `Thread.join` and `Ractor.join` will also automatically pause the current fiber.
|
93
|
+
|
94
|
+
Additionally, `Fiber.await` can be used to run several requests in parallel:
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
require "net/http"
|
98
|
+
|
99
|
+
class PagesController < RageController::API
|
100
|
+
def index
|
101
|
+
pages = Fiber.await(
|
102
|
+
Fiber.schedule { Net::HTTP.get(URI("https://httpbin.org/json")) },
|
103
|
+
Fiber.schedule { Net::HTTP.get(URI("https://httpbin.org/html")) },
|
104
|
+
)
|
105
|
+
|
106
|
+
render json: { pages: pages }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
:information_source: **Note**: When using `Fiber.await`, it is important to wrap any instance of IO into a fiber using `Fiber.schedule`.
|
112
|
+
|
43
113
|
## Benchmarks
|
44
114
|
|
45
115
|
#### hello world
|
@@ -51,7 +121,7 @@ class ArticlesController < ApplicationController
|
|
51
121
|
end
|
52
122
|
end
|
53
123
|
```
|
54
|
-
![Requests per second](https://github.com/rage-rb/rage/assets/2270393/
|
124
|
+
![Requests per second](https://github.com/rage-rb/rage/assets/2270393/6c221903-e265-4c94-80e1-041f266c8f47)
|
55
125
|
|
56
126
|
#### waiting on IO
|
57
127
|
|
data/lib/rage/application.rb
CHANGED
data/lib/rage/cli.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "thor"
|
4
|
-
require "
|
5
|
-
require "rack"
|
4
|
+
require "rage"
|
6
5
|
|
7
6
|
module Rage
|
8
7
|
class CLI < Thor
|
@@ -20,8 +19,10 @@ module Rage
|
|
20
19
|
app = ::Rack::Builder.parse_file("config.ru")
|
21
20
|
app = app[0] if app.is_a?(Array)
|
22
21
|
|
23
|
-
::Iodine.listen service: :http, handler: app
|
24
|
-
::Iodine.threads =
|
22
|
+
::Iodine.listen service: :http, handler: app, port: Rage.config.port
|
23
|
+
::Iodine.threads = Rage.config.threads_count
|
24
|
+
::Iodine.workers = Rage.config.workers_count
|
25
|
+
|
25
26
|
::Iodine.start
|
26
27
|
end
|
27
28
|
end
|
data/lib/rage/controller/api.rb
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
class RageController::API
|
4
4
|
class << self
|
5
|
+
# @private
|
6
|
+
# used by the router to register a new action;
|
7
|
+
# registering means defining a new method which calls the action, makes additional calls (e.g. before actions) and
|
8
|
+
# sends a correct response down to the server;
|
9
|
+
# returns the name of the newly defined method;
|
5
10
|
def __register_action(action)
|
6
11
|
raise "The action '#{action}' could not be found for #{self}" unless method_defined?(action)
|
7
12
|
|
@@ -23,37 +28,143 @@ class RageController::API
|
|
23
28
|
""
|
24
29
|
end
|
25
30
|
|
31
|
+
rescue_handlers_chunk = if @__rescue_handlers
|
32
|
+
lines = @__rescue_handlers.map do |klasses, handler|
|
33
|
+
<<-RUBY
|
34
|
+
rescue #{klasses.join(", ")} => __e
|
35
|
+
#{handler}(__e)
|
36
|
+
[@__status, @__headers, @__body]
|
37
|
+
RUBY
|
38
|
+
end
|
39
|
+
|
40
|
+
lines.join("\n")
|
41
|
+
else
|
42
|
+
""
|
43
|
+
end
|
44
|
+
|
26
45
|
class_eval <<-RUBY
|
27
46
|
def __run_#{action}
|
28
47
|
#{before_actions_chunk}
|
29
48
|
#{action}
|
30
49
|
|
31
50
|
[@__status, @__headers, @__body]
|
51
|
+
|
52
|
+
#{rescue_handlers_chunk}
|
32
53
|
end
|
33
54
|
RUBY
|
34
55
|
end
|
35
56
|
|
36
|
-
#
|
57
|
+
# @private
|
58
|
+
attr_writer :__before_actions, :__rescue_handlers
|
59
|
+
|
60
|
+
# @private
|
61
|
+
# pass the variable down to the child; the child will continue to use it until changes need to be made;
|
62
|
+
# only then the object will be copied; the frozen state communicates that the object is shared with the parent;
|
63
|
+
def inherited(klass)
|
64
|
+
klass.__before_actions = @__before_actions.freeze
|
65
|
+
klass.__rescue_handlers = @__rescue_handlers.freeze
|
66
|
+
end
|
67
|
+
|
68
|
+
############
|
69
|
+
#
|
70
|
+
# PUBLIC API
|
71
|
+
#
|
72
|
+
############
|
73
|
+
|
74
|
+
# Register a global exception handler. Handlers are inherited and matched from bottom to top.
|
75
|
+
#
|
76
|
+
# @param klasses [Class, Array<Class>] exception classes to watch on
|
77
|
+
# @param with [Symbol] the name of a handler method. The method must take one argument, which is the raised exception. Alternatively, you can pass a block, which must also take one argument.
|
78
|
+
# @example
|
79
|
+
# rescue_from User::NotAuthorized, with: :deny_access
|
80
|
+
#
|
81
|
+
# def deny_access(exception)
|
82
|
+
# head :forbidden
|
83
|
+
# end
|
84
|
+
# @example
|
85
|
+
# rescue_from User::NotAuthorized do |_|
|
86
|
+
# head :forbidden
|
87
|
+
# end
|
88
|
+
# @note Unlike Rails, the handler must always take an argument. Use `_` if you don't care about the actual exception.
|
89
|
+
def rescue_from(*klasses, with: nil, &block)
|
90
|
+
unless with
|
91
|
+
if block_given?
|
92
|
+
name = ("a".."z").to_a.sample(15).join
|
93
|
+
with = define_method("__#{name}", &block)
|
94
|
+
else
|
95
|
+
raise "No handler provided. Pass the `with` keyword argument or provide a block."
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
if @__rescue_handlers.nil?
|
100
|
+
@__rescue_handlers = []
|
101
|
+
elsif @__rescue_handlers.frozen?
|
102
|
+
@__rescue_handlers = @__rescue_handlers.dup
|
103
|
+
end
|
104
|
+
|
105
|
+
@__rescue_handlers.unshift([klasses, with])
|
106
|
+
end
|
107
|
+
|
108
|
+
# Register a new `before_action` hook. Calls with the same `action_name` will overwrite the previous ones.
|
37
109
|
#
|
38
110
|
# @param action_name [String] the name of the callback to add
|
39
111
|
# @param only [Symbol, Array<Symbol>] restrict the callback to run only for specific actions
|
40
112
|
# @param except [Symbol, Array<Symbol>] restrict the callback to run for all actions except specified
|
41
113
|
# @example
|
42
114
|
# before_action :find_photo, only: :show
|
115
|
+
#
|
43
116
|
# def find_photo
|
44
|
-
#
|
117
|
+
# Photo.first
|
45
118
|
# end
|
46
119
|
def before_action(action_name, only: nil, except: nil)
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
}
|
120
|
+
if @__before_actions && @__before_actions.frozen?
|
121
|
+
@__before_actions = @__before_actions.dup
|
122
|
+
end
|
123
|
+
|
124
|
+
action = { name: action_name, only: only && Array(only), except: except && Array(except) }
|
125
|
+
if @__before_actions.nil?
|
126
|
+
@__before_actions = [action]
|
127
|
+
elsif i = @__before_actions.find_index { |a| a[:name] == action_name }
|
128
|
+
@__before_actions[i] = action
|
129
|
+
else
|
130
|
+
@__before_actions << action
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Prevent a `before_action` hook from running.
|
135
|
+
#
|
136
|
+
# @param action_name [String] the name of the callback to skip
|
137
|
+
# @param only [Symbol, Array<Symbol>] restrict the callback to be skipped only for specific actions
|
138
|
+
# @param except [Symbol, Array<Symbol>] restrict the callback to be skipped for all actions except specified
|
139
|
+
# @example
|
140
|
+
# skip_before_action :find_photo, only: :create
|
141
|
+
def skip_before_action(action_name, only: nil, except: nil)
|
142
|
+
i = @__before_actions&.find_index { |a| a[:name] == action_name }
|
143
|
+
raise "The following action was specified to be skipped but cannot be found: #{self}##{action_name}" unless i
|
144
|
+
|
145
|
+
@__before_actions = @__before_actions.dup if @__before_actions.frozen?
|
146
|
+
|
147
|
+
if only.nil? && except.nil?
|
148
|
+
@__before_actions.delete_at(i)
|
149
|
+
return
|
150
|
+
end
|
151
|
+
|
152
|
+
action = @__before_actions[i].dup
|
153
|
+
if only
|
154
|
+
action[:except] ? action[:except] |= Array(only) : action[:except] = Array(only)
|
155
|
+
end
|
156
|
+
if except
|
157
|
+
action[:only] = Array(except)
|
158
|
+
end
|
159
|
+
|
160
|
+
@__before_actions[i] = action
|
52
161
|
end
|
53
162
|
end # class << self
|
54
163
|
|
164
|
+
# @private
|
55
165
|
DEFAULT_HEADERS = { "content-type" => "application/json; charset=utf-8" }.freeze
|
56
166
|
|
167
|
+
# @private
|
57
168
|
def initialize(env, params)
|
58
169
|
@__env = env
|
59
170
|
@__params = params
|
@@ -72,7 +183,7 @@ class RageController::API
|
|
72
183
|
# render status: :ok
|
73
184
|
# @example
|
74
185
|
# render plain: "hello world", status: 201
|
75
|
-
# @note `render` doesn't terminate execution of the action, so if you want to exit an action after rendering, you need to do something like
|
186
|
+
# @note `render` doesn't terminate execution of the action, so if you want to exit an action after rendering, you need to do something like `render(...) and return`.
|
76
187
|
def render(json: nil, plain: nil, status: nil)
|
77
188
|
raise "Render was called multiple times in this action" if @__rendered
|
78
189
|
@__rendered = true
|
@@ -81,7 +192,7 @@ class RageController::API
|
|
81
192
|
@__body << if json
|
82
193
|
json.is_a?(String) ? json : json.to_json
|
83
194
|
else
|
84
|
-
|
195
|
+
__set_header("content-type", "text/plain; charset=utf-8")
|
85
196
|
plain
|
86
197
|
end
|
87
198
|
|
@@ -116,7 +227,8 @@ class RageController::API
|
|
116
227
|
|
117
228
|
private
|
118
229
|
|
119
|
-
|
230
|
+
# copy-on-write implementation for the headers object
|
231
|
+
def __set_header(key, value)
|
120
232
|
@__headers = @__headers.dup if DEFAULT_HEADERS.equal?(@__headers)
|
121
233
|
@__headers[key] = value
|
122
234
|
end
|
data/lib/rage/fiber.rb
CHANGED
@@ -1,9 +1,38 @@
|
|
1
1
|
class Fiber
|
2
|
+
# @private
|
2
3
|
def __set_result(result)
|
3
4
|
@__result = result
|
4
5
|
end
|
5
6
|
|
7
|
+
# @private
|
6
8
|
def __get_result
|
7
9
|
@__result
|
8
10
|
end
|
11
|
+
|
12
|
+
# Wait on several fibers at the same time. Calling this method will automatically pause the current fiber, allowing the
|
13
|
+
# server to process other requests. Once all fibers have completed, the current fiber will be automatically resumed.
|
14
|
+
#
|
15
|
+
# @param fibers [Fiber, Array<Fiber>] one or several fibers to wait on. The fibers must be created using the `Fiber.schedule` call.
|
16
|
+
# @example
|
17
|
+
# Fiber.await(
|
18
|
+
# Fiber.schedule { request_1 },
|
19
|
+
# Fiber.schedule { request_2 },
|
20
|
+
# )
|
21
|
+
# @note This method should only be used when multiple fibers have to be processed in parallel. There's no need to use `Fiber.await` for single IO calls.
|
22
|
+
def self.await(*fibers)
|
23
|
+
f = Fiber.current
|
24
|
+
|
25
|
+
num_wait_for = fibers.count(&:alive?)
|
26
|
+
return fibers.map(&:__get_result) if num_wait_for == 0
|
27
|
+
|
28
|
+
Iodine.subscribe("await:#{f.object_id}") do
|
29
|
+
num_wait_for -= 1
|
30
|
+
f.resume if num_wait_for == 0
|
31
|
+
end
|
32
|
+
|
33
|
+
Fiber.yield
|
34
|
+
Iodine.defer { Iodine.unsubscribe("await:#{f.object_id}") }
|
35
|
+
|
36
|
+
fibers.map(&:__get_result)
|
37
|
+
end
|
9
38
|
end
|
data/lib/rage/fiber_scheduler.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "resolv"
|
4
|
+
|
3
5
|
class Rage::FiberScheduler
|
6
|
+
def initialize
|
7
|
+
@root_fiber = Fiber.current
|
8
|
+
end
|
9
|
+
|
4
10
|
def io_wait(io, events, timeout = nil)
|
5
11
|
f = Fiber.current
|
6
12
|
::Iodine::Scheduler.attach(io.fileno, events, timeout&.ceil || 0) { f.resume }
|
@@ -84,8 +90,14 @@ class Rage::FiberScheduler
|
|
84
90
|
end
|
85
91
|
|
86
92
|
def fiber(&block)
|
93
|
+
f = Fiber.current
|
94
|
+
inner_schedule = f != @root_fiber
|
95
|
+
|
87
96
|
fiber = Fiber.new(blocking: false) do
|
88
97
|
Fiber.current.__set_result(block.call)
|
98
|
+
ensure
|
99
|
+
# send a message for `Fiber.await` to work
|
100
|
+
Iodine.publish("await:#{f.object_id}", "") if inner_schedule
|
89
101
|
end
|
90
102
|
fiber.resume
|
91
103
|
|
data/lib/rage/router/backend.rb
CHANGED
@@ -21,8 +21,8 @@ class Rage::Router::Backend
|
|
21
21
|
path_full = path.sub(OPTIONAL_PARAM_REGEXP, "/#{$1}")
|
22
22
|
path_optional = path.sub(OPTIONAL_PARAM_REGEXP, "")
|
23
23
|
|
24
|
-
on(method, path_full, handler)
|
25
|
-
on(method, path_optional, handler)
|
24
|
+
on(method, path_full, handler, constraints: constraints)
|
25
|
+
on(method, path_optional, handler, constraints: constraints)
|
26
26
|
return
|
27
27
|
end
|
28
28
|
|
@@ -166,6 +166,7 @@ class Rage::Router::Backend
|
|
166
166
|
|
167
167
|
def find(env, derived_constraints)
|
168
168
|
method, path = env["REQUEST_METHOD"], env["PATH_INFO"]
|
169
|
+
path.delete_suffix!("/") if path.end_with?("/") && path.length > 1
|
169
170
|
|
170
171
|
current_node = @trees[method]
|
171
172
|
return nil unless current_node
|
data/lib/rage/router/dsl.rb
CHANGED
@@ -10,6 +10,7 @@ class Rage::Router::DSL
|
|
10
10
|
end
|
11
11
|
|
12
12
|
class Handler
|
13
|
+
# @private
|
13
14
|
def initialize(router)
|
14
15
|
@router = router
|
15
16
|
|
@@ -122,6 +123,10 @@ class Rage::Router::DSL
|
|
122
123
|
path = path.delete_suffix("/") if path.end_with?("/")
|
123
124
|
end
|
124
125
|
|
126
|
+
if path == "/" && @path_prefixes.any?
|
127
|
+
path = ""
|
128
|
+
end
|
129
|
+
|
125
130
|
path_prefix = @path_prefixes.any? ? "/#{@path_prefixes.join("/")}" : nil
|
126
131
|
module_prefix = @module_prefixes.any? ? "#{@module_prefixes.join("/")}/" : nil
|
127
132
|
|
data/lib/rage/setup.rb
CHANGED
data/lib/rage/version.rb
CHANGED
data/lib/rage-rb.rb
CHANGED
@@ -17,6 +17,22 @@ module Rage
|
|
17
17
|
@__router ||= Rage::Router::Backend.new
|
18
18
|
end
|
19
19
|
|
20
|
+
def self.config
|
21
|
+
@config ||= Rage::Configuration.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.configure
|
25
|
+
yield(config)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.env
|
29
|
+
@__env ||= ENV["RAGE_ENV"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.groups
|
33
|
+
[:default, Rage.env.to_sym]
|
34
|
+
end
|
35
|
+
|
20
36
|
module Router
|
21
37
|
module Strategies
|
22
38
|
end
|
@@ -29,6 +45,7 @@ end
|
|
29
45
|
require_relative "rage/application"
|
30
46
|
require_relative "rage/fiber"
|
31
47
|
require_relative "rage/fiber_scheduler"
|
48
|
+
require_relative "rage/configuration"
|
32
49
|
|
33
50
|
require_relative "rage/router/strategies/host"
|
34
51
|
require_relative "rage/router/backend"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rage-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roman Samoilov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -61,6 +61,7 @@ extensions: []
|
|
61
61
|
extra_rdoc_files: []
|
62
62
|
files:
|
63
63
|
- ".rspec"
|
64
|
+
- ".yardopts"
|
64
65
|
- CHANGELOG.md
|
65
66
|
- CODE_OF_CONDUCT.md
|
66
67
|
- Gemfile
|
@@ -72,6 +73,7 @@ files:
|
|
72
73
|
- lib/rage.rb
|
73
74
|
- lib/rage/application.rb
|
74
75
|
- lib/rage/cli.rb
|
76
|
+
- lib/rage/configuration.rb
|
75
77
|
- lib/rage/controller/api.rb
|
76
78
|
- lib/rage/fiber.rb
|
77
79
|
- lib/rage/fiber_scheduler.rb
|
@@ -86,6 +88,9 @@ files:
|
|
86
88
|
- lib/rage/templates/Gemfile
|
87
89
|
- lib/rage/templates/app-controllers-application_controller.rb
|
88
90
|
- lib/rage/templates/config-application.rb
|
91
|
+
- lib/rage/templates/config-environments-development.rb
|
92
|
+
- lib/rage/templates/config-environments-production.rb
|
93
|
+
- lib/rage/templates/config-environments-test.rb
|
89
94
|
- lib/rage/templates/config-routes.rb
|
90
95
|
- lib/rage/templates/config.ru
|
91
96
|
- lib/rage/templates/lib-.keep
|