rage-rb 0.1.2 → 0.3.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 +4 -4
- data/.yardopts +1 -1
- data/CHANGELOG.md +27 -0
- data/README.md +3 -3
- data/lib/rage/cli.rb +72 -2
- data/lib/rage/controller/api.rb +69 -18
- data/lib/rage/router/backend.rb +9 -6
- data/lib/rage/router/dsl.rb +44 -14
- data/lib/rage/router/handler_storage.rb +8 -2
- data/lib/rage/setup.rb +20 -4
- data/lib/rage/version.rb +1 -1
- data/lib/rage-rb.rb +5 -0
- 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: 7684c979952ee81bee165b9b667dea87199f3fa28dadadc4878b29a12211fdac
|
4
|
+
data.tar.gz: 2428443ee2456ef375990decfbf36a2952670ee517ac07cf4c994f5b9b7076f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f59da6b77e69fa2b89761b30a497b4c0fa8f02cbabeed65c953b0f5e807b349e5b305bf31564bcc3eaeed4957215766e8781af5a5b8bbd9754e0461fa18f7b87
|
7
|
+
data.tar.gz: 733a15ef91abcbfc079a3bbbb83f82686038059b3c518c1c0a279e8000ad885c65cc5019cc691e2731fa1e59ca1f62e8fe95c8f454837ed0bdc65e181157ffc7
|
data/.yardopts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
--exclude lib/rage/templates --markup markdown --no-private
|
1
|
+
--exclude lib/rage/templates --markup markdown --no-private -o doc
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.0] - 2023-10-08
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- CLI `routes` task.
|
8
|
+
- CLI `console` task.
|
9
|
+
- `:if` and `:unless` options in `before_action`.
|
10
|
+
- Allow to set response headers.
|
11
|
+
- Block version of `before_action`.
|
12
|
+
|
13
|
+
## [0.2.0] - 2023-09-27
|
14
|
+
|
15
|
+
### Added
|
16
|
+
|
17
|
+
- Gem configuration by env.
|
18
|
+
- Add `skip_before_action`.
|
19
|
+
- Add `rescue_from`.
|
20
|
+
- Add `Fiber.await`.
|
21
|
+
- Support the `defaults` route option.
|
22
|
+
|
23
|
+
### Fixed
|
24
|
+
|
25
|
+
- Ignore trailing slashes in the URLs.
|
26
|
+
- Support constraints in routes with optional params.
|
27
|
+
- Make the `root` routes helper work correctly with scopes.
|
28
|
+
- Convert objects to string when rendering text.
|
29
|
+
|
3
30
|
## [0.1.0] - 2023-09-15
|
4
31
|
|
5
32
|
- Initial release
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
<p align="center"><img height="200" src="https://github.com/rage-rb/rage/assets/2270393/
|
1
|
+
<p align="center"><img height="200" src="https://github.com/rage-rb/rage/assets/2270393/9d06e0a4-5c20-49c7-b51d-e16ce8f1e1b7" /></p>
|
2
2
|
|
3
3
|
# Rage
|
4
4
|
|
@@ -141,8 +141,8 @@ end
|
|
141
141
|
|
142
142
|
Version | Changes
|
143
143
|
------- |------------
|
144
|
-
0.2 | Gem configuration by env.<br>Add `skip_before_action`.<br>Add `rescue_from`.<br>Router updates:<br> • make the `root` helper work correctly with `scope`;<br> • support the `defaults` option
|
145
|
-
0.3 | CLI updates:<br> • `routes` task;<br> • `console` task;<br>Support the `:if` and `:unless` options in `before_action`.<br>Allow to set response headers
|
144
|
+
0.2 :white_check_mark: | ~~Gem configuration by env.<br>Add `skip_before_action`.<br>Add `rescue_from`.<br>Router updates:<br> • make the `root` helper work correctly with `scope`;<br> • support the `defaults` option;~~
|
145
|
+
0.3 :white_check_mark: | ~~CLI updates:<br> • `routes` task;<br> • `console` task;<br>Support the `:if` and `:unless` options in `before_action`.<br>Allow to set response headers.~~
|
146
146
|
0.4 | Expose the `params` object.<br>Support header authentication with `authenticate_with_http_token`.<br>Router updates:<br> • add the `resources` route helper;<br> • add the `namespace` route helper;<br> • support regexp constraints;
|
147
147
|
0.5 | Implement Iodine-based equivalent of `ActionController::Live`.<br>Use `ActionDispatch::RemoteIp`.
|
148
148
|
0.6 | Expose the `cookies` object.<br>Expose the `send_data` and `send_file` methods.<br>Support conditional get with `etag` and `last_modified`.
|
data/lib/rage/cli.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
2
|
require "thor"
|
4
3
|
require "rage"
|
4
|
+
require "irb"
|
5
5
|
|
6
6
|
module Rage
|
7
7
|
class CLI < Thor
|
@@ -25,11 +25,81 @@ module Rage
|
|
25
25
|
|
26
26
|
::Iodine.start
|
27
27
|
end
|
28
|
+
|
29
|
+
desc 'routes', 'List all routes.'
|
30
|
+
option :grep, aliases: "-g", desc: "Filter routes by pattern"
|
31
|
+
def routes
|
32
|
+
# the result would be something like this:
|
33
|
+
# Action Verb Path Controller#Action
|
34
|
+
# index GET / application#index
|
35
|
+
|
36
|
+
# load config/application.rb
|
37
|
+
environment
|
38
|
+
|
39
|
+
routes = Rage.__router.routes
|
40
|
+
|
41
|
+
pattern = options[:grep]
|
42
|
+
|
43
|
+
if pattern
|
44
|
+
routes = routes.select do |route|
|
45
|
+
route[:path].match?(pattern) || route[:raw_handler].to_s.match?(pattern) || route[:method].match?(pattern)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
return puts 'Action Verb Path Controller#Action' if routes.empty?
|
50
|
+
|
51
|
+
# construct a table
|
52
|
+
table = []
|
53
|
+
|
54
|
+
# longest_path is either the length of the longest path or 5
|
55
|
+
longest_path = routes.map { |route| route[:path].length }.max + 3
|
56
|
+
longest_path = longest_path > 5 ? longest_path : 5
|
57
|
+
|
58
|
+
longest_verb = routes.map { |route| route[:method].length }.max + 3
|
59
|
+
longest_verb = longest_verb > 4 ? longest_verb : 7
|
60
|
+
|
61
|
+
# longest_handler is either the length of the longest handler or 7, since DELETE is the longest HTTP method
|
62
|
+
longest_handler = routes.map { |route| route[:raw_handler].is_a?(Proc) ? 7 : route[:raw_handler].split('#').last.length }.max + 3
|
63
|
+
longest_handler = longest_handler > 7 ? longest_handler : 7
|
64
|
+
|
65
|
+
# longest_controller is either the length of the longest controller or 12, since Controller#{length} is the longest controller
|
66
|
+
longest_controller = routes.map { |route| route[:raw_handler].is_a?(Proc) ? 7 : route[:raw_handler].to_s.length }.max + 3
|
67
|
+
longest_controller = longest_controller > 12 ? longest_controller : 12
|
68
|
+
|
69
|
+
routes.each do |route|
|
70
|
+
table << [
|
71
|
+
format("%- #{longest_handler}s", route[:raw_handler].is_a?(Proc) ? 'Lambda' : route[:raw_handler].split('#').last),
|
72
|
+
format("%- #{longest_verb}s", route[:method]),
|
73
|
+
format("%- #{longest_path}s", route[:path]),
|
74
|
+
format("%- #{longest_controller}s", route[:raw_handler].is_a?(Proc) ? 'Lambda' : route[:raw_handler])
|
75
|
+
]
|
76
|
+
end
|
77
|
+
|
78
|
+
table.unshift([format("%- #{longest_handler}s", 'Action'), format("%- #{longest_verb}s", 'Verb'), format("%- #{longest_path}s", 'Path'),
|
79
|
+
format("%- #{longest_path}s", "Controller#Action\n")])
|
80
|
+
# print the table
|
81
|
+
table.each do |row|
|
82
|
+
# this should be changed to use the main logger when added
|
83
|
+
puts row.join
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
desc "c", "Start the app console."
|
88
|
+
def console
|
89
|
+
environment
|
90
|
+
ARGV.clear
|
91
|
+
IRB.start
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def environment
|
97
|
+
require File.expand_path("config/application.rb", Dir.pwd)
|
98
|
+
end
|
28
99
|
end
|
29
100
|
|
30
101
|
class NewAppGenerator < Thor::Group
|
31
102
|
include Thor::Actions
|
32
|
-
|
33
103
|
argument :path, type: :string
|
34
104
|
|
35
105
|
def self.source_root
|
data/lib/rage/controller/api.rb
CHANGED
@@ -12,13 +12,21 @@ class RageController::API
|
|
12
12
|
|
13
13
|
before_actions_chunk = if @__before_actions
|
14
14
|
filtered_before_actions = @__before_actions.select do |h|
|
15
|
-
(h[:only]
|
16
|
-
(h[:except]
|
15
|
+
(!h[:only] || h[:only].include?(action)) &&
|
16
|
+
(!h[:except] || !h[:except].include?(action))
|
17
17
|
end
|
18
18
|
|
19
19
|
lines = filtered_before_actions.map do |h|
|
20
|
+
condition = if h[:if] && h[:unless]
|
21
|
+
"if #{h[:if]} && !#{h[:unless]}"
|
22
|
+
elsif h[:if]
|
23
|
+
"if #{h[:if]}"
|
24
|
+
elsif h[:unless]
|
25
|
+
"unless #{h[:unless]}"
|
26
|
+
end
|
27
|
+
|
20
28
|
<<-RUBY
|
21
|
-
#{h[:name]}
|
29
|
+
#{h[:name]} #{condition}
|
22
30
|
return [@__status, @__headers, @__body] if @__rendered
|
23
31
|
RUBY
|
24
32
|
end
|
@@ -65,6 +73,16 @@ class RageController::API
|
|
65
73
|
klass.__rescue_handlers = @__rescue_handlers.freeze
|
66
74
|
end
|
67
75
|
|
76
|
+
# @private
|
77
|
+
@@__tmp_name_seed = ("a".."i").to_a.permutation
|
78
|
+
|
79
|
+
# @private
|
80
|
+
# define temporary method based on a block
|
81
|
+
def define_tmp_method(block)
|
82
|
+
name = @@__tmp_name_seed.next.join
|
83
|
+
define_method("__rage_tmp_#{name}", block)
|
84
|
+
end
|
85
|
+
|
68
86
|
############
|
69
87
|
#
|
70
88
|
# PUBLIC API
|
@@ -89,8 +107,7 @@ class RageController::API
|
|
89
107
|
def rescue_from(*klasses, with: nil, &block)
|
90
108
|
unless with
|
91
109
|
if block_given?
|
92
|
-
|
93
|
-
with = define_method("__#{name}", &block)
|
110
|
+
with = define_tmp_method(block)
|
94
111
|
else
|
95
112
|
raise "No handler provided. Pass the `with` keyword argument or provide a block."
|
96
113
|
end
|
@@ -107,21 +124,53 @@ class RageController::API
|
|
107
124
|
|
108
125
|
# Register a new `before_action` hook. Calls with the same `action_name` will overwrite the previous ones.
|
109
126
|
#
|
110
|
-
# @param action_name [String] the name of the callback to add
|
111
|
-
# @param
|
112
|
-
# @
|
127
|
+
# @param action_name [String, nil] the name of the callback to add
|
128
|
+
# @param [Hash] opts action options
|
129
|
+
# @option opts [Symbol, Array<Symbol>] :only restrict the callback to run only for specific actions
|
130
|
+
# @option opts [Symbol, Array<Symbol>] :except restrict the callback to run for all actions except specified
|
131
|
+
# @option opts [Symbol, Proc] :if only run the callback if the condition is true
|
132
|
+
# @option opts [Symbol, Proc] :unless only run the callback if the condition is false
|
113
133
|
# @example
|
114
134
|
# before_action :find_photo, only: :show
|
115
135
|
#
|
116
136
|
# def find_photo
|
117
137
|
# Photo.first
|
118
138
|
# end
|
119
|
-
|
139
|
+
# @example
|
140
|
+
# before_action :require_user, unless: :logged_in?
|
141
|
+
# @example
|
142
|
+
# before_action :set_locale, if: -> { params[:locale] != "en-US" }
|
143
|
+
# @example
|
144
|
+
# before_action do
|
145
|
+
# unless logged_in? # would be `controller.send(:logged_in?)` in Rails
|
146
|
+
# head :unauthorized
|
147
|
+
# end
|
148
|
+
# end
|
149
|
+
# @note The block form doesn't receive an argument and is executed on the controller level as if it was a regular method.
|
150
|
+
def before_action(action_name = nil, **opts, &block)
|
151
|
+
if block_given?
|
152
|
+
action_name = define_tmp_method(block)
|
153
|
+
elsif action_name.nil?
|
154
|
+
raise "No handler provided. Pass the `action_name` parameter or provide a block."
|
155
|
+
end
|
156
|
+
|
157
|
+
_only, _except, _if, _unless = opts.values_at(:only, :except, :if, :unless)
|
158
|
+
|
120
159
|
if @__before_actions && @__before_actions.frozen?
|
121
160
|
@__before_actions = @__before_actions.dup
|
122
161
|
end
|
123
162
|
|
124
|
-
action = {
|
163
|
+
action = {
|
164
|
+
name: action_name,
|
165
|
+
only: _only && Array(_only),
|
166
|
+
except: _except && Array(_except),
|
167
|
+
if: _if,
|
168
|
+
unless: _unless
|
169
|
+
}
|
170
|
+
|
171
|
+
action[:if] = define_tmp_method(action[:if]) if action[:if].is_a?(Proc)
|
172
|
+
action[:unless] = define_tmp_method(action[:unless]) if action[:unless].is_a?(Proc)
|
173
|
+
|
125
174
|
if @__before_actions.nil?
|
126
175
|
@__before_actions = [action]
|
127
176
|
elsif i = @__before_actions.find_index { |a| a[:name] == action_name }
|
@@ -192,8 +241,8 @@ class RageController::API
|
|
192
241
|
@__body << if json
|
193
242
|
json.is_a?(String) ? json : json.to_json
|
194
243
|
else
|
195
|
-
|
196
|
-
plain
|
244
|
+
headers["content-type"] = "text/plain; charset=utf-8"
|
245
|
+
plain.to_s
|
197
246
|
end
|
198
247
|
|
199
248
|
@__status = 200
|
@@ -225,11 +274,13 @@ class RageController::API
|
|
225
274
|
end
|
226
275
|
end
|
227
276
|
|
228
|
-
|
229
|
-
|
230
|
-
#
|
231
|
-
|
232
|
-
|
233
|
-
|
277
|
+
# Set response headers.
|
278
|
+
#
|
279
|
+
# @example
|
280
|
+
# headers["Content-Type"] = "application/pdf"
|
281
|
+
def headers
|
282
|
+
# copy-on-write implementation for the headers object
|
283
|
+
@__headers = {}.merge!(@__headers) if DEFAULT_HEADERS.equal?(@__headers)
|
284
|
+
@__headers
|
234
285
|
end
|
235
286
|
end
|
data/lib/rage/router/backend.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
require "uri"
|
4
4
|
|
5
5
|
class Rage::Router::Backend
|
6
|
+
attr_reader :routes
|
7
|
+
|
6
8
|
OPTIONAL_PARAM_REGEXP = /\/?\(\/?(:\w+)\/?\)/
|
7
9
|
STRING_HANDLER_REGEXP = /^([a-z0-9_\/]+)#([a-z_]+)$/
|
8
10
|
|
@@ -12,7 +14,8 @@ class Rage::Router::Backend
|
|
12
14
|
@constrainer = Rage::Router::Constrainer.new({})
|
13
15
|
end
|
14
16
|
|
15
|
-
def on(method, path, handler, constraints: {})
|
17
|
+
def on(method, path, handler, constraints: {}, defaults: nil)
|
18
|
+
raw_handler = handler
|
16
19
|
raise "Path could not be empty" if path&.empty?
|
17
20
|
|
18
21
|
if match_index = (path =~ OPTIONAL_PARAM_REGEXP)
|
@@ -21,8 +24,8 @@ class Rage::Router::Backend
|
|
21
24
|
path_full = path.sub(OPTIONAL_PARAM_REGEXP, "/#{$1}")
|
22
25
|
path_optional = path.sub(OPTIONAL_PARAM_REGEXP, "")
|
23
26
|
|
24
|
-
on(method, path_full, handler, constraints: constraints)
|
25
|
-
on(method, path_optional, handler, constraints: constraints)
|
27
|
+
on(method, path_full, handler, constraints: constraints, defaults: defaults)
|
28
|
+
on(method, path_optional, handler, constraints: constraints, defaults: defaults)
|
26
29
|
return
|
27
30
|
end
|
28
31
|
|
@@ -42,7 +45,7 @@ class Rage::Router::Backend
|
|
42
45
|
handler = ->(env, _params) { orig_handler.call(env) }
|
43
46
|
end
|
44
47
|
|
45
|
-
__on(method, path, handler, constraints)
|
48
|
+
__on(method, path, handler, raw_handler, constraints, defaults)
|
46
49
|
end
|
47
50
|
|
48
51
|
def lookup(env)
|
@@ -52,7 +55,7 @@ class Rage::Router::Backend
|
|
52
55
|
|
53
56
|
private
|
54
57
|
|
55
|
-
def __on(method, path, handler, constraints)
|
58
|
+
def __on(method, path, handler, raw_handler, constraints, defaults)
|
56
59
|
@constrainer.validate_constraints(constraints)
|
57
60
|
# Let the constrainer know if any constraints are being used now
|
58
61
|
@constrainer.note_usage(constraints)
|
@@ -159,7 +162,7 @@ class Rage::Router::Backend
|
|
159
162
|
end
|
160
163
|
end
|
161
164
|
|
162
|
-
route = { method: method, path: path, pattern: pattern, params: params, constraints: constraints, handler: handler }
|
165
|
+
route = { method: method, path: path, pattern: pattern, params: params, constraints: constraints, handler: handler, raw_handler: raw_handler, defaults: defaults }
|
163
166
|
@routes << route
|
164
167
|
current_node.add_route(route, @constrainer)
|
165
168
|
end
|
data/lib/rage/router/dsl.rb
CHANGED
@@ -16,6 +16,7 @@ class Rage::Router::DSL
|
|
16
16
|
|
17
17
|
@path_prefixes = []
|
18
18
|
@module_prefixes = []
|
19
|
+
@defaults = []
|
19
20
|
end
|
20
21
|
|
21
22
|
# Register a new GET route.
|
@@ -23,10 +24,13 @@ class Rage::Router::DSL
|
|
23
24
|
# @param path [String] the path for the route handler
|
24
25
|
# @param to [String] the route handler in the format of "controller#action"
|
25
26
|
# @param constraints [Hash] a hash of constraints for the route
|
27
|
+
# @param defaults [Hash] a hash of default parameters for the route
|
26
28
|
# @example
|
27
29
|
# get "/photos/:id", to: "photos#show", constraints: { host: /myhost/ }
|
28
|
-
|
29
|
-
|
30
|
+
# @example
|
31
|
+
# get "/photos(/:id)", to: "photos#show", defaults: { id: "-1" }
|
32
|
+
def get(path, to:, constraints: nil, defaults: nil)
|
33
|
+
__on("GET", path, to, constraints, defaults)
|
30
34
|
end
|
31
35
|
|
32
36
|
# Register a new POST route.
|
@@ -34,10 +38,13 @@ class Rage::Router::DSL
|
|
34
38
|
# @param path [String] the path for the route handler
|
35
39
|
# @param to [String] the route handler in the format of "controller#action"
|
36
40
|
# @param constraints [Hash] a hash of constraints for the route
|
41
|
+
# @param defaults [Hash] a hash of default parameters for the route
|
37
42
|
# @example
|
38
43
|
# post "/photos", to: "photos#create", constraints: { host: /myhost/ }
|
39
|
-
|
40
|
-
|
44
|
+
# @example
|
45
|
+
# post "/photos", to: "photos#create", defaults: { format: "jpg" }
|
46
|
+
def post(path, to:, constraints: nil, defaults: nil)
|
47
|
+
__on("POST", path, to, constraints, defaults)
|
41
48
|
end
|
42
49
|
|
43
50
|
# Register a new PUT route.
|
@@ -45,10 +52,13 @@ class Rage::Router::DSL
|
|
45
52
|
# @param path [String] the path for the route handler
|
46
53
|
# @param to [String] the route handler in the format of "controller#action"
|
47
54
|
# @param constraints [Hash] a hash of constraints for the route
|
55
|
+
# @param defaults [Hash] a hash of default parameters for the route
|
48
56
|
# @example
|
49
57
|
# put "/photos/:id", to: "photos#update", constraints: { host: /myhost/ }
|
50
|
-
|
51
|
-
|
58
|
+
# @example
|
59
|
+
# put "/photos(/:id)", to: "photos#update", defaults: { id: "-1" }
|
60
|
+
def put(path, to:, constraints: nil, defaults: nil)
|
61
|
+
__on("PUT", path, to, constraints, defaults)
|
52
62
|
end
|
53
63
|
|
54
64
|
# Register a new PATCH route.
|
@@ -56,10 +66,13 @@ class Rage::Router::DSL
|
|
56
66
|
# @param path [String] the path for the route handler
|
57
67
|
# @param to [String] the route handler in the format of "controller#action"
|
58
68
|
# @param constraints [Hash] a hash of constraints for the route
|
69
|
+
# @param defaults [Hash] a hash of default parameters for the route
|
59
70
|
# @example
|
60
71
|
# patch "/photos/:id", to: "photos#update", constraints: { host: /myhost/ }
|
61
|
-
|
62
|
-
|
72
|
+
# @example
|
73
|
+
# patch "/photos(/:id)", to: "photos#update", defaults: { id: "-1" }
|
74
|
+
def patch(path, to:, constraints: nil, defaults: nil)
|
75
|
+
__on("PATCH", path, to, constraints, defaults)
|
63
76
|
end
|
64
77
|
|
65
78
|
# Register a new DELETE route.
|
@@ -67,10 +80,13 @@ class Rage::Router::DSL
|
|
67
80
|
# @param path [String] the path for the route handler
|
68
81
|
# @param to [String] the route handler in the format of "controller#action"
|
69
82
|
# @param constraints [Hash] a hash of constraints for the route
|
83
|
+
# @param defaults [Hash] a hash of default parameters for the route
|
70
84
|
# @example
|
71
85
|
# delete "/photos/:id", to: "photos#destroy", constraints: { host: /myhost/ }
|
72
|
-
|
73
|
-
|
86
|
+
# @example
|
87
|
+
# delete "/photos(/:id)", to: "photos#destroy", defaults: { id: "-1" }
|
88
|
+
def delete(path, to:, constraints: nil, defaults: nil)
|
89
|
+
__on("DELETE", path, to, constraints, defaults)
|
74
90
|
end
|
75
91
|
|
76
92
|
# Register a new route pointing to '/'.
|
@@ -79,7 +95,7 @@ class Rage::Router::DSL
|
|
79
95
|
# @example
|
80
96
|
# root to: "photos#index"
|
81
97
|
def root(to:)
|
82
|
-
__on("GET", "/", to, nil)
|
98
|
+
__on("GET", "/", to, nil, nil)
|
83
99
|
end
|
84
100
|
|
85
101
|
# Scopes a set of routes to the given default options.
|
@@ -115,9 +131,22 @@ class Rage::Router::DSL
|
|
115
131
|
@module_prefixes.pop if opts[:module]
|
116
132
|
end
|
117
133
|
|
134
|
+
# Specify default parameters for a set of routes.
|
135
|
+
#
|
136
|
+
# @param defaults [Hash] a hash of default parameters
|
137
|
+
# @example
|
138
|
+
# defaults id: "-1", format: "jpg" do
|
139
|
+
# get "photos/(:id)", to: "photos#index"
|
140
|
+
# end
|
141
|
+
def defaults(defaults, &block)
|
142
|
+
@defaults << defaults
|
143
|
+
instance_eval &block
|
144
|
+
@defaults.pop
|
145
|
+
end
|
146
|
+
|
118
147
|
private
|
119
148
|
|
120
|
-
def __on(method, path, to, constraints)
|
149
|
+
def __on(method, path, to, constraints, defaults)
|
121
150
|
if path != "/"
|
122
151
|
path = "/#{path}" unless path.start_with?("/")
|
123
152
|
path = path.delete_suffix("/") if path.end_with?("/")
|
@@ -129,11 +158,12 @@ class Rage::Router::DSL
|
|
129
158
|
|
130
159
|
path_prefix = @path_prefixes.any? ? "/#{@path_prefixes.join("/")}" : nil
|
131
160
|
module_prefix = @module_prefixes.any? ? "#{@module_prefixes.join("/")}/" : nil
|
161
|
+
defaults = (defaults ? @defaults + [defaults] : @defaults).reduce(&:merge)
|
132
162
|
|
133
163
|
if to.is_a?(String)
|
134
|
-
@router.on(method, "#{path_prefix}#{path}", "#{module_prefix}#{to}", constraints: constraints || {})
|
164
|
+
@router.on(method, "#{path_prefix}#{path}", "#{module_prefix}#{to}", constraints: constraints || {}, defaults: defaults)
|
135
165
|
else
|
136
|
-
@router.on(method, "#{path_prefix}#{path}", to, constraints: constraints || {})
|
166
|
+
@router.on(method, "#{path_prefix}#{path}", to, constraints: constraints || {}, defaults: defaults)
|
137
167
|
end
|
138
168
|
end
|
139
169
|
end
|
@@ -22,7 +22,7 @@ class Rage::Router::HandlerStorage
|
|
22
22
|
params: params,
|
23
23
|
constraints: constraints,
|
24
24
|
handler: route[:handler],
|
25
|
-
create_params_object: compile_create_params_object(params)
|
25
|
+
create_params_object: compile_create_params_object(params, route[:defaults])
|
26
26
|
}
|
27
27
|
|
28
28
|
constraints_keys = constraints.keys
|
@@ -47,13 +47,19 @@ class Rage::Router::HandlerStorage
|
|
47
47
|
|
48
48
|
private
|
49
49
|
|
50
|
-
def compile_create_params_object(param_keys)
|
50
|
+
def compile_create_params_object(param_keys, defaults)
|
51
51
|
lines = []
|
52
52
|
|
53
53
|
param_keys.each_with_index do |key, i|
|
54
54
|
lines << "'#{key}' => param_values[#{i}]"
|
55
55
|
end
|
56
56
|
|
57
|
+
if defaults
|
58
|
+
defaults.except(*param_keys.map(&:to_sym)).each do |key, value|
|
59
|
+
lines << "'#{key}' => '#{value}'"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
57
63
|
eval "->(param_values) { { #{lines.join(',')} } }"
|
58
64
|
end
|
59
65
|
|
data/lib/rage/setup.rb
CHANGED
@@ -1,7 +1,23 @@
|
|
1
1
|
Iodine.patch_rack
|
2
2
|
|
3
|
-
|
3
|
+
require_relative "#{Rage.root}/config/environments/#{Rage.env}"
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
|
6
|
+
# load application files
|
7
|
+
app, bad = Dir["#{Rage.root}/app/**/*.rb"], []
|
8
|
+
|
9
|
+
loop do
|
10
|
+
path = app.shift
|
11
|
+
break if path.nil?
|
12
|
+
|
13
|
+
require_relative path
|
14
|
+
|
15
|
+
# push the file to the end of the list in case it depends on another file that has not yet been required;
|
16
|
+
# re-raise if only errored out files are left
|
17
|
+
rescue NameError
|
18
|
+
raise if (app - bad).empty?
|
19
|
+
app << path
|
20
|
+
bad << path
|
21
|
+
end
|
22
|
+
|
23
|
+
require_relative "#{Rage.root}/config/routes"
|
data/lib/rage/version.rb
CHANGED
data/lib/rage-rb.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require "rack"
|
4
4
|
require "json"
|
5
5
|
require "iodine"
|
6
|
+
require "pathname"
|
6
7
|
|
7
8
|
module Rage
|
8
9
|
def self.application
|
@@ -33,6 +34,10 @@ module Rage
|
|
33
34
|
[:default, Rage.env.to_sym]
|
34
35
|
end
|
35
36
|
|
37
|
+
def self.root
|
38
|
+
@root ||= Pathname.new(".").expand_path
|
39
|
+
end
|
40
|
+
|
36
41
|
module Router
|
37
42
|
module Strategies
|
38
43
|
end
|
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.
|
4
|
+
version: 0.3.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: 2023-
|
11
|
+
date: 2023-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|