rage-rb 0.1.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3aacbd2e65fda6a0e7a7f7a24e67f718e55fd66bd3e0a6c6d3a1a319294be44b
4
- data.tar.gz: 40d3d2225cf40bf0f125884afd99a86b47b34f6dddce5fdeea0a9b5239fdfd0a
3
+ metadata.gz: 7684c979952ee81bee165b9b667dea87199f3fa28dadadc4878b29a12211fdac
4
+ data.tar.gz: 2428443ee2456ef375990decfbf36a2952670ee517ac07cf4c994f5b9b7076f9
5
5
  SHA512:
6
- metadata.gz: 288d8f707d78901e9c209cc3af075bcf3c37c7ef0ff4c24355702bd3898ab2e041afc5ab028e4cbe09e26a95f7297e01af03430ac6f126fd5d6cfa0b772f0e5e
7
- data.tar.gz: 5c70306e1901176e5da774dcb153e21c382359825a2527a7de97ce75772dfdf6a510ac3ffba05486b684b55634a4173596d9469306571acf58ffff274a6185c9
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/d0f0834f-50e4-4b1b-a564-1f241c4ec149" /></p>
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>&emsp;• make the `root` helper work correctly with `scope`;<br>&emsp;• support the `defaults` option;
145
- 0.3 | CLI updates:<br>&emsp;• `routes` task;<br>&emsp;• `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>&emsp;• make the `root` helper work correctly with `scope`;<br>&emsp;• support the `defaults` option;~~
145
+ 0.3 :white_check_mark: | ~~CLI updates:<br>&emsp;• `routes` task;<br>&emsp;• `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>&emsp;• add the `resources` route helper;<br>&emsp;• add the `namespace` route helper;<br>&emsp;• 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
@@ -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].nil? || h[:only].include?(action)) &&
16
- (h[:except].nil? || !h[:except].include?(action))
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
- name = ("a".."z").to_a.sample(15).join
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 only [Symbol, Array<Symbol>] restrict the callback to run only for specific actions
112
- # @param except [Symbol, Array<Symbol>] restrict the callback to run for all actions except specified
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
- def before_action(action_name, only: nil, except: nil)
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 = { name: action_name, only: only && Array(only), except: except && Array(except) }
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
- __set_header("content-type", "text/plain; charset=utf-8")
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
- private
229
-
230
- # copy-on-write implementation for the headers object
231
- def __set_header(key, value)
232
- @__headers = @__headers.dup if DEFAULT_HEADERS.equal?(@__headers)
233
- @__headers[key] = value
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
@@ -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
@@ -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
- def get(path, to:, constraints: nil)
29
- __on("GET", path, to, constraints)
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
- def post(path, to:, constraints: nil)
40
- __on("POST", path, to, constraints)
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
- def put(path, to:, constraints: nil)
51
- __on("PUT", path, to, constraints)
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
- def patch(path, to:, constraints: nil)
62
- __on("PATCH", path, to, constraints)
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
- def delete(path, to:, constraints: nil)
73
- __on("DELETE", path, to, constraints)
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
- project_root = Pathname.new(".").expand_path
3
+ require_relative "#{Rage.root}/config/environments/#{Rage.env}"
4
4
 
5
- require_relative "#{project_root}/config/environments/#{Rage.env}"
6
- Dir["#{project_root}/app/**/*.rb"].each { |path| require_relative path }
7
- require_relative "#{project_root}/config/routes"
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rage
4
- VERSION = "0.1.2"
4
+ VERSION = "0.3.0"
5
5
  end
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.1.2
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-09-25 00:00:00.000000000 Z
11
+ date: 2023-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor