actionpack 1.13.1 → 1.13.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- data/CHANGELOG +29 -0
- data/Rakefile +1 -1
- data/lib/action_controller.rb +1 -1
- data/lib/action_controller/assertions/routing_assertions.rb +20 -4
- data/lib/action_controller/resources.rb +147 -44
- data/lib/action_controller/routing.rb +43 -17
- data/lib/action_controller/test_process.rb +2 -2
- data/lib/action_controller/vendor/html-scanner/html/node.rb +1 -3
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_view/helpers/form_helper.rb +1 -1
- data/lib/action_view/helpers/number_helper.rb +5 -5
- data/lib/action_view/helpers/text_helper.rb +14 -14
- data/test/controller/assert_select_test.rb +1 -1
- data/test/controller/resources_test.rb +231 -23
- data/test/controller/routing_test.rb +32 -0
- data/test/controller/test_test.rb +14 -0
- data/test/template/form_options_helper_test.rb +19 -0
- data/test/template/text_helper_test.rb +25 -1
- metadata +3 -5
- data/lib/action_controller/response.rb.rej +0 -17
- data/lib/action_view/helpers/javascripts/prototype.js.rej +0 -561
data/CHANGELOG
CHANGED
@@ -1,3 +1,32 @@
|
|
1
|
+
*1.13.2* (February 5th, 2007)
|
2
|
+
|
3
|
+
* Add much-needed html-scanner tests. Fixed CDATA parsing bug. [Rick]
|
4
|
+
|
5
|
+
* improve error message for Routing for named routes. [Rob Sanheim]
|
6
|
+
|
7
|
+
* Added enhanced docs to routing assertions. [Rob Sanheim]
|
8
|
+
|
9
|
+
* fix form_for example in ActionController::Resources documentation. [gnarg]
|
10
|
+
|
11
|
+
* Add singleton resources from trunk [Rick Olson]
|
12
|
+
|
13
|
+
* TestSession supports indifferent access so session['foo'] == session[:foo] in your tests. #7372 [julik, jean.helou]
|
14
|
+
|
15
|
+
* select :multiple => true suffixes the attribute name with [] unless already suffixed. #6977 [nik.kakelin, ben, julik]
|
16
|
+
|
17
|
+
* Improve routes documentation. #7095 [zackchandler]
|
18
|
+
|
19
|
+
* Resource member routes require :id, eliminating the ambiguous overlap with collection routes. #7229 [dkubb]
|
20
|
+
|
21
|
+
* Fixed NumberHelper#number_with_delimiter to use "." always for splitting the original number, not the delimiter parameter #7389 [ceefour]
|
22
|
+
|
23
|
+
* Autolinking recognizes trailing and embedded . , : ; #7354 [Jarkko Laine]
|
24
|
+
|
25
|
+
* Make TextHelper::auto_link recognize URLs with colons in path correctly, fixes #7268. [imajes]
|
26
|
+
|
27
|
+
* Improved auto_link to match more valid urls correctly [Tobias Luetke]
|
28
|
+
|
29
|
+
|
1
30
|
*1.13.1* (January 18th, 2007)
|
2
31
|
|
3
32
|
* Fixed content-type bug in Prototype [sam]
|
data/Rakefile
CHANGED
@@ -75,7 +75,7 @@ spec = Gem::Specification.new do |s|
|
|
75
75
|
s.has_rdoc = true
|
76
76
|
s.requirements << 'none'
|
77
77
|
|
78
|
-
s.add_dependency('activesupport', '= 1.4.
|
78
|
+
s.add_dependency('activesupport', '= 1.4.1' + PKG_BUILD)
|
79
79
|
|
80
80
|
s.require_path = 'lib'
|
81
81
|
s.autorequire = 'action_controller'
|
data/lib/action_controller.rb
CHANGED
@@ -3,13 +3,23 @@ module ActionController
|
|
3
3
|
module RoutingAssertions
|
4
4
|
# Asserts that the routing of the given path was handled correctly and that the parsed options match.
|
5
5
|
#
|
6
|
-
# assert_recognizes({:controller => 'items', :action => 'index'}, 'items')
|
6
|
+
# assert_recognizes({:controller => 'items', :action => 'index'}, 'items') # check the default action
|
7
|
+
# assert_recognizes({:controller => 'items', :action => 'list'}, 'items/list') # check a specific action
|
8
|
+
# assert_recognizes({:controller => 'items', :action => 'list', :id => '1'}, 'items/list/1') # check an action with a parameter
|
7
9
|
#
|
8
10
|
# Pass a hash in the second argument to specify the request method. This is useful for routes
|
9
|
-
# requiring a specific method.
|
11
|
+
# requiring a specific HTTP method. The hash should contain a :path with the incoming request path
|
12
|
+
# and a :method containing the required HTTP verb.
|
10
13
|
#
|
14
|
+
# # assert that POSTing to /items will call the create action on ItemsController
|
11
15
|
# assert_recognizes({:controller => 'items', :action => 'create'}, {:path => 'items', :method => :post})
|
12
16
|
#
|
17
|
+
# You can also pass in "extras" with a hash containing URL parameters that would normally be in the query string. This can be used
|
18
|
+
# to assert that values in the query string string will end up in the params hash correctly. To test query strings you must use the
|
19
|
+
# extras argument, appending the query string on the path directly will not work. For example:
|
20
|
+
#
|
21
|
+
# # assert that a path of '/items/list/1?view=print' returns the correct options
|
22
|
+
# assert_recognizes({:controller => 'items', :action => 'list', :id => '1', :view => 'print'}, 'items/list/1', { :view => "print" })
|
13
23
|
def assert_recognizes(expected_options, path, extras={}, message=nil)
|
14
24
|
if path.is_a? Hash
|
15
25
|
request_method = path[:method]
|
@@ -33,7 +43,12 @@ module ActionController
|
|
33
43
|
end
|
34
44
|
end
|
35
45
|
|
36
|
-
# Asserts that the provided options can be used to generate the provided path.
|
46
|
+
# Asserts that the provided options can be used to generate the provided path. This is the inverse of assert_recognizes.
|
47
|
+
# For example:
|
48
|
+
#
|
49
|
+
# assert_generates("/items", :controller => "items", :action => "index")
|
50
|
+
# assert_generates("/items/list", :controller => "items", :action => "list")
|
51
|
+
# assert_generates("/items/list/1", { :controller => "items", :action => "list", :id => "1" })
|
37
52
|
def assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)
|
38
53
|
clean_backtrace do
|
39
54
|
expected_path = "/#{expected_path}" unless expected_path[0] == ?/
|
@@ -53,7 +68,8 @@ module ActionController
|
|
53
68
|
end
|
54
69
|
|
55
70
|
# Asserts that path and options match both ways; in other words, the URL generated from
|
56
|
-
# options is the same as path, and also that the options recognized from path are the same as options
|
71
|
+
# options is the same as path, and also that the options recognized from path are the same as options. This
|
72
|
+
# essentially combines assert_recognizes and assert_generates into one step.
|
57
73
|
def assert_routing(path, options, defaults={}, extras={}, message=nil)
|
58
74
|
assert_recognizes(options, path, extras, message)
|
59
75
|
|
@@ -18,26 +18,26 @@ module ActionController
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def controller
|
21
|
-
(options[:controller] || plural).to_s
|
21
|
+
@controller ||= (options[:controller] || plural).to_s
|
22
22
|
end
|
23
23
|
|
24
24
|
def path
|
25
|
-
"#{path_prefix}/#{plural}"
|
25
|
+
@path ||= "#{path_prefix}/#{plural}"
|
26
26
|
end
|
27
27
|
|
28
28
|
def new_path
|
29
|
-
"#{path}/new"
|
29
|
+
@new_path ||= "#{path}/new"
|
30
30
|
end
|
31
31
|
|
32
32
|
def member_path
|
33
|
-
"#{path}/:id"
|
33
|
+
@member_path ||= "#{path}/:id"
|
34
34
|
end
|
35
35
|
|
36
36
|
def nesting_path_prefix
|
37
|
-
"#{path}/:#{singular}_id"
|
37
|
+
@nesting_path_prefix ||= "#{path}/:#{singular}_id"
|
38
38
|
end
|
39
39
|
|
40
|
-
|
40
|
+
protected
|
41
41
|
def arrange_actions
|
42
42
|
@collection_methods = arrange_actions_by_methods(options.delete(:collection))
|
43
43
|
@member_methods = arrange_actions_by_methods(options.delete(:member))
|
@@ -65,7 +65,20 @@ module ActionController
|
|
65
65
|
(collection[method] ||= []).unshift(action)
|
66
66
|
end
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
|
+
class SingletonResource < Resource #:nodoc:
|
70
|
+
def initialize(entity, options)
|
71
|
+
@plural = @singular = entity
|
72
|
+
@options = options
|
73
|
+
arrange_actions
|
74
|
+
add_default_actions
|
75
|
+
set_prefixes
|
76
|
+
end
|
77
|
+
|
78
|
+
alias_method :member_path, :path
|
79
|
+
alias_method :nesting_path_prefix, :path
|
80
|
+
end
|
81
|
+
|
69
82
|
# Creates named routes for implementing verb-oriented controllers. This is
|
70
83
|
# useful for implementing REST API's, where a single resource has different
|
71
84
|
# behavior based on the HTTP verb (method) used to access it.
|
@@ -145,7 +158,7 @@ module ActionController
|
|
145
158
|
#
|
146
159
|
# or
|
147
160
|
#
|
148
|
-
# <% form_for :message, @message, message_path(@message), :html => {:method => :put} do |f| %>
|
161
|
+
# <% form_for :message, @message, :url => message_path(@message), :html => {:method => :put} do |f| %>
|
149
162
|
#
|
150
163
|
# The #resources method accepts various options, too, to customize the resulting
|
151
164
|
# routes:
|
@@ -217,12 +230,87 @@ module ActionController
|
|
217
230
|
entities.each { |entity| map_resource entity, options.dup, &block }
|
218
231
|
end
|
219
232
|
|
233
|
+
# Creates named routes for implementing verb-oriented controllers for a singleton resource.
|
234
|
+
# A singleton resource is global to the current user visiting the application, such as a user's
|
235
|
+
# /account profile.
|
236
|
+
#
|
237
|
+
# See map.resources for general conventions. These are the main differences:
|
238
|
+
# - a singular name is given to map.resource. The default controller name is taken from the singular name.
|
239
|
+
# - To specify a custom plural name, use the :plural option. There is no :singular option
|
240
|
+
# - No default index, new, or create routes are created for the singleton resource controller.
|
241
|
+
# - When nesting singleton resources, only the singular name is used as the path prefix (example: 'account/messages/1')
|
242
|
+
#
|
243
|
+
# Example:
|
244
|
+
#
|
245
|
+
# map.resource :account
|
246
|
+
#
|
247
|
+
# class AccountController < ActionController::Base
|
248
|
+
# # POST account_url
|
249
|
+
# def create
|
250
|
+
# # create an account
|
251
|
+
# end
|
252
|
+
#
|
253
|
+
# # GET new_account_url
|
254
|
+
# def new
|
255
|
+
# # return an HTML form for describing the new account
|
256
|
+
# end
|
257
|
+
#
|
258
|
+
# # GET account_url
|
259
|
+
# def show
|
260
|
+
# # find and return the account
|
261
|
+
# end
|
262
|
+
#
|
263
|
+
# # GET edit_account_url
|
264
|
+
# def edit
|
265
|
+
# # return an HTML form for editing the account
|
266
|
+
# end
|
267
|
+
#
|
268
|
+
# # PUT account_url
|
269
|
+
# def update
|
270
|
+
# # find and update the account
|
271
|
+
# end
|
272
|
+
#
|
273
|
+
# # DELETE account_url
|
274
|
+
# def destroy
|
275
|
+
# # delete the account
|
276
|
+
# end
|
277
|
+
# end
|
278
|
+
#
|
279
|
+
# Along with the routes themselves, #resource generates named routes for use in
|
280
|
+
# controllers and views. <tt>map.resource :account</tt> produces the following named routes and helpers:
|
281
|
+
#
|
282
|
+
# Named Route Helpers
|
283
|
+
# account account_url, hash_for_account_url,
|
284
|
+
# account_path, hash_for_account_path
|
285
|
+
# edit_account edit_account_url, hash_for_edit_account_url,
|
286
|
+
# edit_account_path, hash_for_edit_account_path
|
287
|
+
def resource(*entities, &block)
|
288
|
+
options = entities.last.is_a?(Hash) ? entities.pop : { }
|
289
|
+
entities.each { |entity| map_singleton_resource entity, options.dup, &block }
|
290
|
+
end
|
291
|
+
|
220
292
|
private
|
221
293
|
def map_resource(entities, options = {}, &block)
|
222
294
|
resource = Resource.new(entities, options)
|
223
295
|
|
224
296
|
with_options :controller => resource.controller do |map|
|
225
297
|
map_collection_actions(map, resource)
|
298
|
+
map_default_collection_actions(map, resource)
|
299
|
+
map_new_actions(map, resource)
|
300
|
+
map_member_actions(map, resource)
|
301
|
+
|
302
|
+
if block_given?
|
303
|
+
with_options(:path_prefix => resource.nesting_path_prefix, &block)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def map_singleton_resource(entities, options = {}, &block)
|
309
|
+
resource = SingletonResource.new(entities, options)
|
310
|
+
|
311
|
+
with_options :controller => resource.controller do |map|
|
312
|
+
map_collection_actions(map, resource)
|
313
|
+
map_default_singleton_actions(map, resource)
|
226
314
|
map_new_actions(map, resource)
|
227
315
|
map_member_actions(map, resource)
|
228
316
|
|
@@ -234,67 +322,82 @@ module ActionController
|
|
234
322
|
|
235
323
|
def map_collection_actions(map, resource)
|
236
324
|
resource.collection_methods.each do |method, actions|
|
237
|
-
route_options = requirements_for(method)
|
238
|
-
|
239
325
|
actions.each do |action|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
route_options.merge(:action => action.to_s)
|
244
|
-
)
|
245
|
-
|
246
|
-
map.named_route(
|
247
|
-
"formatted_#{resource.name_prefix}#{action}_#{resource.plural}",
|
248
|
-
"#{resource.path}.:format;#{action}",
|
249
|
-
route_options.merge(:action => action.to_s)
|
250
|
-
)
|
326
|
+
action_options = action_options_for(action, resource, method)
|
327
|
+
map.named_route("#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path};#{action}", action_options)
|
328
|
+
map.named_route("formatted_#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path}.:format;#{action}", action_options)
|
251
329
|
end
|
252
330
|
end
|
331
|
+
end
|
253
332
|
|
254
|
-
|
255
|
-
|
333
|
+
def map_default_collection_actions(map, resource)
|
334
|
+
index_action_options = action_options_for("index", resource)
|
335
|
+
map.named_route("#{resource.name_prefix}#{resource.plural}", resource.path, index_action_options)
|
336
|
+
map.named_route("formatted_#{resource.name_prefix}#{resource.plural}", "#{resource.path}.:format", index_action_options)
|
337
|
+
|
338
|
+
create_action_options = action_options_for("create", resource)
|
339
|
+
map.connect(resource.path, create_action_options)
|
340
|
+
map.connect("#{resource.path}.:format", create_action_options)
|
341
|
+
end
|
256
342
|
|
257
|
-
|
258
|
-
|
343
|
+
def map_default_singleton_actions(map, resource)
|
344
|
+
create_action_options = action_options_for("create", resource)
|
345
|
+
map.connect(resource.path, create_action_options)
|
346
|
+
map.connect("#{resource.path}.:format", create_action_options)
|
259
347
|
end
|
260
348
|
|
261
349
|
def map_new_actions(map, resource)
|
262
350
|
resource.new_methods.each do |method, actions|
|
263
|
-
route_options = requirements_for(method)
|
264
351
|
actions.each do |action|
|
352
|
+
action_options = action_options_for(action, resource, method)
|
265
353
|
if action == :new
|
266
|
-
map.named_route("#{resource.name_prefix}new_#{resource.singular}", resource.new_path,
|
267
|
-
map.named_route("formatted_#{resource.name_prefix}new_#{resource.singular}", "#{resource.new_path}.:format",
|
354
|
+
map.named_route("#{resource.name_prefix}new_#{resource.singular}", resource.new_path, action_options)
|
355
|
+
map.named_route("formatted_#{resource.name_prefix}new_#{resource.singular}", "#{resource.new_path}.:format", action_options)
|
268
356
|
else
|
269
|
-
map.named_route("#{resource.name_prefix}#{action}_new_#{resource.singular}", "#{resource.new_path};#{action}",
|
270
|
-
map.named_route("formatted_#{resource.name_prefix}#{action}_new_#{resource.singular}", "#{resource.new_path}.:format;#{action}",
|
357
|
+
map.named_route("#{resource.name_prefix}#{action}_new_#{resource.singular}", "#{resource.new_path};#{action}", action_options)
|
358
|
+
map.named_route("formatted_#{resource.name_prefix}#{action}_new_#{resource.singular}", "#{resource.new_path}.:format;#{action}", action_options)
|
271
359
|
end
|
272
360
|
end
|
273
361
|
end
|
274
362
|
end
|
275
|
-
|
363
|
+
|
276
364
|
def map_member_actions(map, resource)
|
277
365
|
resource.member_methods.each do |method, actions|
|
278
|
-
route_options = requirements_for(method)
|
279
|
-
|
280
366
|
actions.each do |action|
|
281
|
-
|
282
|
-
map.named_route("
|
367
|
+
action_options = action_options_for(action, resource, method)
|
368
|
+
map.named_route("#{resource.name_prefix}#{action}_#{resource.singular}", "#{resource.member_path};#{action}", action_options)
|
369
|
+
map.named_route("formatted_#{resource.name_prefix}#{action}_#{resource.singular}", "#{resource.member_path}.:format;#{action}",action_options)
|
283
370
|
end
|
284
371
|
end
|
285
372
|
|
286
|
-
|
287
|
-
map.named_route("
|
373
|
+
show_action_options = action_options_for("show", resource)
|
374
|
+
map.named_route("#{resource.name_prefix}#{resource.singular}", resource.member_path, show_action_options)
|
375
|
+
map.named_route("formatted_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}.:format", show_action_options)
|
288
376
|
|
289
|
-
|
290
|
-
map.connect(
|
377
|
+
update_action_options = action_options_for("update", resource)
|
378
|
+
map.connect(resource.member_path, update_action_options)
|
379
|
+
map.connect("#{resource.member_path}.:format", update_action_options)
|
291
380
|
|
292
|
-
|
293
|
-
map.connect(
|
381
|
+
destroy_action_options = action_options_for("destroy", resource)
|
382
|
+
map.connect(resource.member_path, destroy_action_options)
|
383
|
+
map.connect("#{resource.member_path}.:format", destroy_action_options)
|
294
384
|
end
|
295
|
-
|
296
|
-
def
|
297
|
-
method == :any ? {} : { :
|
385
|
+
|
386
|
+
def conditions_for(method)
|
387
|
+
{ :conditions => method == :any ? {} : { :method => method } }
|
388
|
+
end
|
389
|
+
|
390
|
+
def action_options_for(action, resource, method = nil)
|
391
|
+
default_options = { :action => action.to_s }
|
392
|
+
require_id = resource.kind_of?(SingletonResource) ? {} : { :requirements => { :id => Regexp.new("[^#{Routing::SEPARATORS.join}]+") } }
|
393
|
+
case default_options[:action]
|
394
|
+
when "index", "new" : default_options.merge(conditions_for(method || :get))
|
395
|
+
when "create" : default_options.merge(conditions_for(method || :post))
|
396
|
+
when "show", "edit" : default_options.merge(conditions_for(method || :get)).merge(require_id)
|
397
|
+
when "update" : default_options.merge(conditions_for(method || :put)).merge(require_id)
|
398
|
+
when "destroy" : default_options.merge(conditions_for(method || :delete)).merge(require_id)
|
399
|
+
else default_options.merge(conditions_for(method))
|
400
|
+
end
|
298
401
|
end
|
299
402
|
end
|
300
403
|
end
|
@@ -126,7 +126,8 @@ module ActionController
|
|
126
126
|
# == Named routes
|
127
127
|
#
|
128
128
|
# Routes can be named with the syntax <tt>map.name_of_route options</tt>,
|
129
|
-
# allowing for easy reference within your source as +name_of_route_url
|
129
|
+
# allowing for easy reference within your source as +name_of_route_url+
|
130
|
+
# for the full URL and +name_of_route_path+ for the URI path.
|
130
131
|
#
|
131
132
|
# Example:
|
132
133
|
# # In routes.rb
|
@@ -137,29 +138,39 @@ module ActionController
|
|
137
138
|
#
|
138
139
|
# Arguments can be passed as well.
|
139
140
|
#
|
140
|
-
# redirect_to
|
141
|
+
# redirect_to show_item_path(:id => 25)
|
141
142
|
#
|
142
|
-
#
|
143
|
+
# Use <tt>map.root</tt> as a shorthand to name a route for the root path ""
|
143
144
|
#
|
144
|
-
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
145
|
+
# # In routes.rb
|
146
|
+
# map.root :controller => 'blogs'
|
147
|
+
#
|
148
|
+
# # would recognize http://www.example.com/ as
|
149
|
+
# params = { :controller => 'blogs', :action => 'index' }
|
150
|
+
#
|
151
|
+
# # and provide these named routes
|
152
|
+
# root_url # => 'http://www.example.com/'
|
153
|
+
# root_path # => ''
|
152
154
|
#
|
153
|
-
#
|
155
|
+
# Note: when using +with_options+, the route is simply named after the
|
156
|
+
# method you call on the block parameter rather than map.
|
154
157
|
#
|
155
|
-
#
|
158
|
+
# # In routes.rb
|
159
|
+
# map.with_options :controller => 'blog' do |blog|
|
160
|
+
# blog.show '', :action => 'list'
|
161
|
+
# blog.delete 'delete/:id', :action => 'delete',
|
162
|
+
# blog.edit 'edit/:id', :action => 'edit'
|
163
|
+
# end
|
164
|
+
#
|
165
|
+
# # provides named routes for show, delete, and edit
|
166
|
+
# link_to @article.title, show_path(:id => @article.id)
|
156
167
|
#
|
157
|
-
# == Pretty
|
168
|
+
# == Pretty URLs
|
158
169
|
#
|
159
170
|
# Routes can generate pretty URLs. For example:
|
160
171
|
#
|
161
172
|
# map.connect 'articles/:year/:month/:day',
|
162
|
-
#
|
173
|
+
# :controller => 'articles',
|
163
174
|
# :action => 'find_by_date',
|
164
175
|
# :year => /\d{4}/,
|
165
176
|
# :month => /\d{1,2}/,
|
@@ -1230,8 +1241,11 @@ module ActionController
|
|
1230
1241
|
|
1231
1242
|
if named_route
|
1232
1243
|
path = named_route.generate(options, merged, expire_on)
|
1233
|
-
|
1234
|
-
|
1244
|
+
if path.nil?
|
1245
|
+
raise_named_route_error(options, named_route, named_route_name)
|
1246
|
+
else
|
1247
|
+
return path
|
1248
|
+
end
|
1235
1249
|
else
|
1236
1250
|
merged[:action] ||= 'index'
|
1237
1251
|
options[:action] ||= 'index'
|
@@ -1251,6 +1265,18 @@ module ActionController
|
|
1251
1265
|
|
1252
1266
|
raise RoutingError, "No route matches #{options.inspect}"
|
1253
1267
|
end
|
1268
|
+
|
1269
|
+
# try to give a helpful error message when named route generation fails
|
1270
|
+
def raise_named_route_error(options, named_route, named_route_name)
|
1271
|
+
diff = named_route.requirements.diff(options)
|
1272
|
+
unless diff.empty?
|
1273
|
+
raise RoutingError, "#{named_route_name}_url failed to generate from #{options.inspect}, expected: #{named_route.requirements.inspect}, diff: #{named_route.requirements.diff(options).inspect}"
|
1274
|
+
else
|
1275
|
+
required_segments = named_route.segments.select {|seg| (!seg.optional?) && (!seg.is_a?(DividerSegment)) }
|
1276
|
+
required_keys_or_values = required_segments.map { |seg| seg.key rescue seg.value } # we want either the key or the value from the segment
|
1277
|
+
raise RoutingError, "#{named_route_name}_url failed to generate from #{options.inspect} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: #{required_keys_or_values.inspect} - are they all satisifed?"
|
1278
|
+
end
|
1279
|
+
end
|
1254
1280
|
|
1255
1281
|
def recognize(request)
|
1256
1282
|
params = recognize_path(request.path, extract_request_environment(request))
|