Class: Rutter::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/rutter/builder.rb

Overview

The builder map URL’s to endpoints.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#flat_mapArray (readonly)

Returns Defined routes in a flat map.

Returns:

  • (Array)

    Defined routes in a flat map.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/rutter/builder.rb', line 23

class Builder
  attr_reader :flat_map
  attr_reader :verb_map
  attr_reader :named_map

  # Initializes the builder.
  #
  # @param base [String]
  #   Base URL, used for generating URLs.
  #
  # @yield
  #   Executes the block inside the created builder context.
  #
  # @return [void]
  #
  # @private
  def initialize(base: "http://localhost:9292", &block)
    @uri = URI(base).freeze
    @flat_map = []
    @verb_map = VERBS.map { |v| [v, []] }.to_h
    @named_map = {}

    instance_eval(&block) if block_given?
  end

  # Create a scoped set of routes.
  #
  # @param path [String]
  #   Scope path prefix.
  # @param namespace [String, Symbol]
  #   Scope namespace.
  # @param as [Symbol]
  #   Scope name prefix.
  #
  # @yield
  #   Block is evaluated inside the created scope context.
  #
  # @return [Rutter::Scope]
  #
  # @see Rutter::Scope
  def scope(path: nil, namespace: nil, as: nil, &block)
    Scope.new(self, path: path, namespace: namespace, as: as, &block)
  end

  # Creates a scoped collection of routes with the given name as namespace.
  #
  # @param name [Symbol, String]
  #   Scope namespace.
  #
  # @yield
  #   Scope context.
  #
  # @return [Rutter::Scope]
  #
  # @example
  #   Rutter.new do
  #     namespace :admin do
  #       get "/login", to: "sessions#new", as: :login
  #     end
  #   end
  def namespace(name, &block)
    scope path: name, namespace: name, as: name, &block
  end

  # Mount a Rack compatible at the given path prefix.
  #
  # @param app [#call]
  #   Application to mount.
  # @param at [String]
  #   Path prefix to match.
  # @param host [Regexp]
  #   Match the given host pattern.
  #
  # @return [Rutter::Mount]
  def mount(app, at:, host: nil)
    route = Mount.new(at, app, host: host)
    @flat_map << route
    VERBS.each { |verb| @verb_map[verb] << route }
    route
  end

  # Generates a path from the given arguments.
  #
  # @param name [Symbol]
  #   Name of the route to generate path from.
  #
  # @overload path(name, key: value)
  #   @param key [String, Integer, Array]
  #     Key value.
  # @overload path(name, key: value, key2: value2)
  #   @param key2 [String, Integer, Array]
  #     Key value.
  #
  # @return [String]
  #   Generated path.
  #
  # @raise [RuntimeError]
  #   If the route cannot be found.
  #
  # @see Rutter::Route#expand
  #
  # @example
  #   router = Rutter.new(base: "http://rutter.org")
  #   router.get "/login", to: "sessions#new", as: :login
  #   router.get "/books/:id", to: "books#show", as: :book
  #
  #   router.path(:login)
  #     # => "/login"
  #   router.path(:login, return_to: "/")
  #     # => "/login?return_to=/"
  #   router.path(:book, id: 82)
  #     # => "/books/82"
  def path(name, **args)
    unless (route = @named_map[name])
      raise "No route called '#{name}' was found"
    end

    route.expand(**args)
  end

  # Generates a full URL from the given arguments.
  #
  # @param name [Symbol]
  #   Name of the route to generate URL from.
  #
  # @overload expand(name, subdomain: value)
  #   @param subdomain [String, Symbol]
  #     Subdomain to be added to the host.
  # @overload expand(name, key: value)
  #   @param key [String, Integer, Array]
  #     Key value.
  # @overload expand(name, key: value, key2: value2)
  #   @param key2 [String, Integer, Array]
  #     Key value.
  #
  # @return [String]
  #   Generated URL.
  #
  # @raise [RuntimeError]
  #   If the route cannot be found.
  #
  # @see Rutter::Builder#path
  #
  # @example
  #   router = Rutter.new(base: "http://rutter.org")
  #   router.get "/login", to: "sessions#new", as: :login
  #   router.get "/books/:id", to: "books#show", as: :book
  #
  #   router.url(:login)
  #     # => "http://rutter.org/login"
  #   router.url(:login, return_to: "/")
  #     # => "http://rutter.org/login?return_to=/"
  #   router.url(:book, id: 82)
  #     # => "http://rutter.org/books/82"
  def url(name, **args)
    host = @uri.scheme + "://"
    host += "#{args.delete(:subdomain)}." if args.key?(:subdomain)
    host += @uri.host
    host += ":#{@uri.port}" if @uri.port != 80 && @uri.port != 443
    host + path(name, **args)
  end

  # Add a new, frozen, route to the map.
  #
  # @param verb [String]
  #   Request verb to match.
  # @param path [String]
  #   Path template to match.
  # @param to [#call]
  #   Rack endpoint.
  # @param as [Symbol, String]
  #   Route name/identifier.
  # @param constraints [Hash]
  #   Route segment constraints.
  # @param &block [Proc]
  #   Endpoint as a block.
  # @yieldparam env [Hash]
  #   Rack's environment hash.
  #
  # @return [Rutter::Route]
  #
  # @raise [ArgumentError]
  #   If verb is unsupported.
  # @raise [ArgumentError]
  #   If endpoint is missing.
  #
  # @private
  def add(verb, path, to: nil, as: nil, constraints: nil, &block)
    to = block if block_given?
    raise "Missing endpoint" unless to

    verb = verb.to_s.upcase

    unless VERBS.include?(verb)
      raise ArgumentError, "Unsupported verb '#{verb}'"
    end

    route = Route.new(path, to, constraints)
    @flat_map << route
    @verb_map[verb] << route
    return route unless as

    named_map[Naming.route_name(as)] = route
  end

  # Freeze the state of the router.
  #
  # @return [self]
  def freeze
    @flat_map.freeze
    @verb_map.freeze
    @verb_map.each_value(&:freeze)
    @named_map.freeze

    super
  end

  # @see #add
  VERBS.each do |verb|
    define_method verb.downcase do |path, to: nil, as: nil, constraints: nil, &block|
      add verb, path, to: to, as: as, constraints: constraints, &block
    end
  end

  # Process the request and is compatible with the Rack protocol.
  #
  # @param env [Hash]
  #   Rack environment hash.
  #
  # @return [Array]
  #   Serialized Rack response.
  #
  # @see http://rack.github.io
  #
  # @private
  def call(env)
    request_method = env["REQUEST_METHOD"]

    return NOT_FOUND_RESPONSE unless @verb_map.key?(request_method)

    routes = @verb_map[request_method]
    routes.each do |route|
      next unless route.match?(env)
      return route.call(env)
    end

    NOT_FOUND_RESPONSE
  end

  # @private
  NOT_FOUND_RESPONSE = [404, { "X-Cascade" => "pass" }, ["Not Found"]].freeze
