merb-core 0.9.8 → 0.9.9
Sign up to get free protection for your applications and to get access to all the features.
- data/CONTRIBUTORS +33 -0
- data/README +7 -3
- data/Rakefile +3 -3
- data/lib/merb-core.rb +165 -94
- data/lib/merb-core/bootloader.rb +469 -100
- data/lib/merb-core/config.rb +79 -3
- data/lib/merb-core/constants.rb +24 -2
- data/lib/merb-core/controller/abstract_controller.rb +172 -67
- data/lib/merb-core/controller/exceptions.rb +50 -6
- data/lib/merb-core/controller/merb_controller.rb +215 -108
- data/lib/merb-core/controller/mime.rb +36 -12
- data/lib/merb-core/controller/mixins/authentication.rb +52 -7
- data/lib/merb-core/controller/mixins/conditional_get.rb +14 -0
- data/lib/merb-core/controller/mixins/controller.rb +90 -58
- data/lib/merb-core/controller/mixins/render.rb +34 -10
- data/lib/merb-core/controller/mixins/responder.rb +40 -16
- data/lib/merb-core/controller/template.rb +37 -16
- data/lib/merb-core/core_ext/hash.rb +9 -0
- data/lib/merb-core/core_ext/kernel.rb +92 -41
- data/lib/merb-core/dispatch/dispatcher.rb +29 -45
- data/lib/merb-core/dispatch/request.rb +186 -82
- data/lib/merb-core/dispatch/router.rb +141 -53
- data/lib/merb-core/dispatch/router/behavior.rb +296 -139
- data/lib/merb-core/dispatch/router/resources.rb +51 -19
- data/lib/merb-core/dispatch/router/route.rb +76 -23
- data/lib/merb-core/dispatch/session.rb +80 -36
- data/lib/merb-core/dispatch/session/container.rb +31 -15
- data/lib/merb-core/dispatch/session/cookie.rb +51 -22
- data/lib/merb-core/dispatch/session/memcached.rb +10 -6
- data/lib/merb-core/dispatch/session/memory.rb +17 -5
- data/lib/merb-core/dispatch/session/store_container.rb +21 -9
- data/lib/merb-core/dispatch/worker.rb +16 -2
- data/lib/merb-core/gem_ext/erubis.rb +4 -0
- data/lib/merb-core/plugins.rb +13 -0
- data/lib/merb-core/rack.rb +1 -0
- data/lib/merb-core/rack/adapter.rb +1 -0
- data/lib/merb-core/rack/adapter/abstract.rb +95 -17
- data/lib/merb-core/rack/adapter/irb.rb +50 -5
- data/lib/merb-core/rack/application.rb +27 -5
- data/lib/merb-core/rack/handler/mongrel.rb +6 -6
- data/lib/merb-core/rack/helpers.rb +33 -0
- data/lib/merb-core/rack/middleware/conditional_get.rb +1 -1
- data/lib/merb-core/rack/middleware/path_prefix.rb +3 -3
- data/lib/merb-core/rack/middleware/static.rb +11 -7
- data/lib/merb-core/server.rb +134 -69
- data/lib/merb-core/tasks/gem_management.rb +153 -80
- data/lib/merb-core/tasks/merb_rake_helper.rb +12 -4
- data/lib/merb-core/tasks/stats.rake +1 -1
- data/lib/merb-core/test/helpers/mock_request_helper.rb +29 -22
- data/lib/merb-core/test/helpers/request_helper.rb +1 -1
- data/lib/merb-core/test/helpers/route_helper.rb +50 -4
- data/lib/merb-core/test/matchers/request_matchers.rb +2 -36
- data/lib/merb-core/test/matchers/view_matchers.rb +32 -22
- data/lib/merb-core/test/run_specs.rb +6 -5
- data/lib/merb-core/test/test_ext/rspec.rb +6 -19
- data/lib/merb-core/version.rb +1 -1
- metadata +5 -4
@@ -6,19 +6,19 @@ require 'merb-core/dispatch/router/route'
|
|
6
6
|
module Merb
|
7
7
|
# Router stores route definitions and finds the first
|
8
8
|
# route that matches the incoming request URL.
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# Then information from route is used by dispatcher to
|
11
11
|
# call action on the controller.
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# ==== Routes compilation.
|
14
|
-
#
|
14
|
+
#
|
15
15
|
# The most interesting method of Router (and heart of
|
16
16
|
# route matching machinery) is match method generated
|
17
17
|
# on the fly from routes definitions. It is called routes
|
18
18
|
# compilation. Generated match method body contains
|
19
19
|
# one if/elsif statement that picks the first matching route
|
20
20
|
# definition and sets values to named parameters of the route.
|
21
|
-
#
|
21
|
+
#
|
22
22
|
# Compilation is synchronized by mutex.
|
23
23
|
class Router
|
24
24
|
@routes = []
|
@@ -26,14 +26,14 @@ module Merb
|
|
26
26
|
@resource_routes = {}
|
27
27
|
@compiler_mutex = Mutex.new
|
28
28
|
@root_behavior = Behavior.new.defaults(:action => "index")
|
29
|
-
|
29
|
+
|
30
30
|
# Raised when route lookup fails.
|
31
31
|
class RouteNotFound < StandardError; end;
|
32
32
|
# Raised when parameters given to generation
|
33
33
|
# method do not match route parameters.
|
34
34
|
class GenerationError < StandardError; end;
|
35
35
|
class NotCompiledError < StandardError; end;
|
36
|
-
|
36
|
+
|
37
37
|
class << self
|
38
38
|
# @private
|
39
39
|
attr_accessor :routes, :named_routes, :resource_routes, :root_behavior
|
@@ -41,19 +41,20 @@ module Merb
|
|
41
41
|
# Creates a route building context and evaluates the block in it. A
|
42
42
|
# copy of +root_behavior+ (and instance of Behavior) is copied as
|
43
43
|
# the context.
|
44
|
-
#
|
44
|
+
#
|
45
45
|
# ==== Parameters
|
46
46
|
# first<Array>::
|
47
47
|
# An array containing routes that should be prepended to the routes
|
48
48
|
# defined in the block.
|
49
|
-
#
|
50
49
|
# last<Array>::
|
51
50
|
# An array containing routes that should be appended to the routes
|
52
51
|
# defined in the block.
|
53
|
-
#
|
52
|
+
#
|
54
53
|
# ==== Returns
|
55
54
|
# Merb::Router::
|
56
55
|
# Returns self to allow chaining of methods.
|
56
|
+
#
|
57
|
+
# @api public
|
57
58
|
def prepare(first = [], last = [], &block)
|
58
59
|
@routes = []
|
59
60
|
root_behavior._with_proxy(&block)
|
@@ -63,17 +64,23 @@ module Merb
|
|
63
64
|
end
|
64
65
|
|
65
66
|
# Appends route in the block to routing table.
|
67
|
+
#
|
68
|
+
# @api public
|
66
69
|
def append(&block)
|
67
70
|
prepare(routes, [], &block)
|
68
71
|
end
|
69
|
-
|
72
|
+
|
70
73
|
# Prepends routes in the block to routing table.
|
74
|
+
#
|
75
|
+
# @api public
|
71
76
|
def prepend(&block)
|
72
77
|
prepare([], routes, &block)
|
73
78
|
end
|
74
79
|
|
75
80
|
# Clears the routing table. Route generation and request matching
|
76
81
|
# won't work anymore until a new routing table is built.
|
82
|
+
#
|
83
|
+
# @api private
|
77
84
|
def reset!
|
78
85
|
class << self
|
79
86
|
alias_method :match, :match_before_compilation
|
@@ -84,18 +91,16 @@ module Merb
|
|
84
91
|
# Finds route matching URI of the request and returns a tuple of
|
85
92
|
# [route index, route params]. This method is called by the
|
86
93
|
# dispatcher and isn't as useful in applications.
|
87
|
-
#
|
94
|
+
#
|
88
95
|
# ==== Parameters
|
89
96
|
# request<Merb::Request>:: request to match.
|
90
|
-
#
|
97
|
+
#
|
91
98
|
# ==== Returns
|
92
|
-
#
|
93
|
-
# Two-tuple: route index and route parameters. Route
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
# ---
|
98
|
-
# @private
|
99
|
+
# Array[Integer, Hash]::
|
100
|
+
# Two-tuple: route index and route parameters. Route parameters
|
101
|
+
# are :controller, :action and all the named segments of the route.
|
102
|
+
#
|
103
|
+
# @api private
|
99
104
|
def route_for(request) #:nodoc:
|
100
105
|
index, params = match(request)
|
101
106
|
route = routes[index] if index
|
@@ -105,43 +110,85 @@ module Merb
|
|
105
110
|
end
|
106
111
|
[route, params]
|
107
112
|
end
|
108
|
-
|
109
|
-
#
|
113
|
+
|
114
|
+
# A placeholder for the compiled match method.
|
115
|
+
#
|
116
|
+
# ==== Notes
|
117
|
+
# This method is aliased as +match+ but this method gets overridden with
|
118
|
+
# the actual +match+ method (generated from the routes definitions) after
|
119
|
+
# being compiled. This method is only ever called before routes are
|
120
|
+
# compiled.
|
121
|
+
#
|
122
|
+
# ==== Raises
|
123
|
+
# NotCompiledError:: routes have not been compiled yet.
|
124
|
+
#
|
125
|
+
# @api private
|
110
126
|
def match_before_compilation(request) #:nodoc:
|
111
127
|
raise NotCompiledError, "The routes have not been compiled yet"
|
112
128
|
end
|
113
|
-
|
129
|
+
|
114
130
|
alias_method :match, :match_before_compilation
|
115
131
|
|
116
|
-
#
|
132
|
+
# There are three possible ways to use this method. First, if you have a named route,
|
133
|
+
# you can specify the route as the first parameter as a symbol and any paramters in a
|
134
|
+
# hash. Second, you can generate the default route by just passing the params hash,
|
135
|
+
# just passing the params hash. Finally, you can use the anonymous parameters. This
|
136
|
+
# allows you to specify the parameters to a named route in the order they appear in the
|
137
|
+
# router.
|
117
138
|
#
|
118
|
-
# ==== Parameters
|
119
|
-
# name<Symbol>::
|
120
|
-
# The name of the route
|
139
|
+
# ==== Parameters(Named Route)
|
140
|
+
# name<Symbol>::
|
141
|
+
# The name of the route.
|
142
|
+
# args<Hash>::
|
143
|
+
# Parameters for the route generation.
|
121
144
|
#
|
122
|
-
#
|
145
|
+
# ==== Parameters(Default Route)
|
146
|
+
# args<Hash>::
|
147
|
+
# Parameters for the route generation. This route will use the default route.
|
148
|
+
#
|
149
|
+
# ==== Parameters(Anonymous Parameters)
|
150
|
+
# name<Symbol>::
|
151
|
+
# The name of the route.
|
152
|
+
# args<Array>::
|
123
153
|
# An array of anonymous parameters to generate the route
|
124
154
|
# with. These parameters are assigned to the route parameters
|
125
155
|
# in the order that they are passed.
|
126
156
|
#
|
127
|
-
# params<Hash>::
|
128
|
-
# Named parameters to generate the route with.
|
129
|
-
#
|
130
|
-
# defaults<Hash>::
|
131
|
-
# A hash of default parameters to generate the route with.
|
132
|
-
# This is usually the request parameters. If there are any
|
133
|
-
# required params that are missing to generate the route,
|
134
|
-
# they are pulled from this hash.
|
135
157
|
# ==== Returns
|
136
|
-
# String:: The generated URL
|
137
|
-
#
|
138
|
-
#
|
158
|
+
# String:: The generated URL.
|
159
|
+
#
|
160
|
+
# ==== Examples
|
161
|
+
# Named Route
|
162
|
+
#
|
163
|
+
# Merb::Router.prepare do
|
164
|
+
# match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
|
165
|
+
# end
|
166
|
+
#
|
167
|
+
# url(:articles, :title => "new_article")
|
168
|
+
#
|
169
|
+
# Default Route
|
170
|
+
#
|
171
|
+
# Merb::Router.prepare do
|
172
|
+
# default_routes
|
173
|
+
# end
|
174
|
+
#
|
175
|
+
# url(:controller => "articles", :action => "new")
|
176
|
+
#
|
177
|
+
# Anonymous Paramters
|
178
|
+
#
|
179
|
+
# Merb::Router.prepare do
|
180
|
+
# match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
|
181
|
+
# end
|
182
|
+
#
|
183
|
+
# url(:articles, 2008, 10, "test_article")
|
184
|
+
#
|
185
|
+
# @api private
|
139
186
|
def url(name, *args)
|
140
187
|
unless name.is_a?(Symbol)
|
141
188
|
args.unshift(name)
|
142
189
|
name = :default
|
143
190
|
end
|
144
|
-
|
191
|
+
|
145
192
|
unless route = Merb::Router.named_routes[name]
|
146
193
|
raise Merb::Router::GenerationError, "Named route not found: #{name}"
|
147
194
|
end
|
@@ -152,25 +199,26 @@ module Merb
|
|
152
199
|
end
|
153
200
|
|
154
201
|
# Generates a URL from the resource(s)
|
155
|
-
#
|
202
|
+
#
|
156
203
|
# ==== Parameters
|
157
204
|
# resources<Symbol,Object>::
|
158
205
|
# The identifiers for the resource route to generate. These
|
159
206
|
# can either be symbols or objects. Symbols denote resource
|
160
207
|
# collection routes and objects denote the members.
|
161
|
-
#
|
208
|
+
#
|
162
209
|
# params<Hash>::
|
163
210
|
# Any extra parameters needed to generate the route.
|
211
|
+
#
|
164
212
|
# ==== Returns
|
165
213
|
# String:: The generated URL
|
166
|
-
#
|
167
|
-
# @private
|
214
|
+
#
|
215
|
+
# @api private
|
168
216
|
def resource(*args)
|
169
217
|
defaults = args.pop
|
170
218
|
options = extract_options_from_args!(args) || {}
|
171
219
|
key = []
|
172
220
|
params = []
|
173
|
-
|
221
|
+
|
174
222
|
args.each do |arg|
|
175
223
|
if arg.is_a?(Symbol) || arg.is_a?(String)
|
176
224
|
key << arg.to_s
|
@@ -179,19 +227,56 @@ module Merb
|
|
179
227
|
params << arg
|
180
228
|
end
|
181
229
|
end
|
182
|
-
|
230
|
+
|
183
231
|
params << options
|
184
|
-
|
232
|
+
|
185
233
|
unless route = Merb::Router.resource_routes[key]
|
186
234
|
raise Merb::Router::GenerationError, "Resource route not found: #{args.inspect}"
|
187
235
|
end
|
188
|
-
|
236
|
+
|
189
237
|
route.generate(params, defaults)
|
190
238
|
end
|
239
|
+
|
240
|
+
# Add functionality to the router. This can be in the form of
|
241
|
+
# including a new module or directly defining new methods.
|
242
|
+
#
|
243
|
+
# ==== Parameters
|
244
|
+
# &block<Block>::
|
245
|
+
# A block of code used to extend the route builder with. This
|
246
|
+
# can be including a module or directly defining some new methods
|
247
|
+
# that should be available to building routes.
|
248
|
+
#
|
249
|
+
# ==== Returns
|
250
|
+
# nil
|
251
|
+
#
|
252
|
+
# ==== Example
|
253
|
+
# Merb::Router.extensions do
|
254
|
+
# def domain(name, domain, options={}, &block)
|
255
|
+
# match(:domain => domain).namespace(name, :path => nil, &block)
|
256
|
+
# end
|
257
|
+
# end
|
258
|
+
#
|
259
|
+
# In this case, a method 'domain' will be available to the route builder
|
260
|
+
# which will create namespaces around domains instead of path prefixes.
|
261
|
+
#
|
262
|
+
# This can then be used as follows.
|
263
|
+
#
|
264
|
+
# Merb::Router.prepare do
|
265
|
+
# domain(:admin, "my-admin.com") do
|
266
|
+
# # ... routes come here ...
|
267
|
+
# end
|
268
|
+
# end
|
269
|
+
#
|
270
|
+
# @api public
|
271
|
+
def extensions(&block)
|
272
|
+
Router::Behavior.class_eval(&block)
|
273
|
+
end
|
191
274
|
|
192
275
|
private
|
193
276
|
|
194
|
-
#
|
277
|
+
# Compiles the routes and creates the +match+ method.
|
278
|
+
#
|
279
|
+
# @api private
|
195
280
|
def compile
|
196
281
|
if routes.any?
|
197
282
|
eval(compiled_statement, binding, "Generated Code for Router", 1)
|
@@ -199,18 +284,21 @@ module Merb
|
|
199
284
|
reset!
|
200
285
|
end
|
201
286
|
end
|
202
|
-
|
203
|
-
# Generates method
|
287
|
+
|
288
|
+
# Generates the method for evaluation defining a +match+ method to match
|
289
|
+
# a request with the defined routes.
|
290
|
+
#
|
291
|
+
# @api private
|
204
292
|
def compiled_statement
|
205
293
|
@compiler_mutex.synchronize do
|
206
294
|
condition_keys, if_statements = Set.new, ""
|
207
|
-
|
295
|
+
|
208
296
|
routes.each_with_index do |route, i|
|
209
297
|
route.freeze
|
210
298
|
route.conditions.keys.each { |key| condition_keys << key }
|
211
299
|
if_statements << route.compiled_statement(i == 0)
|
212
300
|
end
|
213
|
-
|
301
|
+
|
214
302
|
statement = "def match(request)\n"
|
215
303
|
statement << condition_keys.inject("") do |cached, key|
|
216
304
|
cached << " cached_#{key} = request.#{key}.to_s\n"
|
@@ -222,7 +310,7 @@ module Merb
|
|
222
310
|
statement << "end"
|
223
311
|
end
|
224
312
|
end
|
225
|
-
|
313
|
+
|
226
314
|
end # class << self
|
227
315
|
end
|
228
316
|
end
|
@@ -3,31 +3,51 @@ module Merb
|
|
3
3
|
class Router
|
4
4
|
|
5
5
|
class Behavior
|
6
|
-
|
7
|
-
class Error < StandardError; end
|
6
|
+
|
7
|
+
class Error < StandardError; end
|
8
8
|
|
9
9
|
# Proxy catches any methods and proxies them to the current behavior.
|
10
10
|
# This allows building routes without constantly having to catching the
|
11
11
|
# yielded behavior object
|
12
|
-
#
|
13
|
-
# @private
|
14
|
-
class Proxy
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
class Proxy
|
15
|
+
|
15
16
|
# Undefine as many methods as possible so that everything can be proxied
|
16
17
|
# along to the behavior
|
17
18
|
instance_methods.each { |m| undef_method m unless %w[ __id__ __send__ class kind_of? respond_to? assert_kind_of should should_not instance_variable_set instance_variable_get instance_eval].include?(m) }
|
18
19
|
|
20
|
+
# @api private
|
19
21
|
def initialize
|
20
22
|
@behaviors = []
|
21
23
|
end
|
22
24
|
|
25
|
+
# Puts a behavior on the bottom of the stack.
|
26
|
+
#
|
27
|
+
# ==== Notes
|
28
|
+
# The behaviors keep track of nested scopes.
|
29
|
+
#
|
30
|
+
# @api private
|
23
31
|
def push(behavior)
|
24
32
|
@behaviors.push(behavior)
|
25
33
|
end
|
26
34
|
|
35
|
+
# Removes the top-most behavior.
|
36
|
+
#
|
37
|
+
# ==== Notes
|
38
|
+
# This occurs at the end of a nested scope (namespace, etc).
|
39
|
+
#
|
40
|
+
# @api private
|
27
41
|
def pop
|
28
42
|
@behaviors.pop
|
29
43
|
end
|
30
44
|
|
45
|
+
# Tests whether the top-most behavior responds to the arguments.
|
46
|
+
#
|
47
|
+
# ==== Notes
|
48
|
+
# Behaviors contain the actual functionality of the proxy.
|
49
|
+
#
|
50
|
+
# @api private
|
31
51
|
def respond_to?(*args)
|
32
52
|
super || @behaviors.last.respond_to?(*args)
|
33
53
|
end
|
@@ -35,7 +55,7 @@ module Merb
|
|
35
55
|
# Rake does some stuff with methods in the global namespace, so if I don't
|
36
56
|
# explicitly define the Behavior methods to proxy here (specifically namespace)
|
37
57
|
# Rake's methods take precedence.
|
38
|
-
#
|
58
|
+
#
|
39
59
|
# Removing the following:
|
40
60
|
# name full_name fixatable redirect
|
41
61
|
%w(
|
@@ -49,25 +69,86 @@ module Merb
|
|
49
69
|
}
|
50
70
|
end
|
51
71
|
|
52
|
-
#
|
72
|
+
# == These methods are to be used in defer_to blocks
|
53
73
|
|
54
|
-
#
|
55
|
-
#
|
74
|
+
# There are three possible ways to use this method. First, if you have a named route,
|
75
|
+
# you can specify the route as the first parameter as a symbol and any paramters in a
|
76
|
+
# hash. Second, you can generate the default route by just passing the params hash,
|
77
|
+
# just passing the params hash. Finally, you can use the anonymous parameters. This
|
78
|
+
# allows you to specify the parameters to a named route in the order they appear in the
|
79
|
+
# router.
|
80
|
+
#
|
81
|
+
# ==== Parameters(Named Route)
|
82
|
+
# name<Symbol>::
|
83
|
+
# The name of the route.
|
84
|
+
# args<Hash>::
|
85
|
+
# Parameters for the route generation.
|
86
|
+
#
|
87
|
+
# ==== Parameters(Default Route)
|
88
|
+
# args<Hash>::
|
89
|
+
# Parameters for the route generation. This route will use the default route.
|
90
|
+
#
|
91
|
+
# ==== Parameters(Anonymous Parameters)
|
92
|
+
# name<Symbol>::
|
93
|
+
# The name of the route.
|
94
|
+
# args<Array>::
|
95
|
+
# An array of anonymous parameters to generate the route
|
96
|
+
# with. These parameters are assigned to the route parameters
|
97
|
+
# in the order that they are passed.
|
98
|
+
#
|
99
|
+
# ==== Returns
|
100
|
+
# String:: The generated URL.
|
101
|
+
#
|
102
|
+
# ==== Examples
|
103
|
+
# Named Route
|
104
|
+
#
|
105
|
+
# Merb::Router.prepare do
|
106
|
+
# match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# url(:articles, :title => "new_article")
|
110
|
+
#
|
111
|
+
# Default Route
|
112
|
+
#
|
113
|
+
# Merb::Router.prepare do
|
114
|
+
# default_routes
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
# url(:controller => "articles", :action => "new")
|
118
|
+
#
|
119
|
+
# Anonymous Paramters
|
120
|
+
#
|
121
|
+
# Merb::Router.prepare do
|
122
|
+
# match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
|
123
|
+
# end
|
124
|
+
#
|
125
|
+
# url(:articles, 2008, 10, "test_article")
|
126
|
+
#
|
127
|
+
# @api public
|
56
128
|
def url(name, *args)
|
57
129
|
args << {}
|
58
130
|
Merb::Router.url(name, *args)
|
59
131
|
end
|
60
132
|
|
133
|
+
# Generates a Rack redirection response.
|
134
|
+
#
|
135
|
+
# ==== Notes
|
136
|
+
# Refer to Merb::Rack::Helpers.redirect for documentation.
|
137
|
+
#
|
138
|
+
# @api public
|
61
139
|
def redirect(url, opts = {})
|
62
|
-
|
140
|
+
Merb::Rack::Helpers.redirect(url, opts)
|
63
141
|
end
|
64
142
|
|
65
|
-
|
66
|
-
params
|
67
|
-
end
|
143
|
+
private
|
68
144
|
|
69
|
-
|
70
|
-
|
145
|
+
# Proxies the method calls to the behavior.
|
146
|
+
#
|
147
|
+
# ==== Notes
|
148
|
+
# Please refer to:
|
149
|
+
# http://ruby-doc.org/core/classes/Kernel.html#M005951
|
150
|
+
#
|
151
|
+
# @api private
|
71
152
|
def method_missing(method, *args, &block)
|
72
153
|
behavior = @behaviors.last
|
73
154
|
|
@@ -78,14 +159,14 @@ module Merb
|
|
78
159
|
end
|
79
160
|
end
|
80
161
|
end
|
81
|
-
|
162
|
+
|
82
163
|
# Behavior objects are used for the Route building DSL. Each object keeps
|
83
164
|
# track of the current definitions for the level at which it is defined.
|
84
165
|
# Each time a method is called on a Behavior object that accepts a block,
|
85
166
|
# a new instance of the Behavior class is created.
|
86
|
-
#
|
167
|
+
#
|
87
168
|
# ==== Parameters
|
88
|
-
#
|
169
|
+
#
|
89
170
|
# proxy<Proxy>::
|
90
171
|
# This is the object initialized by Merb::Router.prepare that tracks the
|
91
172
|
# current Behavior object stack so that Behavior methods can be called
|
@@ -100,11 +181,11 @@ module Merb
|
|
100
181
|
# The initial route options. See #options.
|
101
182
|
# blocks<Array>::
|
102
183
|
# The stack of deferred routing blocks for the route
|
103
|
-
#
|
184
|
+
#
|
104
185
|
# ==== Returns
|
105
186
|
# Behavior:: The initialized Behavior object
|
106
|
-
|
107
|
-
# @private
|
187
|
+
#
|
188
|
+
# @api private
|
108
189
|
def initialize(proxy = nil, conditions = {}, params = {}, defaults = {}, identifiers = {}, options = {}, blocks = []) #:nodoc:
|
109
190
|
@proxy = proxy
|
110
191
|
@conditions = conditions
|
@@ -113,130 +194,129 @@ module Merb
|
|
113
194
|
@identifiers = identifiers
|
114
195
|
@options = options
|
115
196
|
@blocks = blocks
|
116
|
-
|
197
|
+
|
117
198
|
stringify_condition_values
|
118
199
|
end
|
119
|
-
|
200
|
+
|
120
201
|
# Defines the +conditions+ that are required to match a Request. Each
|
121
202
|
# +condition+ is applied to a method of the Request object. Conditions
|
122
203
|
# can also be applied to segments of the +path+.
|
123
|
-
#
|
204
|
+
#
|
124
205
|
# If #match is passed a block, it will create a new route scope with
|
125
206
|
# the conditions passed to it and yield to the block such that all
|
126
207
|
# routes that are defined in the block have the conditions applied
|
127
208
|
# to them.
|
128
|
-
#
|
209
|
+
#
|
129
210
|
# ==== Parameters
|
130
|
-
#
|
211
|
+
#
|
131
212
|
# path<String, Regexp>::
|
132
213
|
# The pattern against which Merb::Request path is matched.
|
133
|
-
#
|
214
|
+
#
|
134
215
|
# When +path+ is a String, any substring that is wrapped in parenthesis
|
135
216
|
# is considered optional and any segment that begins with a colon, ex.:
|
136
217
|
# ":login", defines both a capture and a named param. Extra conditions
|
137
218
|
# can then be applied each named param individually.
|
138
|
-
#
|
219
|
+
#
|
139
220
|
# When +path+ is a Regexp, the pattern is left untouched and the
|
140
221
|
# Merb::Request path is matched against it as is.
|
141
222
|
#
|
142
223
|
# +path+ is optional.
|
143
|
-
#
|
224
|
+
#
|
144
225
|
# conditions<Hash>::
|
145
226
|
# Additional conditions that the request must meet in order to match.
|
146
227
|
# The keys must be the names of previously defined path segments or
|
147
228
|
# be methods that the Merb::Request instance will respond to. The
|
148
229
|
# value is the string or regexp that matched the returned value.
|
149
230
|
# Conditions are inherited by child routes.
|
150
|
-
#
|
231
|
+
#
|
151
232
|
# &block::
|
152
233
|
# All routes defined in the block will be scoped to the conditions
|
153
234
|
# defined by the #match method.
|
154
|
-
#
|
235
|
+
#
|
155
236
|
# ==== Block parameters
|
156
237
|
# r<Behavior>:: +optional+ - The match behavior object.
|
157
|
-
#
|
238
|
+
#
|
158
239
|
# ==== Returns
|
159
240
|
# Behavior::
|
160
241
|
# A new instance of Behavior with the specified path and conditions.
|
161
|
-
#
|
242
|
+
#
|
162
243
|
# +Tip+: When nesting always make sure the most inner sub-match registers
|
163
|
-
# a Route and doesn't just
|
164
|
-
#
|
244
|
+
# a Route and doesn't just return new Behaviors.
|
245
|
+
#
|
165
246
|
# ==== Examples
|
166
|
-
#
|
247
|
+
#
|
167
248
|
# # registers /foo/bar to controller => "foo", :action => "bar"
|
168
249
|
# # and /foo/baz to controller => "foo", :action => "baz"
|
169
250
|
# match("/foo") do
|
170
251
|
# match("/bar").to(:controller => "foo", :action => "bar")
|
171
252
|
# match("/baz").to(:controller => "foo", :action => "caz")
|
172
253
|
# end
|
173
|
-
#
|
254
|
+
#
|
174
255
|
# # Checks the format of the segments against the specified Regexp
|
175
256
|
# match("/:string/:number", :string => /[a-z]+/, :number => /\d+/).
|
176
257
|
# to(:controller => "string_or_numbers")
|
177
|
-
#
|
258
|
+
#
|
178
259
|
# # Equivalent to the default_route
|
179
260
|
# match("/:controller(/:action(:id))(.:format)").register
|
180
|
-
#
|
261
|
+
#
|
181
262
|
# #match only if the browser string contains MSIE or Gecko
|
182
263
|
# match("/foo", :user_agent => /(MSIE|Gecko)/ )
|
183
264
|
# .to(:controller => 'foo', :action => 'popular')
|
184
|
-
#
|
265
|
+
#
|
185
266
|
# # Route GET and POST requests to different actions (see also #resources)
|
186
267
|
# r.match('/foo', :method => :get).to(:action => 'show')
|
187
268
|
# r.match('/foo', :method => :post).to(:action => 'create')
|
188
|
-
#
|
269
|
+
#
|
189
270
|
# # match also takes regular expressions
|
190
|
-
#
|
271
|
+
#
|
191
272
|
# r.match(%r[/account/([a-z]{4,6})]).to(:controller => "account",
|
192
273
|
# :action => "show", :id => "[1]")
|
193
|
-
#
|
274
|
+
#
|
194
275
|
# r.match(%r{/?(en|es|fr|be|nl)?}).to(:language => "[1]") do
|
195
276
|
# match("/guides/:action/:id").to(:controller => "tour_guides")
|
196
277
|
# end
|
197
|
-
|
198
|
-
# @public
|
278
|
+
#
|
279
|
+
# @api public
|
199
280
|
def match(path = {}, conditions = {}, &block)
|
200
281
|
path, conditions = path[:path], path if path.is_a?(Hash)
|
201
|
-
|
202
|
-
raise Error, "The route has already been committed. Further conditions cannot be specified" if @route
|
203
282
|
|
283
|
+
raise Error, "The route has already been committed. Further conditions cannot be specified" if @route
|
204
284
|
|
205
285
|
conditions.delete_if { |k, v| v.nil? }
|
206
286
|
conditions[:path] = merge_paths(path)
|
207
|
-
|
287
|
+
|
208
288
|
behavior = Behavior.new(@proxy, @conditions.merge(conditions), @params, @defaults, @identifiers, @options, @blocks)
|
209
289
|
with_behavior_context(behavior, &block)
|
210
290
|
end
|
211
291
|
|
212
292
|
# Creates a Route from one or more Behavior objects, unless a +block+ is
|
213
293
|
# passed in.
|
214
|
-
#
|
294
|
+
#
|
215
295
|
# ==== Parameters
|
216
296
|
# params<Hash>:: The parameters the route maps to.
|
217
|
-
#
|
297
|
+
#
|
218
298
|
# &block::
|
219
299
|
# All routes defined in the block will be scoped to the params
|
220
300
|
# defined by the #to method.
|
221
|
-
#
|
301
|
+
#
|
222
302
|
# ==== Block parameters
|
223
303
|
# r<Behavior>:: +optional+ - The to behavior object.
|
224
|
-
#
|
304
|
+
#
|
225
305
|
# ==== Returns
|
226
306
|
# Route:: It registers a new route and returns it.
|
227
|
-
#
|
307
|
+
#
|
228
308
|
# ==== Examples
|
229
309
|
# match('/:controller/:id).to(:action => 'show')
|
230
|
-
#
|
310
|
+
#
|
231
311
|
# to(:controller => 'simple') do
|
232
312
|
# match('/test').to(:action => 'index')
|
233
313
|
# match('/other').to(:action => 'other')
|
234
314
|
# end
|
235
|
-
|
236
|
-
# @public
|
315
|
+
#
|
316
|
+
# @api public
|
237
317
|
def to(params = {}, &block)
|
238
318
|
raise Error, "The route has already been committed. Further params cannot be specified" if @route
|
239
|
-
|
319
|
+
|
240
320
|
behavior = Behavior.new(@proxy, @conditions, @params.merge(params), @defaults, @identifiers, @options, @blocks)
|
241
321
|
|
242
322
|
if block_given?
|
@@ -247,7 +327,8 @@ module Merb
|
|
247
327
|
end
|
248
328
|
|
249
329
|
# Equivalent of #to. Allows for some nicer syntax when scoping blocks
|
250
|
-
#
|
330
|
+
#
|
331
|
+
# ==== Examples
|
251
332
|
# Merb::Router.prepare do
|
252
333
|
# with(:controller => "users") do
|
253
334
|
# match("/signup").to(:action => "signup")
|
@@ -255,32 +336,32 @@ module Merb
|
|
255
336
|
# match("/logout").to(:action => "logout")
|
256
337
|
# end
|
257
338
|
# end
|
258
|
-
|
339
|
+
alias :with :to
|
259
340
|
|
260
341
|
# Equivalent of #to. Allows for nicer syntax when registering routes with no params
|
261
|
-
#
|
342
|
+
#
|
343
|
+
# ==== Examples
|
262
344
|
# Merb::Router.prepare do
|
263
345
|
# match("/:controller(/:action(/:id))(.:format)").register
|
264
346
|
# end
|
265
|
-
|
266
|
-
alias_method :register, :to
|
347
|
+
alias :register :to
|
267
348
|
|
268
349
|
# Sets default values for route parameters. If no value for the key
|
269
350
|
# can be extracted from the request, then the value provided here
|
270
351
|
# will be used.
|
271
|
-
#
|
352
|
+
#
|
272
353
|
# ==== Parameters
|
273
354
|
# defaults<Hash>::
|
274
355
|
# The default values for named segments.
|
275
|
-
#
|
356
|
+
#
|
276
357
|
# &block::
|
277
358
|
# All routes defined in the block will be scoped to the defaults defined
|
278
359
|
# by the #default method.
|
279
|
-
#
|
360
|
+
#
|
280
361
|
# ==== Block parameters
|
281
362
|
# r<Behavior>:: +optional+ - The defaults behavior object.
|
282
|
-
#
|
283
|
-
# @public
|
363
|
+
#
|
364
|
+
# @api public
|
284
365
|
def default(defaults = {}, &block)
|
285
366
|
behavior = Behavior.new(@proxy, @conditions, @params, @defaults.merge(defaults), @identifiers, @options, @blocks)
|
286
367
|
with_behavior_context(behavior, &block)
|
@@ -289,34 +370,34 @@ module Merb
|
|
289
370
|
alias_method :defaults, :default
|
290
371
|
|
291
372
|
# Allows the fine tuning of certain router options.
|
292
|
-
#
|
373
|
+
#
|
293
374
|
# ==== Parameters
|
294
375
|
# options<Hash>::
|
295
376
|
# The options to set for all routes defined in the scope. The currently
|
296
377
|
# supported options are:
|
297
378
|
# * :controller_prefix - The module that the controller is included in.
|
298
379
|
# * :name_prefix - The prefix added to all routes named with #name
|
299
|
-
#
|
380
|
+
#
|
300
381
|
# &block::
|
301
382
|
# All routes defined in the block will be scoped to the options defined
|
302
383
|
# by the #options method.
|
303
|
-
#
|
384
|
+
#
|
304
385
|
# ==== Block parameters
|
305
386
|
# r<Behavior>:: The options behavior object. This is optional
|
306
|
-
#
|
387
|
+
#
|
307
388
|
# ==== Examples
|
308
389
|
# # If :group is not matched in the path, it will be "registered" instead
|
309
390
|
# # of nil.
|
310
391
|
# match("/users(/:group)").default(:group => "registered")
|
311
|
-
#
|
312
|
-
# @public
|
392
|
+
#
|
393
|
+
# @api public
|
313
394
|
def options(opts = {}, &block)
|
314
395
|
options = @options.dup
|
315
|
-
|
396
|
+
|
316
397
|
opts.each_pair do |key, value|
|
317
398
|
options[key] = (options[key] || []) + [value.freeze] if value
|
318
399
|
end
|
319
|
-
|
400
|
+
|
320
401
|
behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, options, @blocks)
|
321
402
|
with_behavior_context(behavior, &block)
|
322
403
|
end
|
@@ -325,44 +406,47 @@ module Merb
|
|
325
406
|
|
326
407
|
# Creates a namespace for a route. This way you can have logical
|
327
408
|
# separation to your routes.
|
328
|
-
#
|
409
|
+
#
|
329
410
|
# ==== Parameters
|
330
411
|
# name_or_path<String, Symbol>::
|
331
412
|
# The name or path of the namespace.
|
332
|
-
#
|
413
|
+
#
|
333
414
|
# options<Hash>::
|
334
|
-
# Optional hash
|
335
|
-
#
|
415
|
+
# Optional hash (see below)
|
416
|
+
#
|
336
417
|
# &block::
|
337
418
|
# All routes defined in the block will be scoped to the namespace defined
|
338
419
|
# by the #namespace method.
|
339
|
-
#
|
420
|
+
#
|
421
|
+
# ==== Options (opts)
|
422
|
+
# :path<String>:: match against this url
|
423
|
+
#
|
340
424
|
# ==== Block parameters
|
341
425
|
# r<Behavior>:: The namespace behavior object. This is optional
|
342
|
-
#
|
426
|
+
#
|
343
427
|
# ==== Examples
|
344
428
|
# namespace :admin do
|
345
429
|
# resources :accounts
|
346
430
|
# resource :email
|
347
431
|
# end
|
348
|
-
#
|
432
|
+
#
|
349
433
|
# # /super_admin/accounts
|
350
434
|
# namespace(:admin, :path=>"super_admin") do
|
351
435
|
# resources :accounts
|
352
436
|
# end
|
353
|
-
#
|
354
|
-
# @public
|
437
|
+
#
|
438
|
+
# @api public
|
355
439
|
def namespace(name_or_path, opts = {}, &block)
|
356
440
|
name = name_or_path.to_s # We don't want this modified ever
|
357
441
|
path = opts.has_key?(:path) ? opts[:path] : name
|
358
|
-
|
442
|
+
|
359
443
|
raise Error, "The route has already been committed. Further options cannot be specified" if @route
|
360
|
-
|
444
|
+
|
361
445
|
# option keys could be nil
|
362
446
|
opts[:controller_prefix] = name unless opts.has_key?(:controller_prefix)
|
363
447
|
opts[:name_prefix] = name unless opts.has_key?(:name_prefix)
|
364
448
|
opts[:resource_prefix] = opts[:name_prefix] unless opts.has_key?(:resource_prefix)
|
365
|
-
|
449
|
+
|
366
450
|
behavior = self
|
367
451
|
behavior = behavior.match("/#{path}") unless path.nil? || path.empty?
|
368
452
|
behavior.options(opts, &block)
|
@@ -372,22 +456,22 @@ module Merb
|
|
372
456
|
# insertion into a route. This is useful when using models and want a
|
373
457
|
# specific method to be called on it (For example, for ActiveRecord::Base
|
374
458
|
# it would be #to_param).
|
375
|
-
#
|
459
|
+
#
|
376
460
|
# The default method called on objects is #to_s.
|
377
|
-
#
|
461
|
+
#
|
378
462
|
# ==== Paramters
|
379
463
|
# identifiers<Hash>::
|
380
464
|
# The keys are Classes and the values are the method that instances of the specified
|
381
465
|
# class should have called on.
|
382
|
-
#
|
466
|
+
#
|
383
467
|
# &block::
|
384
468
|
# All routes defined in the block will be call the specified methods during
|
385
469
|
# generation.
|
386
|
-
#
|
470
|
+
#
|
387
471
|
# ==== Block parameters
|
388
472
|
# r<Behavior>:: The identify behavior object. This is optional
|
389
|
-
#
|
390
|
-
# @public
|
473
|
+
#
|
474
|
+
# @api public
|
391
475
|
def identify(identifiers = {}, &block)
|
392
476
|
identifiers = if Hash === identifiers
|
393
477
|
@identifiers.merge(identifiers)
|
@@ -402,23 +486,23 @@ module Merb
|
|
402
486
|
# Creates the most common routes /:controller/:action/:id.format when
|
403
487
|
# called with no arguments. You can pass a hash or a block to add parameters
|
404
488
|
# or override the default behavior.
|
405
|
-
#
|
489
|
+
#
|
406
490
|
# ==== Parameters
|
407
491
|
# params<Hash>::
|
408
492
|
# This optional hash can be used to augment the default settings
|
409
|
-
#
|
493
|
+
#
|
410
494
|
# &block::
|
411
495
|
# When passing a block a new behavior is yielded and more refinement is
|
412
496
|
# possible.
|
413
|
-
#
|
497
|
+
#
|
414
498
|
# ==== Returns
|
415
499
|
# Route:: the default route
|
416
|
-
#
|
500
|
+
#
|
417
501
|
# ==== Examples
|
418
|
-
#
|
502
|
+
#
|
419
503
|
# # Passing an extra parameter "mode" to all matches
|
420
504
|
# r.default_routes :mode => "default"
|
421
|
-
#
|
505
|
+
#
|
422
506
|
# # specifying exceptions within a block
|
423
507
|
# r.default_routes do |nr|
|
424
508
|
# nr.defer_to do |request, params|
|
@@ -426,31 +510,31 @@ module Merb
|
|
426
510
|
# :action => "new") if request.env["REQUEST_URI"] =~ /\/private\//
|
427
511
|
# end
|
428
512
|
# end
|
429
|
-
|
430
|
-
# @public
|
513
|
+
#
|
514
|
+
# @api public
|
431
515
|
def default_routes(params = {}, &block)
|
432
516
|
match("/:controller(/:action(/:id))(.:format)").to(params, &block).name(:default)
|
433
517
|
end
|
434
518
|
|
435
519
|
# Takes a block and stores it for deferred conditional routes. The block
|
436
520
|
# takes the +request+ object and the +params+ hash as parameters.
|
437
|
-
#
|
521
|
+
#
|
438
522
|
# ==== Parameters
|
439
523
|
# params<Hash>:: Parameters and conditions associated with this behavior.
|
440
524
|
# &conditional_block::
|
441
525
|
# A block with the conditions to be met for the behavior to take
|
442
526
|
# effect.
|
443
|
-
#
|
527
|
+
#
|
444
528
|
# ==== Returns
|
445
529
|
# Route :: The default route.
|
446
|
-
#
|
530
|
+
#
|
447
531
|
# ==== Examples
|
448
532
|
# defer_to do |request, params|
|
449
533
|
# params.merge :controller => 'here',
|
450
534
|
# :action => 'there' if request.xhr?
|
451
535
|
# end
|
452
|
-
|
453
|
-
# @public
|
536
|
+
#
|
537
|
+
# @api public
|
454
538
|
def defer_to(params = {}, &block)
|
455
539
|
defer(block).to(params)
|
456
540
|
end
|
@@ -458,27 +542,39 @@ module Merb
|
|
458
542
|
# Takes a Proc as a parameter and applies it as a deferred proc for all the
|
459
543
|
# routes defined in the block. This is mostly interesting for plugin
|
460
544
|
# developers.
|
545
|
+
#
|
546
|
+
# ==== Examples
|
547
|
+
# defered_block = proc do |r, p|
|
548
|
+
# p.merge :controller => 'api/comments' if request.xhr?
|
549
|
+
# end
|
550
|
+
# defer(defered_block) do
|
551
|
+
# resources :comments
|
552
|
+
# end
|
553
|
+
#
|
554
|
+
# @api public
|
461
555
|
def defer(deferred_block, &block)
|
462
556
|
blocks = @blocks + [CachedProc.new(deferred_block)]
|
463
557
|
behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, @options, blocks)
|
464
558
|
with_behavior_context(behavior, &block)
|
465
559
|
end
|
466
560
|
|
467
|
-
#
|
468
|
-
#
|
561
|
+
# Registers the route as a named route with the name given.
|
562
|
+
#
|
469
563
|
# ==== Parameters
|
470
|
-
# symbol<Symbol>::
|
471
|
-
#
|
564
|
+
# symbol<Symbol>:: the name of the route.
|
565
|
+
#
|
472
566
|
# ==== Raises
|
473
567
|
# ArgumentError:: symbol is not a Symbol.
|
568
|
+
#
|
569
|
+
# @api public
|
474
570
|
def name(prefix, name = nil)
|
475
571
|
unless name
|
476
572
|
name, prefix = prefix, nil
|
477
573
|
end
|
478
|
-
|
574
|
+
|
479
575
|
full_name([prefix, @options[:name_prefix], name].flatten.compact.join('_'))
|
480
576
|
end
|
481
|
-
|
577
|
+
|
482
578
|
# Names this route in Router. Name must be a Symbol. The current
|
483
579
|
# name_prefix is ignored.
|
484
580
|
#
|
@@ -487,6 +583,8 @@ module Merb
|
|
487
583
|
#
|
488
584
|
# ==== Raises
|
489
585
|
# ArgumentError:: symbol is not a Symbol.
|
586
|
+
#
|
587
|
+
# @api private
|
490
588
|
def full_name(name)
|
491
589
|
if @route
|
492
590
|
@route.name = name
|
@@ -496,27 +594,34 @@ module Merb
|
|
496
594
|
end
|
497
595
|
end
|
498
596
|
|
597
|
+
# Specifies that a route can be fixatable.
|
598
|
+
#
|
499
599
|
# ==== Parameters
|
500
600
|
# enabled<Boolean>:: True enables fixation on the route.
|
601
|
+
#
|
602
|
+
# @api public
|
501
603
|
def fixatable(enable = true)
|
502
604
|
@route.fixation = enable
|
503
605
|
self
|
504
606
|
end
|
505
|
-
|
506
|
-
#
|
507
|
-
#
|
607
|
+
|
608
|
+
# Redirects the current route.
|
609
|
+
#
|
508
610
|
# ==== Parameters
|
509
|
-
# path<String
|
510
|
-
#
|
511
|
-
#
|
611
|
+
# path<String>:: The path to redirect to.
|
612
|
+
#
|
512
613
|
# options<Hash>::
|
513
|
-
# Options
|
514
|
-
#
|
515
|
-
#
|
516
|
-
#
|
614
|
+
# Options (see below)
|
615
|
+
#
|
616
|
+
# ==== Options (opts)
|
617
|
+
# :permanent<Boolean>::
|
618
|
+
# Whether or not the redirect should be permanent.
|
619
|
+
# The default value is false.
|
620
|
+
#
|
621
|
+
# @api public
|
517
622
|
def redirect(url, opts = {})
|
518
623
|
raise Error, "The route has already been committed." if @route
|
519
|
-
|
624
|
+
|
520
625
|
status = opts[:permanent] ? 301 : 302
|
521
626
|
@route = Route.new(@conditions, {:url => url.freeze, :status => status.freeze}, @blocks, :redirects => true)
|
522
627
|
@route.register
|
@@ -529,6 +634,8 @@ module Merb
|
|
529
634
|
# it doesn't affect how/which routes are added.
|
530
635
|
#
|
531
636
|
# &block:: A context in which routes are generated.
|
637
|
+
#
|
638
|
+
# @api public
|
532
639
|
def capture(&block)
|
533
640
|
captured_routes = {}
|
534
641
|
name_prefix = [@options[:name_prefix]].flatten.compact.map { |p| "#{p}_"}
|
@@ -545,27 +652,42 @@ module Merb
|
|
545
652
|
captured_routes
|
546
653
|
end
|
547
654
|
|
548
|
-
#
|
549
|
-
#
|
550
|
-
#
|
551
|
-
|
655
|
+
# Proxy routes with the default behaviors.
|
656
|
+
#
|
657
|
+
# ==== Parameters
|
658
|
+
# &block:: defines routes within the provided context.
|
659
|
+
#
|
660
|
+
# @api private
|
661
|
+
def _with_proxy(&block)
|
552
662
|
proxy = Proxy.new
|
553
663
|
proxy.push Behavior.new(proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks)
|
554
664
|
proxy.instance_eval(&block)
|
555
665
|
proxy
|
556
666
|
end
|
557
667
|
|
558
|
-
|
559
|
-
|
668
|
+
protected
|
669
|
+
|
670
|
+
# Returns the current route.
|
671
|
+
#
|
672
|
+
# ==== Returns
|
673
|
+
# Route:: the route.
|
674
|
+
#
|
675
|
+
# @api private
|
560
676
|
def _route
|
561
677
|
@route
|
562
678
|
end
|
563
679
|
|
564
|
-
|
680
|
+
# Turns a route definition into a Route object.
|
681
|
+
#
|
682
|
+
# ==== Returns
|
683
|
+
# Route:: the route generated.
|
684
|
+
#
|
685
|
+
# @api private
|
686
|
+
def to_route
|
565
687
|
raise Error, "The route has already been committed." if @route
|
566
|
-
|
688
|
+
|
567
689
|
controller = @params[:controller]
|
568
|
-
|
690
|
+
|
569
691
|
if prefixes = @options[:controller_prefix]
|
570
692
|
controller ||= ":controller"
|
571
693
|
|
@@ -594,12 +716,22 @@ module Merb
|
|
594
716
|
|
595
717
|
# Allows to insert the route at a certain spot in the list of routes
|
596
718
|
# instead of appending to the list.
|
597
|
-
|
719
|
+
#
|
720
|
+
# ==== Params
|
721
|
+
# route<Route>:: the route to insert before.
|
722
|
+
# &block:: the route definition to insert.
|
723
|
+
#
|
724
|
+
# @api plugin
|
725
|
+
def before(route, &block)
|
598
726
|
options(:before => route, &block)
|
599
727
|
end
|
600
|
-
|
601
|
-
|
602
|
-
|
728
|
+
|
729
|
+
private
|
730
|
+
|
731
|
+
# Takes @conditions and turns values into strings (except for Regexp and
|
732
|
+
# Array values).
|
733
|
+
#
|
734
|
+
# @api private
|
603
735
|
def stringify_condition_values # :nodoc:
|
604
736
|
@conditions.each do |key, value|
|
605
737
|
unless value.nil? || Regexp === value || Array === value
|
@@ -607,7 +739,18 @@ module Merb
|
|
607
739
|
end
|
608
740
|
end
|
609
741
|
end
|
610
|
-
|
742
|
+
|
743
|
+
# Creates a new context with a given behavior for the route definition in
|
744
|
+
# the block.
|
745
|
+
#
|
746
|
+
# ==== Params
|
747
|
+
# behavior<Behavior>:: the behavior to proxy the calls in the block.
|
748
|
+
# &block:: the routing definitions to be nested within the behavior.
|
749
|
+
#
|
750
|
+
# ==== Returns
|
751
|
+
# Behavior:: the behavior wrapping.
|
752
|
+
#
|
753
|
+
# @api private
|
611
754
|
def with_behavior_context(behavior, &block) # :nodoc:
|
612
755
|
if block_given?
|
613
756
|
@proxy.push(behavior)
|
@@ -616,11 +759,25 @@ module Merb
|
|
616
759
|
end
|
617
760
|
behavior
|
618
761
|
end
|
619
|
-
|
762
|
+
|
763
|
+
# Merges the path elements together into an array to be joined for
|
764
|
+
# generating named routes.
|
765
|
+
#
|
766
|
+
# ==== Parameters
|
767
|
+
# path<String>:: the path to merge at the end.
|
768
|
+
#
|
769
|
+
# ==== Returns
|
770
|
+
# Array:: array of path elements.
|
771
|
+
#
|
772
|
+
# ==== Notes
|
773
|
+
# An array of ['a', 'b'] (the 'a' namespace with the 'b' action) will
|
774
|
+
# produce a name of :a_b.
|
775
|
+
#
|
776
|
+
# @api private
|
620
777
|
def merge_paths(path) # :nodoc:
|
621
778
|
[@conditions[:path], path.freeze].flatten.compact
|
622
779
|
end
|
623
|
-
|
780
|
+
|
624
781
|
end
|
625
782
|
end
|
626
783
|
end
|