actionpack 3.0.0.beta4 → 3.0.0.rc
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 +36 -0
- data/{README → README.rdoc} +79 -137
- data/lib/abstract_controller.rb +1 -0
- data/lib/abstract_controller/asset_paths.rb +1 -1
- data/lib/abstract_controller/base.rb +3 -12
- data/lib/abstract_controller/rendering.rb +2 -2
- data/lib/abstract_controller/view_paths.rb +2 -1
- data/lib/action_controller.rb +1 -2
- data/lib/action_controller/base.rb +3 -9
- data/lib/action_controller/log_subscriber.rb +56 -0
- data/lib/action_controller/metal.rb +10 -3
- data/lib/action_controller/metal/helpers.rb +5 -4
- data/lib/action_controller/metal/hide_actions.rb +3 -3
- data/lib/action_controller/metal/instrumentation.rb +2 -1
- data/lib/action_controller/metal/mime_responds.rb +13 -10
- data/lib/action_controller/metal/rack_delegation.rb +0 -4
- data/lib/action_controller/metal/request_forgery_protection.rb +1 -1
- data/lib/action_controller/metal/rescue.rb +9 -0
- data/lib/action_controller/metal/responder.rb +13 -5
- data/lib/action_controller/metal/streaming.rb +2 -0
- data/lib/action_controller/metal/url_for.rb +5 -5
- data/lib/action_controller/railtie.rb +14 -23
- data/lib/action_controller/record_identifier.rb +6 -25
- data/lib/action_controller/test_case.rb +18 -6
- data/lib/action_controller/vendor/html-scanner/html/node.rb +1 -0
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +1 -0
- data/lib/action_dispatch.rb +6 -0
- data/lib/action_dispatch/http/cache.rb +2 -2
- data/lib/action_dispatch/http/filter_parameters.rb +10 -66
- data/lib/action_dispatch/http/mime_type.rb +1 -1
- data/lib/action_dispatch/http/parameter_filter.rb +72 -0
- data/lib/action_dispatch/http/parameters.rb +31 -2
- data/lib/action_dispatch/http/request.rb +4 -1
- data/lib/action_dispatch/http/upload.rb +2 -2
- data/lib/action_dispatch/middleware/callbacks.rb +4 -4
- data/lib/action_dispatch/middleware/cookies.rb +39 -6
- data/lib/action_dispatch/middleware/flash.rb +9 -2
- data/lib/action_dispatch/middleware/session/abstract_store.rb +121 -36
- data/lib/action_dispatch/middleware/session/cookie_store.rb +26 -19
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +9 -1
- data/lib/action_dispatch/middleware/show_exceptions.rb +2 -2
- data/lib/action_dispatch/middleware/stack.rb +12 -5
- data/lib/action_dispatch/railtie.rb +1 -1
- data/lib/action_dispatch/routing.rb +11 -13
- data/lib/action_dispatch/routing/deprecated_mapper.rb +6 -388
- data/lib/action_dispatch/routing/mapper.rb +364 -234
- data/lib/action_dispatch/routing/polymorphic_routes.rb +186 -0
- data/lib/action_dispatch/routing/route.rb +11 -2
- data/lib/action_dispatch/routing/route_set.rb +62 -28
- data/lib/action_dispatch/routing/url_for.rb +2 -1
- data/lib/action_dispatch/testing/assertions.rb +0 -2
- data/lib/action_dispatch/testing/assertions/routing.rb +0 -1
- data/lib/action_dispatch/testing/assertions/selector.rb +20 -24
- data/lib/action_dispatch/testing/integration.rb +2 -2
- data/lib/action_dispatch/testing/test_response.rb +2 -2
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_view.rb +1 -0
- data/lib/action_view/base.rb +20 -21
- data/lib/action_view/context.rb +9 -12
- data/lib/action_view/helpers.rb +0 -2
- data/lib/action_view/helpers/active_model_helper.rb +17 -2
- data/lib/action_view/helpers/asset_tag_helper.rb +15 -33
- data/lib/action_view/helpers/atom_feed_helper.rb +5 -3
- data/lib/action_view/helpers/cache_helper.rb +4 -2
- data/lib/action_view/helpers/capture_helper.rb +4 -4
- data/lib/action_view/helpers/csrf_helper.rb +3 -1
- data/lib/action_view/helpers/date_helper.rb +10 -5
- data/lib/action_view/helpers/debug_helper.rb +3 -1
- data/lib/action_view/helpers/form_helper.rb +36 -30
- data/lib/action_view/helpers/form_options_helper.rb +7 -6
- data/lib/action_view/helpers/form_tag_helper.rb +17 -6
- data/lib/action_view/helpers/javascript_helper.rb +1 -0
- data/lib/action_view/helpers/number_helper.rb +16 -45
- data/lib/action_view/helpers/prototype_helper.rb +14 -16
- data/lib/action_view/helpers/raw_output_helper.rb +9 -0
- data/lib/action_view/helpers/record_tag_helper.rb +5 -0
- data/lib/action_view/helpers/sanitize_helper.rb +26 -20
- data/lib/action_view/helpers/scriptaculous_helper.rb +6 -5
- data/lib/action_view/helpers/tag_helper.rb +2 -1
- data/lib/action_view/helpers/text_helper.rb +24 -111
- data/lib/action_view/helpers/translation_helper.rb +17 -10
- data/lib/action_view/helpers/url_helper.rb +26 -33
- data/lib/action_view/log_subscriber.rb +28 -0
- data/lib/action_view/lookup_context.rb +2 -0
- data/lib/action_view/paths.rb +1 -0
- data/lib/action_view/railtie.rb +15 -3
- data/lib/action_view/render/layouts.rb +2 -1
- data/lib/action_view/render/partials.rb +3 -1
- data/lib/action_view/render/rendering.rb +2 -1
- data/lib/action_view/template.rb +12 -8
- data/lib/action_view/template/error.rb +1 -0
- data/lib/action_view/template/handlers.rb +1 -0
- data/lib/action_view/template/resolver.rb +2 -1
- data/lib/action_view/template/text.rb +1 -0
- data/lib/action_view/test_case.rb +42 -20
- metadata +44 -23
- data/lib/action_controller/polymorphic_routes.rb +0 -182
- data/lib/action_controller/railties/log_subscriber.rb +0 -56
- data/lib/action_controller/railties/url_helpers.rb +0 -14
- data/lib/action_dispatch/testing/assertions/model.rb +0 -19
- data/lib/action_view/helpers/record_identification_helper.rb +0 -20
- data/lib/action_view/railties/log_subscriber.rb +0 -24
@@ -0,0 +1,186 @@
|
|
1
|
+
module ActionDispatch
|
2
|
+
module Routing
|
3
|
+
# Polymorphic URL helpers are methods for smart resolution to a named route call when
|
4
|
+
# given an Active Record model instance. They are to be used in combination with
|
5
|
+
# ActionController::Resources.
|
6
|
+
#
|
7
|
+
# These methods are useful when you want to generate correct URL or path to a RESTful
|
8
|
+
# resource without having to know the exact type of the record in question.
|
9
|
+
#
|
10
|
+
# Nested resources and/or namespaces are also supported, as illustrated in the example:
|
11
|
+
#
|
12
|
+
# polymorphic_url([:admin, @article, @comment])
|
13
|
+
#
|
14
|
+
# results in:
|
15
|
+
#
|
16
|
+
# admin_article_comment_url(@article, @comment)
|
17
|
+
#
|
18
|
+
# == Usage within the framework
|
19
|
+
#
|
20
|
+
# Polymorphic URL helpers are used in a number of places throughout the Rails framework:
|
21
|
+
#
|
22
|
+
# * <tt>url_for</tt>, so you can use it with a record as the argument, e.g.
|
23
|
+
# <tt>url_for(@article)</tt>;
|
24
|
+
# * ActionView::Helpers::FormHelper uses <tt>polymorphic_path</tt>, so you can write
|
25
|
+
# <tt>form_for(@article)</tt> without having to specify <tt>:url</tt> parameter for the form
|
26
|
+
# action;
|
27
|
+
# * <tt>redirect_to</tt> (which, in fact, uses <tt>url_for</tt>) so you can write
|
28
|
+
# <tt>redirect_to(post)</tt> in your controllers;
|
29
|
+
# * ActionView::Helpers::AtomFeedHelper, so you don't have to explicitly specify URLs
|
30
|
+
# for feed entries.
|
31
|
+
#
|
32
|
+
# == Prefixed polymorphic helpers
|
33
|
+
#
|
34
|
+
# In addition to <tt>polymorphic_url</tt> and <tt>polymorphic_path</tt> methods, a
|
35
|
+
# number of prefixed helpers are available as a shorthand to <tt>:action => "..."</tt>
|
36
|
+
# in options. Those are:
|
37
|
+
#
|
38
|
+
# * <tt>edit_polymorphic_url</tt>, <tt>edit_polymorphic_path</tt>
|
39
|
+
# * <tt>new_polymorphic_url</tt>, <tt>new_polymorphic_path</tt>
|
40
|
+
#
|
41
|
+
# Example usage:
|
42
|
+
#
|
43
|
+
# edit_polymorphic_path(@post) # => "/posts/1/edit"
|
44
|
+
# polymorphic_path(@post, :format => :pdf) # => "/posts/1.pdf"
|
45
|
+
module PolymorphicRoutes
|
46
|
+
# Constructs a call to a named RESTful route for the given record and returns the
|
47
|
+
# resulting URL string. For example:
|
48
|
+
#
|
49
|
+
# # calls post_url(post)
|
50
|
+
# polymorphic_url(post) # => "http://example.com/posts/1"
|
51
|
+
# polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1"
|
52
|
+
# polymorphic_url([:admin, blog, post]) # => "http://example.com/admin/blogs/1/posts/1"
|
53
|
+
# polymorphic_url([user, :blog, post]) # => "http://example.com/users/1/blog/posts/1"
|
54
|
+
# polymorphic_url(Comment) # => "http://example.com/comments"
|
55
|
+
#
|
56
|
+
# ==== Options
|
57
|
+
#
|
58
|
+
# * <tt>:action</tt> - Specifies the action prefix for the named route:
|
59
|
+
# <tt>:new</tt> or <tt>:edit</tt>. Default is no prefix.
|
60
|
+
# * <tt>:routing_type</tt> - Allowed values are <tt>:path</tt> or <tt>:url</tt>.
|
61
|
+
# Default is <tt>:url</tt>.
|
62
|
+
#
|
63
|
+
# ==== Examples
|
64
|
+
#
|
65
|
+
# # an Article record
|
66
|
+
# polymorphic_url(record) # same as article_url(record)
|
67
|
+
#
|
68
|
+
# # a Comment record
|
69
|
+
# polymorphic_url(record) # same as comment_url(record)
|
70
|
+
#
|
71
|
+
# # it recognizes new records and maps to the collection
|
72
|
+
# record = Comment.new
|
73
|
+
# polymorphic_url(record) # same as comments_url()
|
74
|
+
#
|
75
|
+
# # the class of a record will also map to the collection
|
76
|
+
# polymorphic_url(Comment) # same as comments_url()
|
77
|
+
#
|
78
|
+
def polymorphic_url(record_or_hash_or_array, options = {})
|
79
|
+
if record_or_hash_or_array.kind_of?(Array)
|
80
|
+
record_or_hash_or_array = record_or_hash_or_array.compact
|
81
|
+
record_or_hash_or_array = record_or_hash_or_array[0] if record_or_hash_or_array.size == 1
|
82
|
+
end
|
83
|
+
|
84
|
+
record = extract_record(record_or_hash_or_array)
|
85
|
+
record = record.to_model if record.respond_to?(:to_model)
|
86
|
+
|
87
|
+
args = case record_or_hash_or_array
|
88
|
+
when Hash; [ record_or_hash_or_array ]
|
89
|
+
when Array; record_or_hash_or_array.dup
|
90
|
+
else [ record_or_hash_or_array ]
|
91
|
+
end
|
92
|
+
|
93
|
+
inflection = if options[:action].to_s == "new"
|
94
|
+
args.pop
|
95
|
+
:singular
|
96
|
+
elsif (record.respond_to?(:persisted?) && !record.persisted?)
|
97
|
+
args.pop
|
98
|
+
:plural
|
99
|
+
elsif record.is_a?(Class)
|
100
|
+
args.pop
|
101
|
+
:plural
|
102
|
+
else
|
103
|
+
:singular
|
104
|
+
end
|
105
|
+
|
106
|
+
args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
|
107
|
+
named_route = build_named_route_call(record_or_hash_or_array, inflection, options)
|
108
|
+
|
109
|
+
url_options = options.except(:action, :routing_type)
|
110
|
+
unless url_options.empty?
|
111
|
+
args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options
|
112
|
+
end
|
113
|
+
|
114
|
+
send(named_route, *args)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns the path component of a URL for the given record. It uses
|
118
|
+
# <tt>polymorphic_url</tt> with <tt>:routing_type => :path</tt>.
|
119
|
+
def polymorphic_path(record_or_hash_or_array, options = {})
|
120
|
+
polymorphic_url(record_or_hash_or_array, options.merge(:routing_type => :path))
|
121
|
+
end
|
122
|
+
|
123
|
+
%w(edit new).each do |action|
|
124
|
+
module_eval <<-EOT, __FILE__, __LINE__ + 1
|
125
|
+
def #{action}_polymorphic_url(record_or_hash, options = {}) # def edit_polymorphic_url(record_or_hash, options = {})
|
126
|
+
polymorphic_url( # polymorphic_url(
|
127
|
+
record_or_hash, # record_or_hash,
|
128
|
+
options.merge(:action => "#{action}")) # options.merge(:action => "edit"))
|
129
|
+
end # end
|
130
|
+
#
|
131
|
+
def #{action}_polymorphic_path(record_or_hash, options = {}) # def edit_polymorphic_path(record_or_hash, options = {})
|
132
|
+
polymorphic_url( # polymorphic_url(
|
133
|
+
record_or_hash, # record_or_hash,
|
134
|
+
options.merge(:action => "#{action}", :routing_type => :path)) # options.merge(:action => "edit", :routing_type => :path))
|
135
|
+
end # end
|
136
|
+
EOT
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
def action_prefix(options)
|
141
|
+
options[:action] ? "#{options[:action]}_" : ''
|
142
|
+
end
|
143
|
+
|
144
|
+
def routing_type(options)
|
145
|
+
options[:routing_type] || :url
|
146
|
+
end
|
147
|
+
|
148
|
+
def build_named_route_call(records, inflection, options = {})
|
149
|
+
unless records.is_a?(Array)
|
150
|
+
record = extract_record(records)
|
151
|
+
route = ''
|
152
|
+
else
|
153
|
+
record = records.pop
|
154
|
+
route = records.inject("") do |string, parent|
|
155
|
+
if parent.is_a?(Symbol) || parent.is_a?(String)
|
156
|
+
string << "#{parent}_"
|
157
|
+
else
|
158
|
+
string << ActiveModel::Naming.plural(parent).singularize
|
159
|
+
string << "_"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
if record.is_a?(Symbol) || record.is_a?(String)
|
165
|
+
route << "#{record}_"
|
166
|
+
else
|
167
|
+
route << ActiveModel::Naming.plural(record)
|
168
|
+
route = route.singularize if inflection == :singular
|
169
|
+
route << "_"
|
170
|
+
route << "index_" if ActiveModel::Naming.uncountable?(record) && inflection == :plural
|
171
|
+
end
|
172
|
+
|
173
|
+
action_prefix(options) + route + routing_type(options).to_s
|
174
|
+
end
|
175
|
+
|
176
|
+
def extract_record(record_or_hash_or_array)
|
177
|
+
case record_or_hash_or_array
|
178
|
+
when Array; record_or_hash_or_array.last
|
179
|
+
when Hash; record_or_hash_or_array[:id]
|
180
|
+
else record_or_hash_or_array
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
@@ -2,9 +2,10 @@ module ActionDispatch
|
|
2
2
|
module Routing
|
3
3
|
class Route #:nodoc:
|
4
4
|
attr_reader :app, :conditions, :defaults, :name
|
5
|
-
attr_reader :path, :requirements
|
5
|
+
attr_reader :path, :requirements, :set
|
6
6
|
|
7
|
-
def initialize(app, conditions, requirements, defaults, name, anchor)
|
7
|
+
def initialize(set, app, conditions, requirements, defaults, name, anchor)
|
8
|
+
@set = set
|
8
9
|
@app = app
|
9
10
|
@defaults = defaults
|
10
11
|
@name = name
|
@@ -24,6 +25,9 @@ module ActionDispatch
|
|
24
25
|
h[k] = Rack::Mount::RegexpWithNamedGroups.new(v)
|
25
26
|
h
|
26
27
|
}
|
28
|
+
|
29
|
+
@conditions.delete_if{ |k,v| k != :path_info && !valid_condition?(k) }
|
30
|
+
@requirements.delete_if{ |k,v| !valid_condition?(k) }
|
27
31
|
end
|
28
32
|
|
29
33
|
def verb
|
@@ -50,6 +54,11 @@ module ActionDispatch
|
|
50
54
|
"%-6s %-40s %s" % [(verb || :any).to_s.upcase, path, requirements.inspect]
|
51
55
|
end
|
52
56
|
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def valid_condition?(method)
|
60
|
+
segment_keys.include?(method) || set.valid_conditions.include?(method)
|
61
|
+
end
|
53
62
|
end
|
54
63
|
end
|
55
64
|
end
|
@@ -24,7 +24,7 @@ module ActionDispatch
|
|
24
24
|
return [404, {'X-Cascade' => 'pass'}, []]
|
25
25
|
end
|
26
26
|
|
27
|
-
controller
|
27
|
+
dispatch(controller, params[:action], env)
|
28
28
|
end
|
29
29
|
|
30
30
|
def prepare_params!(params)
|
@@ -32,29 +32,43 @@ module ActionDispatch
|
|
32
32
|
split_glob_param!(params) if @glob_param
|
33
33
|
end
|
34
34
|
|
35
|
-
|
35
|
+
# If this is a default_controller (i.e. a controller specified by the user)
|
36
|
+
# we should raise an error in case it's not found, because it usually means
|
37
|
+
# an user error. However, if the controller was retrieved through a dynamic
|
38
|
+
# segment, as in :controller(/:action), we should simply return nil and
|
39
|
+
# delegate the control back to Rack cascade. Besides, if this is not a default
|
40
|
+
# controller, it means we should respect the @scope[:module] parameter.
|
41
|
+
def controller(params, default_controller=true)
|
36
42
|
if params && params.key?(:controller)
|
37
43
|
controller_param = params[:controller]
|
38
|
-
|
39
|
-
controller_name = "#{controller_param.camelize}Controller"
|
40
|
-
controller = @controllers[controller_param] =
|
41
|
-
ActiveSupport::Dependencies.ref(controller_name)
|
42
|
-
end
|
43
|
-
|
44
|
-
controller.get
|
44
|
+
controller_reference(controller_param)
|
45
45
|
end
|
46
46
|
rescue NameError => e
|
47
|
-
raise ActionController::RoutingError, e.message, e.backtrace if
|
47
|
+
raise ActionController::RoutingError, e.message, e.backtrace if default_controller
|
48
48
|
end
|
49
49
|
|
50
|
-
|
51
|
-
def merge_default_action!(params)
|
52
|
-
params[:action] ||= 'index'
|
53
|
-
end
|
50
|
+
private
|
54
51
|
|
55
|
-
|
56
|
-
|
52
|
+
def controller_reference(controller_param)
|
53
|
+
unless controller = @controllers[controller_param]
|
54
|
+
controller_name = "#{controller_param.camelize}Controller"
|
55
|
+
controller = @controllers[controller_param] =
|
56
|
+
ActiveSupport::Dependencies.ref(controller_name)
|
57
57
|
end
|
58
|
+
controller.get
|
59
|
+
end
|
60
|
+
|
61
|
+
def dispatch(controller, action, env)
|
62
|
+
controller.action(action).call(env)
|
63
|
+
end
|
64
|
+
|
65
|
+
def merge_default_action!(params)
|
66
|
+
params[:action] ||= 'index'
|
67
|
+
end
|
68
|
+
|
69
|
+
def split_glob_param!(params)
|
70
|
+
params[@glob_param] = params[@glob_param].split('/').map { |v| URI.unescape(v) }
|
71
|
+
end
|
58
72
|
end
|
59
73
|
|
60
74
|
# A NamedRouteCollection instance is a collection of named routes, and also
|
@@ -185,9 +199,9 @@ module ActionDispatch
|
|
185
199
|
end
|
186
200
|
end
|
187
201
|
|
188
|
-
attr_accessor :routes, :named_routes
|
202
|
+
attr_accessor :set, :routes, :named_routes
|
189
203
|
attr_accessor :disable_clear_and_finalize, :resources_path_names
|
190
|
-
attr_accessor :default_url_options, :request_class
|
204
|
+
attr_accessor :default_url_options, :request_class, :valid_conditions
|
191
205
|
|
192
206
|
def self.default_resources_path_names
|
193
207
|
{ :new => 'new', :edit => 'edit' }
|
@@ -199,7 +213,11 @@ module ActionDispatch
|
|
199
213
|
self.resources_path_names = self.class.default_resources_path_names.dup
|
200
214
|
self.controller_namespaces = Set.new
|
201
215
|
self.default_url_options = {}
|
216
|
+
|
202
217
|
self.request_class = request_class
|
218
|
+
self.valid_conditions = request_class.public_instance_methods.map { |m| m.to_sym }
|
219
|
+
self.valid_conditions.delete(:id)
|
220
|
+
self.valid_conditions.push(:controller, :action)
|
203
221
|
|
204
222
|
@disable_clear_and_finalize = false
|
205
223
|
clear!
|
@@ -262,10 +280,10 @@ module ActionDispatch
|
|
262
280
|
# Yes plz - JP
|
263
281
|
included do
|
264
282
|
routes.install_helpers(self)
|
265
|
-
singleton_class.send(:define_method, :
|
283
|
+
singleton_class.send(:define_method, :_routes) { routes }
|
266
284
|
end
|
267
285
|
|
268
|
-
define_method(:
|
286
|
+
define_method(:_routes) { routes }
|
269
287
|
end
|
270
288
|
|
271
289
|
helpers
|
@@ -277,7 +295,7 @@ module ActionDispatch
|
|
277
295
|
end
|
278
296
|
|
279
297
|
def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true)
|
280
|
-
route = Route.new(app, conditions, requirements, defaults, name, anchor)
|
298
|
+
route = Route.new(self, app, conditions, requirements, defaults, name, anchor)
|
281
299
|
@set.add_route(*route)
|
282
300
|
named_routes[name] = route if name
|
283
301
|
routes << route
|
@@ -312,7 +330,11 @@ module ActionDispatch
|
|
312
330
|
|
313
331
|
def use_recall_for(key)
|
314
332
|
if @recall[key] && (!@options.key?(key) || @options[key] == @recall[key])
|
315
|
-
|
333
|
+
if named_route_exists?
|
334
|
+
@options[key] = @recall.delete(key) if segment_keys.include?(key)
|
335
|
+
else
|
336
|
+
@options[key] = @recall.delete(key)
|
337
|
+
end
|
316
338
|
end
|
317
339
|
end
|
318
340
|
|
@@ -371,7 +393,7 @@ module ActionDispatch
|
|
371
393
|
|
372
394
|
def generate
|
373
395
|
error = ActionController::RoutingError.new("No route matches #{options.inspect}")
|
374
|
-
path, params = @set.generate(:path_info, named_route, options, recall, opts)
|
396
|
+
path, params = @set.set.generate(:path_info, named_route, options, recall, opts)
|
375
397
|
|
376
398
|
raise error unless path
|
377
399
|
|
@@ -392,7 +414,8 @@ module ActionDispatch
|
|
392
414
|
elsif value.is_a?(Array)
|
393
415
|
value.map { |v| Rack::Mount::Utils.escape_uri(v.to_param) }.join('/')
|
394
416
|
else
|
395
|
-
|
417
|
+
return nil unless param = value.to_param
|
418
|
+
param.split('/').map { |v| Rack::Mount::Utils.escape_uri(v) }.join("/")
|
396
419
|
end
|
397
420
|
end
|
398
421
|
{:parameterize => parameterize}
|
@@ -402,6 +425,15 @@ module ActionDispatch
|
|
402
425
|
return false unless current_controller
|
403
426
|
controller.to_param != current_controller.to_param
|
404
427
|
end
|
428
|
+
|
429
|
+
private
|
430
|
+
def named_route_exists?
|
431
|
+
named_route && set.named_routes[named_route]
|
432
|
+
end
|
433
|
+
|
434
|
+
def segment_keys
|
435
|
+
set.named_routes[named_route].segment_keys
|
436
|
+
end
|
405
437
|
end
|
406
438
|
|
407
439
|
# Generate the path indicated by the arguments, and return an array of
|
@@ -415,14 +447,14 @@ module ActionDispatch
|
|
415
447
|
end
|
416
448
|
|
417
449
|
def generate(options, recall = {}, extras = false)
|
418
|
-
Generator.new(options, recall,
|
450
|
+
Generator.new(options, recall, self, extras).generate
|
419
451
|
end
|
420
452
|
|
421
453
|
RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash]
|
422
454
|
|
423
455
|
def url_for(options)
|
424
456
|
finalize!
|
425
|
-
options =
|
457
|
+
options = (options || {}).reverse_merge!(default_url_options)
|
426
458
|
|
427
459
|
handle_positional_args(options)
|
428
460
|
|
@@ -445,9 +477,9 @@ module ActionDispatch
|
|
445
477
|
path_options = yield(path_options) if block_given?
|
446
478
|
path = generate(path_options, path_segments || {})
|
447
479
|
|
448
|
-
# ROUTES TODO: This can be called directly, so script_name should probably be set in the
|
480
|
+
# ROUTES TODO: This can be called directly, so script_name should probably be set in the routes
|
449
481
|
rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path)
|
450
|
-
rewritten_url << "##{Rack::Utils.
|
482
|
+
rewritten_url << "##{Rack::Mount::Utils.escape_uri(options[:anchor].to_param.to_s)}" if options[:anchor]
|
451
483
|
|
452
484
|
rewritten_url
|
453
485
|
end
|
@@ -477,6 +509,8 @@ module ActionDispatch
|
|
477
509
|
end
|
478
510
|
|
479
511
|
dispatcher = route.app
|
512
|
+
dispatcher = dispatcher.app while dispatcher.is_a?(Mapper::Constraints)
|
513
|
+
|
480
514
|
if dispatcher.is_a?(Dispatcher) && dispatcher.controller(params, false)
|
481
515
|
dispatcher.prepare_params!(params)
|
482
516
|
return params
|
@@ -82,6 +82,7 @@ module ActionDispatch
|
|
82
82
|
#
|
83
83
|
module UrlFor
|
84
84
|
extend ActiveSupport::Concern
|
85
|
+
include PolymorphicRoutes
|
85
86
|
|
86
87
|
included do
|
87
88
|
# TODO: with_routing extends @controller with url_helpers, trickling down to including this module which overrides its default_url_options
|
@@ -128,7 +129,7 @@ module ActionDispatch
|
|
128
129
|
when String
|
129
130
|
options
|
130
131
|
when nil, Hash
|
131
|
-
|
132
|
+
_routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys)
|
132
133
|
else
|
133
134
|
polymorphic_url(options)
|
134
135
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module ActionDispatch
|
2
2
|
module Assertions
|
3
3
|
autoload :DomAssertions, 'action_dispatch/testing/assertions/dom'
|
4
|
-
autoload :ModelAssertions, 'action_dispatch/testing/assertions/model'
|
5
4
|
autoload :ResponseAssertions, 'action_dispatch/testing/assertions/response'
|
6
5
|
autoload :RoutingAssertions, 'action_dispatch/testing/assertions/routing'
|
7
6
|
autoload :SelectorAssertions, 'action_dispatch/testing/assertions/selector'
|
@@ -11,7 +10,6 @@ module ActionDispatch
|
|
11
10
|
|
12
11
|
included do
|
13
12
|
include DomAssertions
|
14
|
-
include ModelAssertions
|
15
13
|
include ResponseAssertions
|
16
14
|
include RoutingAssertions
|
17
15
|
include SelectorAssertions
|
@@ -53,7 +53,6 @@ module ActionDispatch
|
|
53
53
|
extras.each_key { |key| expected_options.delete key } unless extras.nil?
|
54
54
|
|
55
55
|
expected_options.stringify_keys!
|
56
|
-
routing_diff = expected_options.diff(request.path_parameters)
|
57
56
|
msg = build_message(message, "The recognized options <?> did not match <?>, difference: <?>",
|
58
57
|
request.path_parameters, expected_options, expected_options.diff(request.path_parameters))
|
59
58
|
assert_block(msg) { request.path_parameters == expected_options }
|