end

#named_mapHash (readonly)

Returns Defined routes grouped by route name.

Returns:

  • (Hash)

    Defined routes grouped by route name.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/rutter/builder.rb', line 23

class Builder
  attr_reader :flat_map
  attr_reader :verb_map
  attr_reader :named_map

  # Initializes the builder.
  #
  # @param base [String]
  #   Base URL, used for generating URLs.
  #
  # @yield
  #   Executes the block inside the created builder context.
  #
  # @return [void]
  #
  # @private
  def initialize(base: "http://localhost:9292", &block)
    @uri = URI(base).freeze
    @flat_map = []
    @verb_map = VERBS.map { |v| [v, []] }.to_h
    @named_map = {}

    instance_eval(&block) if block_given?
  end

  # Create a scoped set of routes.
  #
  # @param path [String]
  #   Scope path prefix.
  # @param namespace [String, Symbol]
  #   Scope namespace.
  # @param as [Symbol]
  #   Scope name prefix.
  #
  # @yield
  #   Block is evaluated inside the created scope context.
  #
  # @return [Rutter::Scope]
  #
  # @see Rutter::Scope
  def scope(path: nil, namespace: nil, as: nil, &block)
    Scope.new(self, path: path, namespace: namespace, as: as, &block)
  end

  # Creates a scoped collection of routes with the given name as namespace.
  #
  # @param name [Symbol, String]
  #   Scope namespace.
  #
  # @yield
  #   Scope context.
  #
  # @return [Rutter::Scope]
  #
  # @example
  #   Rutter.new do
  #     namespace :admin do
  #       get "/login", to: "sessions#new", as: :login
  #     end
  #   end
  def namespace(name, &block)
    scope path: name, namespace: name, as: name, &block
  end

  # Mount a Rack compatible at the given path prefix.
  #
  # @param app [#call]
  #   Application to mount.
  # @param at [String]
  #   Path prefix to match.
  # @param host [Regexp]
  #   Match the given host pattern.
  #
  # @return [Rutter::Mount]
  def mount(app, at:, host: nil)
    route = Mount.new(at, app, host: host)
    @flat_map << route
    VERBS.each { |verb| @verb_map[verb] << route }
    route
  end

  # Generates a path from the given arguments.
  #
  # @param name [Symbol]
  #   Name of the route to generate path from.
  #
  # @overload path(name, key: value)
  #   @param key [String, Integer, Array]
  #     Key value.
  # @overload path(name, key: value, key2: value2)
  #   @param key2 [String, Integer, Array]
  #     Key value.
  #
  # @return [String]
  #   Generated path.
  #
  # @raise [RuntimeError]
  #   If the route cannot be found.
  #
  # @see Rutter::Route#expand
  #
  # @example
  #   router = Rutter.new(base: "http://rutter.org")
  #   router.get "/login", to: "sessions#new", as: :login
  #   router.get "/books/:id", to: "books#show", as: :book
  #
  #   router.path(:login)
  #     # => "/login"
  #   router.path(:login, return_to: "/")
  #     # => "/login?return_to=/"
  #   router.path(:book, id: 82)
  #     # => "/books/82"
  def path(name, **args)
    unless (route = @named_map[name])
      raise "No route called '#{name}' was found"
    end

    route.expand(**args)
  end

  # Generates a full URL from the given arguments.
  #
  # @param name [Symbol]
  #   Name of the route to generate URL from.
  #
  # @overload expand(name, subdomain: value)
  #   @param subdomain [String, Symbol]
  #     Subdomain to be added to the host.
  # @overload expand(name, key: value)
  #   @param key [String, Integer, Array]
  #     Key value.
  # @overload expand(name, key: value, key2: value2)
  #   @param key2 [String, Integer, Array]
  #     Key value.
  #
  # @return [String]
  #   Generated URL.
  #
  # @raise [RuntimeError]
  #   If the route cannot be found.
  #
  # @see Rutter::Builder#path
  #
  # @example
  #   router = Rutter.new(base: "http://rutter.org")
  #   router.get "/login", to: "sessions#new", as: :login
  #   router.get "/books/:id", to: "books#show", as: :book
  #
  #   router.url(:login)
  #     # => "http://rutter.org/login"
  #   router.url(:login, return_to: "/")
  #     # => "http://rutter.org/login?return_to=/"
  #   router.url(:book, id: 82)
  #     # => "http://rutter.org/books/82"
  def url(name, **args)
    host = @uri.scheme + "://"
    host += "#{args.delete(:subdomain)}." if args.key?(:subdomain)
    host += @uri.host
    host += ":#{@uri.port}" if @uri.port != 80 && @uri.port != 443
    host + path(name, **args)
  end

  # Add a new, frozen, route to the map.
  #
  # @param verb [String]
  #   Request verb to match.
  # @param path [String]
  #   Path template to match.
  # @param to [#call]
  #   Rack endpoint.
  # @param as [Symbol, String]
  #   Route name/identifier.
  # @param constraints [Hash]
  #   Route segment constraints.
  # @param &block [Proc]
  #   Endpoint as a block.
  # @yieldparam env [Hash]
  #   Rack's environment hash.
  #
  # @return [Rutter::Route]
  #
  # @raise [ArgumentError]
  #   If verb is unsupported.
  # @raise [ArgumentError]
  #   If endpoint is missing.
  #
  # @private
  def add(verb, path, to: nil, as: nil, constraints: nil, &block)
    to = block if block_given?
    raise "Missing endpoint" unless to

    verb = verb.to_s.upcase

    unless VERBS.include?(verb)
      raise ArgumentError, "Unsupported verb '#{verb}'"
    end

    route = Route.new(path, to, constraints)
    @flat_map << route
    @verb_map[verb] << route
    return route unless as

    named_map[Naming.route_name(as)] = route
  end

  # Freeze the state of the router.
  #
  # @return [self]
  def freeze
    @flat_map.freeze
    @verb_map.freeze
    @verb_map.each_value(&:freeze)
    @named_map.freeze

    super
  end

  # @see #add
  VERBS.each do |verb|
    define_method verb.downcase do |path, to: nil, as: nil, constraints: nil, &block|
      add verb, path, to: to, as: as, constraints: constraints, &block
    end
  end

  # Process the request and is compatible with the Rack protocol.
  #
  # @param env [Hash]
  #   Rack environment hash.
  #
  # @return [Array]
  #   Serialized Rack response.
  #
  # @see http://rack.github.io
  #
  # @private
  def call(env)
    request_method = env["REQUEST_METHOD"]

    return NOT_FOUND_RESPONSE unless @verb_map.key?(request_method)

    routes = @verb_map[request_method]
    routes.each do |route|
      next unless route.match?(env)
      return route.call(env)
    end

    NOT_FOUND_RESPONSE
  end

  # @private
  NOT_FOUND_RESPONSE = [404, { "X-Cascade" => "pass" }, ["Not Found"]].freeze
