rage-rb 1.6.0 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile +9 -7
- data/README.md +22 -8
- data/lib/rage/cli.rb +2 -1
- data/lib/rage/controller/api.rb +50 -11
- data/lib/rage/cookies.rb +5 -7
- data/lib/rage/ext/active_record/connection_pool.rb +1 -1
- data/lib/rage/fiber.rb +3 -3
- data/lib/rage/fiber_scheduler.rb +1 -1
- data/lib/rage/logger/json_formatter.rb +1 -1
- data/lib/rage/logger/logger.rb +1 -1
- data/lib/rage/logger/text_formatter.rb +1 -1
- data/lib/rage/middleware/cors.rb +2 -2
- data/lib/rage/middleware/reloader.rb +1 -1
- data/lib/rage/params_parser.rb +1 -1
- data/lib/rage/router/backend.rb +4 -6
- data/lib/rage/router/constrainer.rb +1 -1
- data/lib/rage/router/dsl.rb +6 -6
- data/lib/rage/router/dsl_plugins/legacy_hash_notation.rb +1 -1
- data/lib/rage/router/dsl_plugins/legacy_root_notation.rb +1 -1
- data/lib/rage/router/handler_storage.rb +1 -1
- data/lib/rage/setup.rb +5 -1
- data/lib/rage/sidekiq_session.rb +1 -1
- data/lib/rage/version.rb +1 -1
- data/rage.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61d3c256494b63668809f556d221c9dd86b1542ce30051c689e1f30a7b1aca00
|
4
|
+
data.tar.gz: 268fc8606e772b06985effe6918270f2ecb1c21b191bfa59ae9a74c0eeb8f459
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0136a9c93cb94dc161367ecac78b3d106404e4450fb1f4c6df8d6e38400da242fdaeebf54a7ed18ae5fc0037bea9e62ae94b5870883a2adb493e5721059a9eb8
|
7
|
+
data.tar.gz: c10509dbc8ae25ae0f1c19b35903664863fb07fb81409fd6cc16b962bde35d46f7bb552562994757b74fcc4d32f6ef9970a66f0893d0c36f11da5c27a7f2b4df
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.7.0] - 2024-07-30
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Support `wrap_parameters` by [@alex-rogachev](https://github.com/alex-rogachev) (#89).
|
8
|
+
- Unknown environment error handling by [@cuneyter](https://github.com/cuneyter) (#95).
|
9
|
+
- Allow `rescue_from` handlers to not accept arguments (#93).
|
10
|
+
|
3
11
|
## [1.6.0] - 2024-07-15
|
4
12
|
|
5
13
|
### Added
|
data/Gemfile
CHANGED
@@ -8,12 +8,14 @@ gemspec
|
|
8
8
|
gem "rake", "~> 13.0"
|
9
9
|
|
10
10
|
gem "rspec", "~> 3.0"
|
11
|
-
gem "http"
|
12
11
|
gem "yard"
|
12
|
+
gem "rubocop", "~> 1.65", require: false
|
13
13
|
|
14
|
-
|
15
|
-
gem "
|
16
|
-
gem "
|
17
|
-
|
18
|
-
gem "
|
19
|
-
gem "
|
14
|
+
group :test do
|
15
|
+
gem "http"
|
16
|
+
gem "pg"
|
17
|
+
gem "mysql2"
|
18
|
+
gem "connection_pool", "~> 2.0"
|
19
|
+
gem "rbnacl"
|
20
|
+
gem "domain_name"
|
21
|
+
end
|
data/README.md
CHANGED
@@ -15,7 +15,7 @@ Inspired by [Deno](https://deno.com) and built on top of [Iodine](https://github
|
|
15
15
|
|
16
16
|
* **API-only** - separation of concerns is one of the most fundamental principles in software development. Backend and frontend are very different layers with different goals and paths to those goals. Separating BE code from FE code results in a much more sustainable architecture compared with classic Rails monoliths.
|
17
17
|
|
18
|
-
* **Acceptance of modern Ruby** - the framework includes a fiber scheduler, which means your code never blocks while waiting on
|
18
|
+
* **Acceptance of modern Ruby** - the framework includes a fiber scheduler, which means your code never blocks while waiting on I/O.
|
19
19
|
|
20
20
|
## Installation
|
21
21
|
|
@@ -116,34 +116,48 @@ class PagesController < RageController::API
|
|
116
116
|
end
|
117
117
|
```
|
118
118
|
|
119
|
-
:information_source: **Note**: When using `Fiber.await`, it is important to wrap
|
119
|
+
:information_source: **Note**: When using `Fiber.await`, it is important to wrap every argument into a fiber using `Fiber.schedule`.
|
120
120
|
|
121
121
|
## Benchmarks
|
122
122
|
|
123
|
-
####
|
123
|
+
#### Hello World
|
124
124
|
|
125
125
|
```ruby
|
126
|
-
class
|
126
|
+
class BenchmarksController < ApplicationController
|
127
127
|
def index
|
128
128
|
render json: { hello: "world" }
|
129
129
|
end
|
130
130
|
end
|
131
131
|
```
|
132
|
-
![Requests per second](https://github.com/rage-rb/rage/assets/2270393/6c221903-e265-4c94-80e1-041f266c8f47)
|
133
132
|
|
134
|
-
|
133
|
+
![Requests per second](https://github.com/user-attachments/assets/a7f864ae-0dfb-4628-a420-265a10d8591d)
|
134
|
+
|
135
|
+
#### Waiting on I/O
|
135
136
|
|
136
137
|
```ruby
|
137
138
|
require "net/http"
|
138
139
|
|
139
|
-
class
|
140
|
+
class BenchmarksController < ApplicationController
|
140
141
|
def index
|
141
142
|
Net::HTTP.get(URI("<endpoint-that-responds-in-one-second>"))
|
142
143
|
head :ok
|
143
144
|
end
|
144
145
|
end
|
145
146
|
```
|
146
|
-
|
147
|
+
|
148
|
+
![Time to complete 100 requests](https://github.com/user-attachments/assets/4f4feda3-bd88-43d8-8999-268534c2f9de)
|
149
|
+
|
150
|
+
#### Using ActiveRecord
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
class BenchmarksController < ApplicationController
|
154
|
+
def show
|
155
|
+
render json: World.find(rand(10_000))
|
156
|
+
end
|
157
|
+
end
|
158
|
+
```
|
159
|
+
|
160
|
+
![Requests per second-2](https://github.com/user-attachments/assets/b7ee0bff-e7c8-4fd4-a565-ce0b67a6320e)
|
147
161
|
|
148
162
|
## Upcoming releases
|
149
163
|
|
data/lib/rage/cli.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "thor"
|
3
4
|
require "rack"
|
4
5
|
|
@@ -40,7 +41,7 @@ module Rage
|
|
40
41
|
::Iodine.start
|
41
42
|
end
|
42
43
|
|
43
|
-
desc
|
44
|
+
desc "routes", "List all routes."
|
44
45
|
option :grep, aliases: "-g", desc: "Filter routes by pattern"
|
45
46
|
option :help, aliases: "-h", desc: "Show this message."
|
46
47
|
def routes
|
data/lib/rage/controller/api.rb
CHANGED
@@ -7,6 +7,7 @@ class RageController::API
|
|
7
7
|
# registering means defining a new method which calls the action, makes additional calls (e.g. before actions) and
|
8
8
|
# sends a correct response down to the server;
|
9
9
|
# returns the name of the newly defined method;
|
10
|
+
# rubocop:disable Layout/IndentationWidth, Layout/EndAlignment, Layout/HeredocIndentation
|
10
11
|
def __register_action(action)
|
11
12
|
raise Rage::Errors::RouterError, "The action '#{action}' could not be found for #{self}" unless method_defined?(action)
|
12
13
|
|
@@ -65,7 +66,7 @@ class RageController::API
|
|
65
66
|
lines = @__rescue_handlers.map do |klasses, handler|
|
66
67
|
<<~RUBY
|
67
68
|
rescue #{klasses.join(", ")} => __e
|
68
|
-
#{handler}(__e)
|
69
|
+
#{instance_method(handler).arity == 0 ? handler : "#{handler}(__e)"}
|
69
70
|
[@__status, @__headers, @__body]
|
70
71
|
RUBY
|
71
72
|
end
|
@@ -77,7 +78,24 @@ class RageController::API
|
|
77
78
|
|
78
79
|
activerecord_loaded = defined?(::ActiveRecord)
|
79
80
|
|
80
|
-
|
81
|
+
wrap_parameters_chunk = if __wrap_parameters_key
|
82
|
+
<<~RUBY
|
83
|
+
wrap_key = self.class.__wrap_parameters_key
|
84
|
+
if !@__params.key?(wrap_key) && @__env["CONTENT_TYPE"]
|
85
|
+
wrap_options = self.class.__wrap_parameters_options
|
86
|
+
wrapped_params = if wrap_options[:include].any?
|
87
|
+
@__params.slice(*wrap_options[:include])
|
88
|
+
else
|
89
|
+
params_to_exclude_by_default = %i[action controller]
|
90
|
+
@__params.except(*(wrap_options[:exclude] + params_to_exclude_by_default))
|
91
|
+
end
|
92
|
+
|
93
|
+
@__params[wrap_key] = wrapped_params
|
94
|
+
end
|
95
|
+
RUBY
|
96
|
+
end
|
97
|
+
|
98
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
81
99
|
def __run_#{action}
|
82
100
|
#{if activerecord_loaded
|
83
101
|
<<~RUBY
|
@@ -85,6 +103,7 @@ class RageController::API
|
|
85
103
|
RUBY
|
86
104
|
end}
|
87
105
|
|
106
|
+
#{wrap_parameters_chunk}
|
88
107
|
#{before_actions_chunk}
|
89
108
|
#{action}
|
90
109
|
|
@@ -119,9 +138,11 @@ class RageController::API
|
|
119
138
|
end
|
120
139
|
RUBY
|
121
140
|
end
|
141
|
+
# rubocop:enable all
|
122
142
|
|
123
143
|
# @private
|
124
144
|
attr_writer :__before_actions, :__after_actions, :__rescue_handlers
|
145
|
+
attr_accessor :__wrap_parameters_key, :__wrap_parameters_options
|
125
146
|
|
126
147
|
# @private
|
127
148
|
# pass the variable down to the child; the child will continue to use it until changes need to be made;
|
@@ -130,6 +151,8 @@ class RageController::API
|
|
130
151
|
klass.__before_actions = @__before_actions.freeze
|
131
152
|
klass.__after_actions = @__after_actions.freeze
|
132
153
|
klass.__rescue_handlers = @__rescue_handlers.freeze
|
154
|
+
klass.__wrap_parameters_key = __wrap_parameters_key
|
155
|
+
klass.__wrap_parameters_options = __wrap_parameters_options
|
133
156
|
end
|
134
157
|
|
135
158
|
# @private
|
@@ -151,18 +174,17 @@ class RageController::API
|
|
151
174
|
# Register a global exception handler. Handlers are inherited and matched from bottom to top.
|
152
175
|
#
|
153
176
|
# @param klasses [Class, Array<Class>] exception classes to watch on
|
154
|
-
# @param with [Symbol] the name of a handler method.
|
177
|
+
# @param with [Symbol] the name of a handler method. Alternatively, you can pass a block.
|
155
178
|
# @example
|
156
179
|
# rescue_from User::NotAuthorized, with: :deny_access
|
157
180
|
#
|
158
|
-
# def deny_access
|
181
|
+
# def deny_access
|
159
182
|
# head :forbidden
|
160
183
|
# end
|
161
184
|
# @example
|
162
|
-
# rescue_from User::NotAuthorized do |
|
163
|
-
#
|
185
|
+
# rescue_from User::NotAuthorized do |exception|
|
186
|
+
# render json: { message: exception.message }, status: :forbidden
|
164
187
|
# end
|
165
|
-
# @note Unlike in Rails, the handler must always take an argument. Use `_` if you don't care about the actual exception.
|
166
188
|
def rescue_from(*klasses, with: nil, &block)
|
167
189
|
unless with
|
168
190
|
if block_given?
|
@@ -183,7 +205,7 @@ class RageController::API
|
|
183
205
|
|
184
206
|
# Register a new `before_action` hook. Calls with the same `action_name` will overwrite the previous ones.
|
185
207
|
#
|
186
|
-
# @param action_name [
|
208
|
+
# @param action_name [Symbol, nil] the name of the callback to add
|
187
209
|
# @param [Hash] opts action options
|
188
210
|
# @option opts [Symbol, Array<Symbol>] :only restrict the callback to run only for specific actions
|
189
211
|
# @option opts [Symbol, Array<Symbol>] :except restrict the callback to run for all actions except specified
|
@@ -215,7 +237,7 @@ class RageController::API
|
|
215
237
|
|
216
238
|
if @__before_actions.nil?
|
217
239
|
@__before_actions = [action]
|
218
|
-
elsif i = @__before_actions.find_index { |a| a[:name] == action_name }
|
240
|
+
elsif (i = @__before_actions.find_index { |a| a[:name] == action_name })
|
219
241
|
@__before_actions[i] = action
|
220
242
|
else
|
221
243
|
@__before_actions << action
|
@@ -241,7 +263,7 @@ class RageController::API
|
|
241
263
|
|
242
264
|
if @__after_actions.nil?
|
243
265
|
@__after_actions = [action]
|
244
|
-
elsif i = @__after_actions.find_index { |a| a[:name] == action_name }
|
266
|
+
elsif (i = @__after_actions.find_index { |a| a[:name] == action_name })
|
245
267
|
@__after_actions[i] = action
|
246
268
|
else
|
247
269
|
@__after_actions << action
|
@@ -277,6 +299,23 @@ class RageController::API
|
|
277
299
|
@__before_actions[i] = action
|
278
300
|
end
|
279
301
|
|
302
|
+
# Initialize controller params wrapping into a nested hash.
|
303
|
+
# If initialized, params wrapping logic will be added to the controller.
|
304
|
+
# Params get wrapped only if the CONTENT_TYPE header is present and params hash doesn't contain a param that
|
305
|
+
# has the same name as the wrapper key.
|
306
|
+
#
|
307
|
+
# @param key [Symbol] key that the wrapped params hash will nested under
|
308
|
+
# @param include [Array] array of params that should be included to the wrapped params hash
|
309
|
+
# @param exclude [Array] array of params that should be excluded from the wrapped params hash
|
310
|
+
# @example
|
311
|
+
# wrap_parameters :user, include: %i[name age]
|
312
|
+
# @example
|
313
|
+
# wrap_parameters :user, exclude: %i[address]
|
314
|
+
def wrap_parameters(key, include: [], exclude: [])
|
315
|
+
@__wrap_parameters_key = key
|
316
|
+
@__wrap_parameters_options = { include:, exclude: }
|
317
|
+
end
|
318
|
+
|
280
319
|
private
|
281
320
|
|
282
321
|
# used by `before_action` and `after_action`
|
@@ -287,7 +326,7 @@ class RageController::API
|
|
287
326
|
raise ArgumentError, "No handler provided. Pass the `action_name` parameter or provide a block."
|
288
327
|
end
|
289
328
|
|
290
|
-
|
329
|
+
_only, _except, _if, _unless = opts.values_at(:only, :except, :if, :unless)
|
291
330
|
|
292
331
|
action = {
|
293
332
|
name: action_name,
|
data/lib/rage/cookies.rb
CHANGED
@@ -97,7 +97,7 @@ class Rage::Cookies
|
|
97
97
|
return
|
98
98
|
end
|
99
99
|
|
100
|
-
if domain = value[:domain]
|
100
|
+
if (domain = value[:domain])
|
101
101
|
host = @env["HTTP_HOST"]
|
102
102
|
|
103
103
|
_domain = if domain.is_a?(String)
|
@@ -141,7 +141,7 @@ class Rage::Cookies
|
|
141
141
|
return @request_cookies if @parsed
|
142
142
|
|
143
143
|
@parsed = true
|
144
|
-
if cookie_header = @env["HTTP_COOKIE"]
|
144
|
+
if (cookie_header = @env["HTTP_COOKIE"])
|
145
145
|
cookie_header.split(/; */n).each do |cookie|
|
146
146
|
next if cookie.empty?
|
147
147
|
key, value = cookie.split("=", 2).yield_self { |k, _| [k.to_sym, _] }
|
@@ -193,7 +193,7 @@ class Rage::Cookies
|
|
193
193
|
nil
|
194
194
|
rescue RbNaCl::CryptoError
|
195
195
|
i ||= 0
|
196
|
-
if box = fallback_boxes[i]
|
196
|
+
if (box = fallback_boxes[i])
|
197
197
|
i += 1
|
198
198
|
retry
|
199
199
|
end
|
@@ -230,10 +230,8 @@ class Rage::Cookies
|
|
230
230
|
end
|
231
231
|
|
232
232
|
def fallback_boxes
|
233
|
-
@fallback_boxes ||=
|
234
|
-
|
235
|
-
RbNaCl::SimpleBox.from_secret_key(RbNaCl::Hash.blake2b(key, digest_size: 32, salt: SALT))
|
236
|
-
end
|
233
|
+
@fallback_boxes ||= Rage.config.fallback_secret_key_base.map do |key|
|
234
|
+
RbNaCl::SimpleBox.from_secret_key(RbNaCl::Hash.blake2b(key, digest_size: 32, salt: SALT))
|
237
235
|
end
|
238
236
|
end
|
239
237
|
end # class << self
|
@@ -97,7 +97,7 @@ module Rage::Ext::ActiveRecord::ConnectionPool
|
|
97
97
|
|
98
98
|
# Signal that the fiber is finished with the current connection and it can be returned to the pool.
|
99
99
|
def release_connection(owner = Fiber.current)
|
100
|
-
if conn = @__in_use.delete(owner)
|
100
|
+
if (conn = @__in_use.delete(owner))
|
101
101
|
conn.__idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
102
102
|
@__connections << conn
|
103
103
|
Iodine.publish("ext:ar-connection-released", "", Iodine::PubSub::PROCESS) if @__blocked.length > 0
|
data/lib/rage/fiber.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
##
|
4
4
|
# Rage provides a simple and efficient API to wait on several instances of IO at the same time - {Fiber.await}.
|
5
|
-
#
|
5
|
+
#
|
6
6
|
# Let's say we have the following controller:
|
7
7
|
# ```ruby
|
8
8
|
# class UsersController < RageController::API
|
@@ -34,7 +34,7 @@
|
|
34
34
|
# end
|
35
35
|
# ```
|
36
36
|
# With this change, if each request takes 1 second to execute, the total execution time will still be 1 second.
|
37
|
-
#
|
37
|
+
#
|
38
38
|
# ## Creating fibers
|
39
39
|
# Many developers see fibers as "lightweight threads" that should be used in conjunction with fiber pools, the same way we use thread pools for threads.<br>
|
40
40
|
# Instead, it makes sense to think of fibers as regular Ruby objects. We don't use a pool of arrays when we need to create an array - we create a new object and let Ruby and the GC do their job.<br>
|
@@ -68,7 +68,7 @@ class Fiber
|
|
68
68
|
@__rage_id = object_id.to_s
|
69
69
|
end
|
70
70
|
|
71
|
-
|
71
|
+
# @private
|
72
72
|
def __get_id
|
73
73
|
@__rage_id
|
74
74
|
end
|
data/lib/rage/fiber_scheduler.rb
CHANGED
@@ -66,7 +66,7 @@ class Rage::FiberScheduler
|
|
66
66
|
end
|
67
67
|
|
68
68
|
# TODO: GC works a little strange with this closure;
|
69
|
-
#
|
69
|
+
#
|
70
70
|
# def timeout_after(duration, exception_class = Timeout::Error, *exception_arguments, &block)
|
71
71
|
# fiber, block_status = Fiber.current, :running
|
72
72
|
# ::Iodine.run_after((duration * 1000).to_i) do
|
@@ -15,7 +15,7 @@ class Rage::JSONFormatter
|
|
15
15
|
context.each { |k, v| context_msg << "\"#{k}\":#{v.to_json}," }
|
16
16
|
end
|
17
17
|
|
18
|
-
if final = logger[:final]
|
18
|
+
if (final = logger[:final])
|
19
19
|
params, env = final[:params], final[:env]
|
20
20
|
if params && params[:controller]
|
21
21
|
return "{\"tags\":[\"#{tags[0]}\"],\"timestamp\":\"#{timestamp}\",\"pid\":\"#{@pid}\",\"level\":\"info\",\"method\":\"#{env["REQUEST_METHOD"]}\",\"path\":\"#{env["PATH_INFO"]}\",\"controller\":\"#{Rage::Router::Util.path_to_name(params[:controller])}\",\"action\":\"#{params[:action]}\",#{context_msg}\"status\":#{final[:response][0]},\"duration\":#{final[:duration]}}\n"
|
data/lib/rage/logger/logger.rb
CHANGED
@@ -8,7 +8,7 @@ require "logger"
|
|
8
8
|
# [fecbba0735355738] timestamp=2023-10-19T11:12:56+00:00 pid=1825 level=info message=hello
|
9
9
|
# ```
|
10
10
|
# In the log entry above, `timestamp`, `pid`, `level`, and `message` are keys, while `fecbba0735355738` is a tag.
|
11
|
-
#
|
11
|
+
#
|
12
12
|
# Use {tagged} to add custom tags to an entry:
|
13
13
|
# ```ruby
|
14
14
|
# Rage.logger.tagged("ApiCall") do
|
@@ -15,7 +15,7 @@ class Rage::TextFormatter
|
|
15
15
|
context.each { |k, v| context_msg << "#{k}=#{v} " }
|
16
16
|
end
|
17
17
|
|
18
|
-
if final = logger[:final]
|
18
|
+
if (final = logger[:final])
|
19
19
|
params, env = final[:params], final[:env]
|
20
20
|
if params && params[:controller]
|
21
21
|
return "[#{tags[0]}] timestamp=#{timestamp} pid=#{@pid} level=info method=#{env["REQUEST_METHOD"]} path=#{env["PATH_INFO"]} controller=#{Rage::Router::Util.path_to_name(params[:controller])} action=#{params[:action]} #{context_msg}status=#{final[:response][0]} duration=#{final[:duration]}\n"
|
data/lib/rage/middleware/cors.rb
CHANGED
@@ -19,7 +19,7 @@ class Rage::Cors
|
|
19
19
|
|
20
20
|
response
|
21
21
|
ensure
|
22
|
-
if !$! && origin = @cors_check.call(env)
|
22
|
+
if !$! && (origin = @cors_check.call(env))
|
23
23
|
headers = response[1]
|
24
24
|
headers["Access-Control-Allow-Origin"] = origin
|
25
25
|
if @origins != "*"
|
@@ -99,7 +99,7 @@ class Rage::Cors
|
|
99
99
|
def create_headers
|
100
100
|
headers = {
|
101
101
|
"Access-Control-Allow-Origin" => "",
|
102
|
-
"Access-Control-Allow-Methods" => @methods
|
102
|
+
"Access-Control-Allow-Methods" => @methods
|
103
103
|
}
|
104
104
|
|
105
105
|
if @allow_headers
|
data/lib/rage/params_parser.rb
CHANGED
data/lib/rage/router/backend.rb
CHANGED
@@ -51,7 +51,7 @@ class Rage::Router::Backend
|
|
51
51
|
def on(method, path, handler, constraints: {}, defaults: nil)
|
52
52
|
raise "Path could not be empty" if path&.empty?
|
53
53
|
|
54
|
-
if match_index = (path =~ OPTIONAL_PARAM_REGEXP)
|
54
|
+
if (match_index = (path =~ OPTIONAL_PARAM_REGEXP))
|
55
55
|
raise ArgumentError, "Optional Parameter has to be the last parameter of the path" if path.length != match_index + $&.length
|
56
56
|
|
57
57
|
path_full = path.sub(OPTIONAL_PARAM_REGEXP, "/#{$1}")
|
@@ -200,11 +200,9 @@ class Rage::Router::Backend
|
|
200
200
|
end
|
201
201
|
|
202
202
|
@routes.each do |existing_route|
|
203
|
-
if
|
204
|
-
|
205
|
-
|
206
|
-
existing_route[:constraints] == constraints
|
207
|
-
)
|
203
|
+
if existing_route[:method] == method &&
|
204
|
+
existing_route[:pattern] == pattern &&
|
205
|
+
existing_route[:constraints] == constraints
|
208
206
|
raise ArgumentError, "Method '#{method}' already declared for route '#{pattern}' with constraints '#{constraints.inspect}'"
|
209
207
|
end
|
210
208
|
end
|
@@ -73,7 +73,7 @@ class Rage::Router::Constrainer
|
|
73
73
|
if key == :host
|
74
74
|
lines << " host: env['HTTP_HOST'.freeze],"
|
75
75
|
else
|
76
|
-
raise ArgumentError,
|
76
|
+
raise ArgumentError, "unknown non-custom strategy for compiling constraint derivation function"
|
77
77
|
end
|
78
78
|
else
|
79
79
|
lines << " #{strategy.name}: @strategies[#{key}].derive_constraint(env),"
|
data/lib/rage/router/dsl.rb
CHANGED
@@ -213,7 +213,7 @@ class Rage::Router::DSL
|
|
213
213
|
@path_prefixes << path_prefix
|
214
214
|
@module_prefixes << module_prefix
|
215
215
|
|
216
|
-
instance_eval
|
216
|
+
instance_eval(&block)
|
217
217
|
|
218
218
|
@path_prefixes.pop
|
219
219
|
@module_prefixes.pop
|
@@ -253,7 +253,7 @@ class Rage::Router::DSL
|
|
253
253
|
@module_prefixes << opts[:module] if opts[:module]
|
254
254
|
@controllers << opts[:controller] if opts[:controller]
|
255
255
|
|
256
|
-
instance_eval
|
256
|
+
instance_eval(&block)
|
257
257
|
|
258
258
|
@path_prefixes.pop if opts[:path]
|
259
259
|
@module_prefixes.pop if opts[:module]
|
@@ -269,7 +269,7 @@ class Rage::Router::DSL
|
|
269
269
|
# end
|
270
270
|
def defaults(defaults, &block)
|
271
271
|
@defaults << defaults
|
272
|
-
instance_eval
|
272
|
+
instance_eval(&block)
|
273
273
|
@defaults.pop
|
274
274
|
end
|
275
275
|
|
@@ -282,7 +282,7 @@ class Rage::Router::DSL
|
|
282
282
|
# end
|
283
283
|
def controller(controller, &block)
|
284
284
|
@controllers << controller
|
285
|
-
instance_eval
|
285
|
+
instance_eval(&block)
|
286
286
|
@controllers.pop
|
287
287
|
end
|
288
288
|
|
@@ -297,7 +297,7 @@ class Rage::Router::DSL
|
|
297
297
|
def collection(&block)
|
298
298
|
orig_path_prefixes = @path_prefixes
|
299
299
|
@path_prefixes = @path_prefixes[0...-1] if @path_prefixes.last&.start_with?(":")
|
300
|
-
instance_eval
|
300
|
+
instance_eval(&block)
|
301
301
|
@path_prefixes = orig_path_prefixes
|
302
302
|
end
|
303
303
|
|
@@ -317,7 +317,7 @@ class Rage::Router::DSL
|
|
317
317
|
@path_prefixes = [*@path_prefixes[0...-1], ":#{member_prefix}"]
|
318
318
|
end
|
319
319
|
|
320
|
-
instance_eval
|
320
|
+
instance_eval(&block)
|
321
321
|
|
322
322
|
@path_prefixes = orig_path_prefixes
|
323
323
|
end
|
data/lib/rage/setup.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
Iodine.patch_rack
|
2
2
|
|
3
|
-
|
3
|
+
begin
|
4
|
+
require_relative "#{Rage.root}/config/environments/#{Rage.env}"
|
5
|
+
rescue LoadError
|
6
|
+
raise LoadError, "The <#{Rage.env}> environment could not be found. Please check the environment name."
|
7
|
+
end
|
4
8
|
|
5
9
|
# Run application initializers
|
6
10
|
Dir["#{Rage.root}/config/initializers/**/*.rb"].each { |initializer| load(initializer) }
|
data/lib/rage/sidekiq_session.rb
CHANGED
data/lib/rage/version.rb
CHANGED
data/rage.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
21
|
spec.files = Dir.chdir(__dir__) do
|
22
22
|
`git ls-files -z`.split("\x0").reject do |f|
|
23
|
-
(File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor])
|
23
|
+
(File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor .rubocop])
|
24
24
|
end
|
25
25
|
end
|
26
26
|
spec.bindir = "exe"
|
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: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roman Samoilov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|