end

#verb_mapHash (readonly)

Returns Defined routes grouped by verb.

Returns:

  • (Hash)

    Defined routes grouped by verb.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/rutter/builder.rb', line 23

class Builder
  attr_reader :flat_map
  attr_reader :verb_map
  attr_reader :named_map

  # Initializes the builder.
  #
  # @param base [String]
  #   Base URL, used for generating URLs.
  #
  # @yield
  #   Executes the block inside the created builder context.
  #
  # @return [void]
  #
  # @private
  def initialize(base: "http://localhost:9292", &block)
    @uri = URI(base).freeze
    @flat_map = []
    @verb_map = VERBS.map { |v| [v, []] }.to_h
    @named_map = {}

    instance_eval(&block) if block_given?
  end

  # Create a scoped set of routes.
  #
  # @param path [String]
  #   Scope path prefix.
  # @param namespace [String, Symbol]
  #   Scope namespace.
  # @param as [Symbol]
  #   Scope name prefix.
  #
  # @yield
  #   Block is evaluated inside the created scope context.
  #
  # @return [Rutter::Scope]
  #
  # @see Rutter::Scope
  def scope(path: nil, namespace: nil, as: nil, &block)
    Scope.new(self, path: path, namespace: namespace, as: as, &block)
  end

  # Creates a scoped collection of routes with the given name as namespace.
  #
  # @param name [Symbol, String]
  #   Scope namespace.
  #
  # @yield
  #   Scope context.
  #
  # @return [Rutter::Scope]
  #
  # @example
  #   Rutter.new do
  #     namespace :admin do
  #       get "/login", to: "sessions#new", as: :login
  #     end
  #   end
  def namespace(name, &block)
    scope path: name, namespace: name, as: name, &block
  end

  # Mount a Rack compatible at the given path prefix.
  #
  # @param app [#call]
  #   Application to mount.
  # @param at [String]
  #   Path prefix to match.
  # @param host [Regexp]
  #   Match the given host pattern.
  #
  # @return [Rutter::Mount]
  def mount(app, at:, host: nil)
    route = Mount.new(at, app, host: host)
    @flat_map << route
    VERBS.each { |verb| @verb_map[verb] << route }
    route
  end

  # Generates a path from the given arguments.
  #
  # @param name [Symbol]
  #   Name of the route to generate path from.
  #
  # @overload path(name, key: value)
  #   @param key [String, Integer, Array]
  #     Key value.
  # @overload path(name, key: value, key2: value2)
  #   @param key2 [String, Integer, Array]
  #     Key value.
  #
  # @return [String]
  #   Generated path.
  #
  # @raise [RuntimeError]
  #   If the route cannot be found.
  #
  # @see Rutter::Route#expand
  #
  # @example
  #   router = Rutter.new(base: "http://rutter.org")
  #   router.get "/login", to: "sessions#new", as: :login
  #   router.get "/books/:id", to: "books#show", as: :book
  #
  #   router.path(:login)
  #     # => "/login"
  #   router.path(:login, return_to: "/")
  #     # => "/login?return_to=/"
  #   router.path(:book, id: 82)
  #     # => "/books/82"
  def path(name, **args)
    unless (route = @named_map[name])
      raise "No route called '#{name}' was found"
    end

    route.expand(**args)
  end

  # Generates a full URL from the given arguments.
  #
  # @param name [Symbol]
  #   Name of the route to generate URL from.
  #
  # @overload expand(name, subdomain: value)
  #   @param subdomain [String, Symbol]
  #     Subdomain to be added to the host.
  # @overload expand(name, key: value)
  #   @param key [String, Integer, Array]
  #     Key value.
  # @overload expand(name, key: value, key2: value2)
  #   @param key2 [String, Integer, Array]
  #     Key value.
  #
  # @return [String]
  #   Generated URL.
  #
  # @raise [RuntimeError]
  #   If the route cannot be found.
  #
  # @see Rutter::Builder#path
  #
  # @example
  #   router = Rutter.new(base: "http://rutter.org")
  #   router.get "/login", to: "sessions#new", as: :login
  #   router.get "/books/:id", to: "books#show", as: :book
  #
  #   router.url(:login)
  #     # => "http://rutter.org/login"
  #   router.url(:login, return_to: "/")
  #     # => "http://rutter.org/login?return_to=/"
  #   router.url(:book, id: 82)
  #     # => "http://rutter.org/books/82"
  def url(name, **args)
    host = @uri.scheme + "://"
    host += "#{args.delete(:subdomain)}." if args.key?(:subdomain)
    host += @uri.host
    host += ":#{@uri.port}" if @uri.port != 80 && @uri.port != 443
    host + path(name, **args)
  end

  # Add a new, frozen, route to the map.
  #
  # @param verb [String]
  #   Request verb to match.
  # @param path [String]
  #   Path template to match.
  # @param to [#call]
  #   Rack endpoint.
  # @param as [Symbol, String]
  #   Route name/identifier.
  # @param constraints [Hash]
  #   Route segment constraints.
  # @param &block [Proc]
  #   Endpoint as a block.
  # @yieldparam env [Hash]
  #   Rack's environment hash.
  #
  # @return [Rutter::Route]
  #
  # @raise [ArgumentError]
  #   If verb is unsupported.
  # @raise [ArgumentError]
  #   If endpoint is missing.
  #
  # @private
  def add(verb, path, to: nil, as: nil, constraints: nil, &block)
    to = block if block_given?
    raise "Missing endpoint" unless to

    verb = verb.to_s.upcase

    unless VERBS.include?(verb)
      raise ArgumentError, "Unsupported verb '#{verb}'"
    end

    route = Route.new(path, to, constraints)
    @flat_map << route
    @verb_map[verb] << route
    return route unless as

    named_map[Naming.route_name(as)] = route
  end

  # Freeze the state of the router.
  #
  # @return [self]
  def freeze
    @flat_map.freeze
    @verb_map.freeze
    @verb_map.each_value(&:freeze)
    @named_map.freeze

    super
  end

  # @see #add
  VERBS.each do |verb|
    define_method verb.downcase do |path, to: nil, as: nil, constraints: nil, &block|
      add verb, path, to: to, as: as, constraints: constraints, &block
    end
  end

  # Process the request and is compatible with the Rack protocol.
  #
  # @param env [Hash]
  #   Rack environment hash.
  #
  # @return [Array]
  #   Serialized Rack response.
  #
  # @see http://rack.github.io
  #
  # @private
  def call(env)
    request_method = env["REQUEST_METHOD"]

    return NOT_FOUND_RESPONSE unless @verb_map.key?(request_method)

    routes = @verb_map[request_method]
    routes.each do |route|
      next unless route.match?(env)
      return route.call(env)
    end

    NOT_FOUND_RESPONSE
  end

  # @private
  NOT_FOUND_RESPONSE = [404, { "X-Cascade" => "pass" }, ["Not Found"]].freeze
end

Instance Method Details

#freezeself

Freeze the state of the router.

Returns:

  • (self)


231
232
233
234
235
236
237
238
# File 'lib/rutter/builder.rb', line 231

def freeze
  @flat_map.freeze
  @verb_map.freeze
  @verb_map.each_value(&:freeze)
  @named_map.freeze

  super
end

#mount(app, at:, host: nil) ⇒ Rutter::Mount

Mount a Rack compatible at the given path prefix.

Parameters:

  • app (#call)

    Application to mount.

  • at (String)

    Path prefix to match.

  • host (Regexp) (defaults to: nil)

    Match the given host pattern.

Returns:

  • (Rutter::Mount)


97
98
99
100
101
102
# File 'lib/rutter/builder.rb', line 97

def mount(app, at:, host: nil)
  route = Mount.new(at, app, host: host)
  @flat_map << route
  VERBS.each { |verb| @verb_map[verb] << route }
  route
end

#namespace(name) { ... } ⇒ Rutter::Scope

Creates a scoped collection of routes with the given name as namespace.

Examples:

Rutter.new do
  namespace :admin do
    get "/login", to: "sessions#new", as: :login
  end
end

Parameters:

  • name (Symbol, String)

    Scope namespace.

Yields:

  • Scope context.

Returns:

  • (Rutter::Scope)


83
84
85
# File 'lib/rutter/builder.rb', line 83

def namespace(name, &block)
  scope path: name, namespace: name, as: name, &block
end

#path(name, key: value) ⇒ String #path(name, key: value, key2: value2) ⇒ String

Generates a path from the given arguments.

Examples:

router = Rutter.new(base: "http://rutter.org")
router.get "/login", to: "sessions#new", as: :login
router.get "/books/:id", to: "books#show", as: :book

router.path(:login)
  # => "/login"
router.path(:login, return_to: "/")
  # => "/login?return_to=/"
router.path(:book, id: 82)
  # => "/books/82"

Overloads:

  • #path(name, key: value) ⇒ String

    Parameters:

    • key (String, Integer, Array) (defaults to: value)

      Key value.

  • #path(name, key: value, key2: value2) ⇒ String

    Parameters:

    • key2 (String, Integer, Array) (defaults to: value2)

      Key value.

Parameters:

  • name (Symbol)

    Name of the route to generate path from.

Returns:

  • (String)

    Generated path.

Raises:

  • (RuntimeError)

    If the route cannot be found.

See Also:

  • Route#expand


135
136
137
138
139
140
141
# File 'lib/rutter/builder.rb', line 135

def path(name, **args)
  unless (route = @named_map[name])
    raise "No route called '#{name}' was found"
  end

  route.expand(**args)
end

#scope(path: nil, namespace: nil, as: nil) { ... } ⇒ Rutter::Scope

Create a scoped set of routes.

Parameters:

  • path (String) (defaults to: nil)

    Scope path prefix.

  • namespace (String, Symbol) (defaults to: nil)

    Scope namespace.

  • as (Symbol) (defaults to: nil)

    Scope name prefix.

Yields:

  • Block is evaluated inside the created scope context.

Returns:

  • (Rutter::Scope)

See Also:

  • Scope


63
64
65
# File 'lib/rutter/builder.rb', line 63

def scope(path: nil, namespace: nil, as: nil, &block)
  Scope.new(self, path: path, namespace: namespace, as: as, &block)
end

#expand(name, subdomain: value) ⇒ String #expand(name, key: value) ⇒ String #expand(name, key: value, key2: value2) ⇒ String

Generates a full URL from the given arguments.

Examples:

router = Rutter.new(base: "http://rutter.org")
router.get "/login", to: "sessions#new", as: :login
router.get "/books/:id", to: "books#show", as: :book

router.url(:login)
  # => "http://rutter.org/login"
router.url(:login, return_to: "/")
  # => "http://rutter.org/login?return_to=/"
router.url(:book, id: 82)
  # => "http://rutter.org/books/82"

Overloads:

  • #expand(name, subdomain: value) ⇒ String

    Parameters:

    • subdomain (String, Symbol) (defaults to: value)

      Subdomain to be added to the host.

  • #expand(name, key: value) ⇒ String

    Parameters:

    • key (String, Integer, Array) (defaults to: value)

      Key value.

  • #expand(name, key: value, key2: value2) ⇒ String

    Parameters:

    • key2 (String, Integer, Array) (defaults to: value2)

      Key value.

Parameters:

  • name (Symbol)

    Name of the route to generate URL from.

Returns:

  • (String)

    Generated URL.

Raises:

  • (RuntimeError)

    If the route cannot be found.

See Also:



177
178
179
180
181
182
183
# File 'lib/rutter/builder.rb', line 177

def url(name, **args)
  host = @uri.scheme + "://"
  host += "#{args.delete(:subdomain)}." if args.key?(:subdomain)
  host += @uri.host
  host += ":#{@uri.port}" if @uri.port != 80 && @uri.port != 443
  host + path(name, **args)
end