actionpack 3.2.22.5 → 4.0.0.beta1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +641 -418
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -288
- data/lib/abstract_controller.rb +1 -8
- data/lib/abstract_controller/asset_paths.rb +2 -2
- data/lib/abstract_controller/base.rb +39 -37
- data/lib/abstract_controller/callbacks.rb +101 -82
- data/lib/abstract_controller/collector.rb +7 -3
- data/lib/abstract_controller/helpers.rb +23 -11
- data/lib/abstract_controller/layouts.rb +68 -73
- data/lib/abstract_controller/logger.rb +1 -2
- data/lib/abstract_controller/rendering.rb +22 -13
- data/lib/abstract_controller/translation.rb +16 -1
- data/lib/abstract_controller/url_for.rb +6 -6
- data/lib/abstract_controller/view_paths.rb +1 -1
- data/lib/action_controller.rb +15 -6
- data/lib/action_controller/base.rb +46 -22
- data/lib/action_controller/caching.rb +46 -33
- data/lib/action_controller/caching/fragments.rb +23 -53
- data/lib/action_controller/deprecated.rb +5 -1
- data/lib/action_controller/deprecated/integration_test.rb +3 -0
- data/lib/action_controller/log_subscriber.rb +11 -8
- data/lib/action_controller/metal.rb +16 -30
- data/lib/action_controller/metal/conditional_get.rb +76 -32
- data/lib/action_controller/metal/data_streaming.rb +20 -26
- data/lib/action_controller/metal/exceptions.rb +19 -6
- data/lib/action_controller/metal/flash.rb +24 -9
- data/lib/action_controller/metal/force_ssl.rb +32 -9
- data/lib/action_controller/metal/head.rb +25 -4
- data/lib/action_controller/metal/helpers.rb +6 -9
- data/lib/action_controller/metal/hide_actions.rb +1 -2
- data/lib/action_controller/metal/http_authentication.rb +105 -87
- data/lib/action_controller/metal/implicit_render.rb +1 -1
- data/lib/action_controller/metal/instrumentation.rb +2 -1
- data/lib/action_controller/metal/live.rb +141 -0
- data/lib/action_controller/metal/mime_responds.rb +161 -47
- data/lib/action_controller/metal/params_wrapper.rb +112 -74
- data/lib/action_controller/metal/rack_delegation.rb +9 -3
- data/lib/action_controller/metal/redirecting.rb +15 -20
- data/lib/action_controller/metal/renderers.rb +11 -9
- data/lib/action_controller/metal/rendering.rb +8 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +112 -19
- data/lib/action_controller/metal/responder.rb +20 -19
- data/lib/action_controller/metal/streaming.rb +12 -18
- data/lib/action_controller/metal/strong_parameters.rb +516 -0
- data/lib/action_controller/metal/testing.rb +13 -18
- data/lib/action_controller/metal/url_for.rb +27 -25
- data/lib/action_controller/model_naming.rb +12 -0
- data/lib/action_controller/railtie.rb +33 -17
- data/lib/action_controller/railties/helpers.rb +22 -0
- data/lib/action_controller/record_identifier.rb +18 -72
- data/lib/action_controller/test_case.rb +215 -123
- data/lib/action_controller/vendor/html-scanner.rb +4 -19
- data/lib/action_dispatch.rb +27 -19
- data/lib/action_dispatch/http/cache.rb +63 -11
- data/lib/action_dispatch/http/filter_parameters.rb +18 -8
- data/lib/action_dispatch/http/filter_redirect.rb +37 -0
- data/lib/action_dispatch/http/headers.rb +27 -19
- data/lib/action_dispatch/http/mime_negotiation.rb +25 -2
- data/lib/action_dispatch/http/mime_type.rb +145 -113
- data/lib/action_dispatch/http/mime_types.rb +1 -1
- data/lib/action_dispatch/http/parameter_filter.rb +44 -46
- data/lib/action_dispatch/http/parameters.rb +12 -5
- data/lib/action_dispatch/http/rack_cache.rb +2 -3
- data/lib/action_dispatch/http/request.rb +49 -18
- data/lib/action_dispatch/http/response.rb +129 -35
- data/lib/action_dispatch/http/upload.rb +60 -17
- data/lib/action_dispatch/http/url.rb +53 -31
- data/lib/action_dispatch/journey.rb +5 -0
- data/lib/action_dispatch/journey/backwards.rb +5 -0
- data/lib/action_dispatch/journey/formatter.rb +146 -0
- data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +44 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +156 -0
- data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
- data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
- data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
- data/lib/action_dispatch/journey/nodes/node.rb +124 -0
- data/lib/action_dispatch/journey/parser.rb +206 -0
- data/lib/action_dispatch/journey/parser.y +47 -0
- data/lib/action_dispatch/journey/parser_extras.rb +23 -0
- data/lib/action_dispatch/journey/path/pattern.rb +196 -0
- data/lib/action_dispatch/journey/route.rb +116 -0
- data/lib/action_dispatch/journey/router.rb +164 -0
- data/lib/action_dispatch/journey/router/strexp.rb +24 -0
- data/lib/action_dispatch/journey/router/utils.rb +54 -0
- data/lib/action_dispatch/journey/routes.rb +75 -0
- data/lib/action_dispatch/journey/scanner.rb +61 -0
- data/lib/action_dispatch/journey/visitors.rb +189 -0
- data/lib/action_dispatch/journey/visualizer/fsm.css +34 -0
- data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
- data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
- data/lib/action_dispatch/middleware/callbacks.rb +9 -4
- data/lib/action_dispatch/middleware/cookies.rb +168 -57
- data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -17
- data/lib/action_dispatch/middleware/exception_wrapper.rb +27 -3
- data/lib/action_dispatch/middleware/flash.rb +58 -58
- data/lib/action_dispatch/middleware/params_parser.rb +14 -29
- data/lib/action_dispatch/middleware/public_exceptions.rb +31 -14
- data/lib/action_dispatch/middleware/reloader.rb +6 -6
- data/lib/action_dispatch/middleware/remote_ip.rb +145 -39
- data/lib/action_dispatch/middleware/request_id.rb +2 -6
- data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
- data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +81 -7
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +12 -45
- data/lib/action_dispatch/middleware/ssl.rb +70 -0
- data/lib/action_dispatch/middleware/stack.rb +6 -1
- data/lib/action_dispatch/middleware/static.rb +5 -24
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +14 -11
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +25 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +15 -9
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +121 -5
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +7 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +30 -15
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +39 -13
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +6 -2
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +144 -0
- data/lib/action_dispatch/railtie.rb +16 -6
- data/lib/action_dispatch/request/session.rb +181 -0
- data/lib/action_dispatch/routing.rb +41 -40
- data/lib/action_dispatch/routing/inspector.rb +240 -0
- data/lib/action_dispatch/routing/mapper.rb +501 -273
- data/lib/action_dispatch/routing/polymorphic_routes.rb +16 -20
- data/lib/action_dispatch/routing/redirection.rb +46 -29
- data/lib/action_dispatch/routing/route_set.rb +203 -164
- data/lib/action_dispatch/routing/routes_proxy.rb +2 -0
- data/lib/action_dispatch/routing/url_for.rb +48 -33
- data/lib/action_dispatch/testing/assertions/dom.rb +3 -13
- data/lib/action_dispatch/testing/assertions/response.rb +32 -40
- data/lib/action_dispatch/testing/assertions/routing.rb +40 -39
- data/lib/action_dispatch/testing/assertions/selector.rb +15 -20
- data/lib/action_dispatch/testing/assertions/tag.rb +20 -23
- data/lib/action_dispatch/testing/integration.rb +41 -22
- data/lib/action_dispatch/testing/test_process.rb +9 -6
- data/lib/action_dispatch/testing/test_request.rb +7 -3
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +4 -4
- data/lib/action_view.rb +17 -8
- data/lib/action_view/base.rb +15 -34
- data/lib/action_view/buffers.rb +1 -1
- data/lib/action_view/context.rb +4 -4
- data/lib/action_view/dependency_tracker.rb +91 -0
- data/lib/action_view/digestor.rb +85 -0
- data/lib/action_view/flows.rb +1 -4
- data/lib/action_view/helpers.rb +2 -4
- data/lib/action_view/helpers/active_model_helper.rb +3 -4
- data/lib/action_view/helpers/asset_tag_helper.rb +211 -353
- data/lib/action_view/helpers/asset_url_helper.rb +354 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +13 -10
- data/lib/action_view/helpers/cache_helper.rb +150 -18
- data/lib/action_view/helpers/capture_helper.rb +42 -29
- data/lib/action_view/helpers/csrf_helper.rb +0 -2
- data/lib/action_view/helpers/date_helper.rb +268 -247
- data/lib/action_view/helpers/debug_helper.rb +10 -11
- data/lib/action_view/helpers/form_helper.rb +904 -547
- data/lib/action_view/helpers/form_options_helper.rb +341 -166
- data/lib/action_view/helpers/form_tag_helper.rb +188 -88
- data/lib/action_view/helpers/javascript_helper.rb +23 -16
- data/lib/action_view/helpers/number_helper.rb +148 -354
- data/lib/action_view/helpers/output_safety_helper.rb +3 -3
- data/lib/action_view/helpers/record_tag_helper.rb +17 -22
- data/lib/action_view/helpers/rendering_helper.rb +2 -4
- data/lib/action_view/helpers/sanitize_helper.rb +3 -6
- data/lib/action_view/helpers/tag_helper.rb +43 -37
- data/lib/action_view/helpers/tags.rb +39 -0
- data/lib/action_view/helpers/tags/base.rb +148 -0
- data/lib/action_view/helpers/tags/check_box.rb +64 -0
- data/lib/action_view/helpers/tags/checkable.rb +16 -0
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +43 -0
- data/lib/action_view/helpers/tags/collection_helpers.rb +83 -0
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
- data/lib/action_view/helpers/tags/collection_select.rb +28 -0
- data/lib/action_view/helpers/tags/color_field.rb +25 -0
- data/lib/action_view/helpers/tags/date_field.rb +13 -0
- data/lib/action_view/helpers/tags/date_select.rb +72 -0
- data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
- data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
- data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
- data/lib/action_view/helpers/tags/email_field.rb +8 -0
- data/lib/action_view/helpers/tags/file_field.rb +8 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
- data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
- data/lib/action_view/helpers/tags/label.rb +65 -0
- data/lib/action_view/helpers/tags/month_field.rb +13 -0
- data/lib/action_view/helpers/tags/number_field.rb +18 -0
- data/lib/action_view/helpers/tags/password_field.rb +12 -0
- data/lib/action_view/helpers/tags/radio_button.rb +31 -0
- data/lib/action_view/helpers/tags/range_field.rb +8 -0
- data/lib/action_view/helpers/tags/search_field.rb +24 -0
- data/lib/action_view/helpers/tags/select.rb +41 -0
- data/lib/action_view/helpers/tags/tel_field.rb +8 -0
- data/lib/action_view/helpers/tags/text_area.rb +18 -0
- data/lib/action_view/helpers/tags/text_field.rb +29 -0
- data/lib/action_view/helpers/tags/time_field.rb +13 -0
- data/lib/action_view/helpers/tags/time_select.rb +8 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
- data/lib/action_view/helpers/tags/url_field.rb +8 -0
- data/lib/action_view/helpers/tags/week_field.rb +13 -0
- data/lib/action_view/helpers/text_helper.rb +126 -113
- data/lib/action_view/helpers/translation_helper.rb +32 -16
- data/lib/action_view/helpers/url_helper.rb +200 -271
- data/lib/action_view/locale/en.yml +1 -105
- data/lib/action_view/log_subscriber.rb +6 -4
- data/lib/action_view/lookup_context.rb +15 -39
- data/lib/action_view/model_naming.rb +12 -0
- data/lib/action_view/path_set.rb +9 -39
- data/lib/action_view/railtie.rb +6 -22
- data/lib/action_view/record_identifier.rb +84 -0
- data/lib/action_view/renderer/abstract_renderer.rb +10 -19
- data/lib/action_view/renderer/partial_renderer.rb +144 -81
- data/lib/action_view/renderer/renderer.rb +2 -19
- data/lib/action_view/renderer/streaming_template_renderer.rb +2 -5
- data/lib/action_view/renderer/template_renderer.rb +14 -13
- data/lib/action_view/routing_url_for.rb +107 -0
- data/lib/action_view/template.rb +22 -21
- data/lib/action_view/template/error.rb +22 -12
- data/lib/action_view/template/handlers.rb +12 -9
- data/lib/action_view/template/handlers/builder.rb +1 -1
- data/lib/action_view/template/handlers/erb.rb +11 -16
- data/lib/action_view/template/handlers/raw.rb +11 -0
- data/lib/action_view/template/resolver.rb +111 -83
- data/lib/action_view/template/text.rb +12 -8
- data/lib/action_view/template/types.rb +57 -0
- data/lib/action_view/test_case.rb +66 -43
- data/lib/action_view/testing/resolvers.rb +3 -2
- data/lib/action_view/vendor/html-scanner.rb +20 -0
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/document.rb +0 -0
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/node.rb +12 -12
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/sanitizer.rb +18 -7
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/selector.rb +1 -1
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/tokenizer.rb +1 -1
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/version.rb +0 -0
- metadata +135 -125
- data/lib/action_controller/caching/actions.rb +0 -185
- data/lib/action_controller/caching/pages.rb +0 -187
- data/lib/action_controller/caching/sweeping.rb +0 -97
- data/lib/action_controller/deprecated/performance_test.rb +0 -1
- data/lib/action_controller/metal/compatibility.rb +0 -65
- data/lib/action_controller/metal/session_management.rb +0 -14
- data/lib/action_controller/railties/paths.rb +0 -25
- data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
- data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
- data/lib/action_dispatch/middleware/head.rb +0 -18
- data/lib/action_dispatch/middleware/rescue.rb +0 -26
- data/lib/action_dispatch/testing/performance_test.rb +0 -10
- data/lib/action_view/asset_paths.rb +0 -142
- data/lib/action_view/helpers/asset_paths.rb +0 -7
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
- data/lib/sprockets/assets.rake +0 -99
- data/lib/sprockets/bootstrap.rb +0 -37
- data/lib/sprockets/compressors.rb +0 -83
- data/lib/sprockets/helpers.rb +0 -6
- data/lib/sprockets/helpers/isolated_helper.rb +0 -13
- data/lib/sprockets/helpers/rails_helper.rb +0 -182
- data/lib/sprockets/railtie.rb +0 -62
- data/lib/sprockets/static_compiler.rb +0 -56
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'action_controller/model_naming'
|
2
|
+
|
1
3
|
module ActionDispatch
|
2
4
|
module Routing
|
3
5
|
# Polymorphic URL helpers are methods for smart resolution to a named route call when
|
@@ -32,7 +34,7 @@ module ActionDispatch
|
|
32
34
|
# == Prefixed polymorphic helpers
|
33
35
|
#
|
34
36
|
# 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
|
37
|
+
# number of prefixed helpers are available as a shorthand to <tt>action: "..."</tt>
|
36
38
|
# in options. Those are:
|
37
39
|
#
|
38
40
|
# * <tt>edit_polymorphic_url</tt>, <tt>edit_polymorphic_path</tt>
|
@@ -41,20 +43,20 @@ module ActionDispatch
|
|
41
43
|
# Example usage:
|
42
44
|
#
|
43
45
|
# edit_polymorphic_path(@post) # => "/posts/1/edit"
|
44
|
-
# polymorphic_path(@post, :
|
45
|
-
#
|
46
|
-
# == Using with mounted engines
|
46
|
+
# polymorphic_path(@post, format: :pdf) # => "/posts/1.pdf"
|
47
47
|
#
|
48
|
-
#
|
49
|
-
# polymorphic_url pointing at engine's routes. To do that, just pass proxy used
|
50
|
-
# to reach engine's routes as a first argument:
|
48
|
+
# == Usage with mounted engines
|
51
49
|
#
|
52
|
-
#
|
50
|
+
# If you are using a mounted engine and you need to use a polymorphic_url
|
51
|
+
# pointing at the engine's routes, pass in the engine's route proxy as the first
|
52
|
+
# argument to the method. For example:
|
53
53
|
#
|
54
|
-
#
|
55
|
-
#
|
54
|
+
# polymorphic_url([blog, @post]) # calls blog.post_path(@post)
|
55
|
+
# form_for([blog, @post]) # => "/blog/posts/1"
|
56
56
|
#
|
57
57
|
module PolymorphicRoutes
|
58
|
+
include ActionController::ModelNaming
|
59
|
+
|
58
60
|
# Constructs a call to a named RESTful route for the given record and returns the
|
59
61
|
# resulting URL string. For example:
|
60
62
|
#
|
@@ -72,8 +74,6 @@ module ActionDispatch
|
|
72
74
|
# * <tt>:routing_type</tt> - Allowed values are <tt>:path</tt> or <tt>:url</tt>.
|
73
75
|
# Default is <tt>:url</tt>.
|
74
76
|
#
|
75
|
-
# ==== Examples
|
76
|
-
#
|
77
77
|
# # an Article record
|
78
78
|
# polymorphic_url(record) # same as article_url(record)
|
79
79
|
#
|
@@ -130,7 +130,7 @@ module ActionDispatch
|
|
130
130
|
end
|
131
131
|
|
132
132
|
# Returns the path component of a URL for the given record. It uses
|
133
|
-
# <tt>polymorphic_url</tt> with <tt
|
133
|
+
# <tt>polymorphic_url</tt> with <tt>routing_type: :path</tt>.
|
134
134
|
def polymorphic_path(record_or_hash_or_array, options = {})
|
135
135
|
polymorphic_url(record_or_hash_or_array, options.merge(:routing_type => :path))
|
136
136
|
end
|
@@ -156,10 +156,6 @@ module ActionDispatch
|
|
156
156
|
options[:action] ? "#{options[:action]}_" : ''
|
157
157
|
end
|
158
158
|
|
159
|
-
def convert_to_model(object)
|
160
|
-
object.respond_to?(:to_model) ? object.to_model : object
|
161
|
-
end
|
162
|
-
|
163
159
|
def routing_type(options)
|
164
160
|
options[:routing_type] || :url
|
165
161
|
end
|
@@ -171,7 +167,7 @@ module ActionDispatch
|
|
171
167
|
if parent.is_a?(Symbol) || parent.is_a?(String)
|
172
168
|
parent
|
173
169
|
else
|
174
|
-
|
170
|
+
model_name_from_record_or_class(parent).singular_route_key
|
175
171
|
end
|
176
172
|
end
|
177
173
|
else
|
@@ -183,9 +179,9 @@ module ActionDispatch
|
|
183
179
|
route << record
|
184
180
|
elsif record
|
185
181
|
if inflection == :singular
|
186
|
-
route <<
|
182
|
+
route << model_name_from_record_or_class(record).singular_route_key
|
187
183
|
else
|
188
|
-
route <<
|
184
|
+
route << model_name_from_record_or_class(record).route_key
|
189
185
|
end
|
190
186
|
else
|
191
187
|
raise ArgumentError, "Nil location provided. Can't build URI."
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'action_dispatch/http/request'
|
2
2
|
require 'active_support/core_ext/uri'
|
3
|
+
require 'active_support/core_ext/array/extract_options'
|
3
4
|
require 'rack/utils'
|
5
|
+
require 'action_controller/metal/exceptions'
|
4
6
|
|
5
7
|
module ActionDispatch
|
6
8
|
module Routing
|
@@ -15,6 +17,14 @@ module ActionDispatch
|
|
15
17
|
def call(env)
|
16
18
|
req = Request.new(env)
|
17
19
|
|
20
|
+
# If any of the path parameters has a invalid encoding then
|
21
|
+
# raise since it's likely to trigger errors further on.
|
22
|
+
req.symbolized_path_parameters.each do |key, value|
|
23
|
+
unless value.valid_encoding?
|
24
|
+
raise ActionController::BadRequest, "Invalid parameter: #{key} => #{value}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
18
28
|
uri = URI.parse(path(req.symbolized_path_parameters, req))
|
19
29
|
uri.scheme ||= req.scheme
|
20
30
|
uri.host ||= req.host
|
@@ -34,6 +44,25 @@ module ActionDispatch
|
|
34
44
|
def path(params, request)
|
35
45
|
block.call params, request
|
36
46
|
end
|
47
|
+
|
48
|
+
def inspect
|
49
|
+
"redirect(#{status})"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class PathRedirect < Redirect
|
54
|
+
def path(params, request)
|
55
|
+
(params.empty? || !block.match(/%\{\w*\}/)) ? block : (block % escape(params))
|
56
|
+
end
|
57
|
+
|
58
|
+
def inspect
|
59
|
+
"redirect(#{status}, #{block})"
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
def escape(params)
|
64
|
+
Hash[params.map{ |k,v| [k, Rack::Utils.escape(v)] }]
|
65
|
+
end
|
37
66
|
end
|
38
67
|
|
39
68
|
class OptionRedirect < Redirect # :nodoc:
|
@@ -46,7 +75,7 @@ module ActionDispatch
|
|
46
75
|
:port => request.optional_port,
|
47
76
|
:path => request.path,
|
48
77
|
:params => request.query_parameters
|
49
|
-
}.merge options
|
78
|
+
}.merge! options
|
50
79
|
|
51
80
|
if !params.empty? && url_options[:path].match(/%\{\w*\}/)
|
52
81
|
url_options[:path] = (url_options[:path] % escape_path(params))
|
@@ -55,6 +84,10 @@ module ActionDispatch
|
|
55
84
|
ActionDispatch::Http::URL.url_for url_options
|
56
85
|
end
|
57
86
|
|
87
|
+
def inspect
|
88
|
+
"redirect(#{status}, #{options.map{ |k,v| "#{k}: #{v}" }.join(', ')})"
|
89
|
+
end
|
90
|
+
|
58
91
|
private
|
59
92
|
def escape_path(params)
|
60
93
|
Hash[params.map{ |k,v| [k, URI.parser.escape(v)] }]
|
@@ -65,11 +98,11 @@ module ActionDispatch
|
|
65
98
|
|
66
99
|
# Redirect any path to another path:
|
67
100
|
#
|
68
|
-
#
|
101
|
+
# get "/stories" => redirect("/posts")
|
69
102
|
#
|
70
103
|
# You can also use interpolation in the supplied redirect argument:
|
71
104
|
#
|
72
|
-
#
|
105
|
+
# get 'docs/:article', to: redirect('/wiki/%{article}')
|
73
106
|
#
|
74
107
|
# Alternatively you can use one of the other syntaxes:
|
75
108
|
#
|
@@ -78,54 +111,38 @@ module ActionDispatch
|
|
78
111
|
# params, depending of how many arguments your block accepts. A string is required as a
|
79
112
|
# return value.
|
80
113
|
#
|
81
|
-
#
|
114
|
+
# get 'jokes/:number', to: redirect { |params, request|
|
82
115
|
# path = (params[:number].to_i.even? ? "wheres-the-beef" : "i-love-lamp")
|
83
116
|
# "http://#{request.host_with_port}/#{path}"
|
84
117
|
# }
|
85
118
|
#
|
119
|
+
# Note that the +do end+ syntax for the redirect block wouldn't work, as Ruby would pass
|
120
|
+
# the block to +get+ instead of +redirect+. Use <tt>{ ... }</tt> instead.
|
121
|
+
#
|
86
122
|
# The options version of redirect allows you to supply only the parts of the url which need
|
87
123
|
# to change, it also supports interpolation of the path similar to the first example.
|
88
124
|
#
|
89
|
-
#
|
90
|
-
#
|
125
|
+
# get 'stores/:name', to: redirect(subdomain: 'stores', path: '/%{name}')
|
126
|
+
# get 'stores/:name(*all)', to: redirect(subdomain: 'stores', path: '/%{name}%{all}')
|
91
127
|
#
|
92
128
|
# Finally, an object which responds to call can be supplied to redirect, allowing you to reuse
|
93
129
|
# common redirect routes. The call method must accept two arguments, params and request, and return
|
94
130
|
# a string.
|
95
131
|
#
|
96
|
-
#
|
132
|
+
# get 'accounts/:name' => redirect(SubdomainRedirector.new('api'))
|
97
133
|
#
|
98
134
|
def redirect(*args, &block)
|
99
|
-
options = args.
|
135
|
+
options = args.extract_options!
|
100
136
|
status = options.delete(:status) || 301
|
137
|
+
path = args.shift
|
101
138
|
|
102
139
|
return OptionRedirect.new(status, options) if options.any?
|
103
|
-
|
104
|
-
path = args.shift
|
105
|
-
|
106
|
-
block = lambda { |params, request|
|
107
|
-
(params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % escape(params))
|
108
|
-
} if String === path
|
140
|
+
return PathRedirect.new(status, path) if String === path
|
109
141
|
|
110
142
|
block = path if path.respond_to? :call
|
111
|
-
|
112
|
-
# :FIXME: remove in Rails 4.0
|
113
|
-
if block && block.respond_to?(:arity) && block.arity < 2
|
114
|
-
msg = "redirect blocks with arity of #{block.arity} are deprecated. Your block must take 2 parameters: the environment, and a request object"
|
115
|
-
ActiveSupport::Deprecation.warn msg
|
116
|
-
deprecated_block = block
|
117
|
-
block = lambda { |params, _| deprecated_block.call(params) }
|
118
|
-
end
|
119
|
-
|
120
143
|
raise ArgumentError, "redirection argument not supported" unless block
|
121
|
-
|
122
144
|
Redirect.new status, block
|
123
145
|
end
|
124
|
-
|
125
|
-
private
|
126
|
-
def escape(params)
|
127
|
-
Hash[params.map{ |k,v| [k, Rack::Utils.escape(v)] }]
|
128
|
-
end
|
129
146
|
end
|
130
147
|
end
|
131
148
|
end
|
@@ -1,9 +1,10 @@
|
|
1
|
-
require 'journey'
|
1
|
+
require 'action_dispatch/journey'
|
2
2
|
require 'forwardable'
|
3
|
-
require '
|
3
|
+
require 'thread_safe'
|
4
4
|
require 'active_support/core_ext/object/to_query'
|
5
5
|
require 'active_support/core_ext/hash/slice'
|
6
6
|
require 'active_support/core_ext/module/remove_method'
|
7
|
+
require 'active_support/core_ext/array/extract_options'
|
7
8
|
require 'action_controller/metal/exceptions'
|
8
9
|
|
9
10
|
module ActionDispatch
|
@@ -21,11 +22,20 @@ module ActionDispatch
|
|
21
22
|
def initialize(options={})
|
22
23
|
@defaults = options[:defaults]
|
23
24
|
@glob_param = options.delete(:glob)
|
24
|
-
@
|
25
|
+
@controller_class_names = ThreadSafe::Cache.new
|
25
26
|
end
|
26
27
|
|
27
28
|
def call(env)
|
28
29
|
params = env[PARAMETERS_KEY]
|
30
|
+
|
31
|
+
# If any of the path parameters has a invalid encoding then
|
32
|
+
# raise since it's likely to trigger errors further on.
|
33
|
+
params.each do |key, value|
|
34
|
+
unless value.valid_encoding?
|
35
|
+
raise ActionController::BadRequest, "Invalid parameter: #{key} => #{value}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
29
39
|
prepare_params!(params)
|
30
40
|
|
31
41
|
# Just raise undefined constant errors if a controller was specified as default.
|
@@ -60,13 +70,8 @@ module ActionDispatch
|
|
60
70
|
private
|
61
71
|
|
62
72
|
def controller_reference(controller_param)
|
63
|
-
|
64
|
-
|
65
|
-
unless controller = @controllers[controller_param]
|
66
|
-
controller = @controllers[controller_param] =
|
67
|
-
ActiveSupport::Dependencies.reference(controller_name)
|
68
|
-
end
|
69
|
-
controller.get(controller_name)
|
73
|
+
const_name = @controller_class_names[controller_param] ||= "#{controller_param.camelize}Controller"
|
74
|
+
ActiveSupport::Dependencies.constantize(const_name)
|
70
75
|
end
|
71
76
|
|
72
77
|
def dispatch(controller, action, env)
|
@@ -94,14 +99,13 @@ module ActionDispatch
|
|
94
99
|
attr_reader :routes, :helpers, :module
|
95
100
|
|
96
101
|
def initialize
|
97
|
-
@routes
|
102
|
+
@routes = {}
|
98
103
|
@helpers = []
|
99
|
-
|
100
|
-
@module = Module.new
|
104
|
+
@module = Module.new
|
101
105
|
end
|
102
106
|
|
103
107
|
def helper_names
|
104
|
-
|
108
|
+
@helpers.map(&:to_s)
|
105
109
|
end
|
106
110
|
|
107
111
|
def clear!
|
@@ -139,90 +143,131 @@ module ActionDispatch
|
|
139
143
|
routes.length
|
140
144
|
end
|
141
145
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
146
|
+
class UrlHelper # :nodoc:
|
147
|
+
def self.create(route, options)
|
148
|
+
if optimize_helper?(route)
|
149
|
+
OptimizedUrlHelper.new(route, options)
|
150
|
+
else
|
151
|
+
new route, options
|
152
|
+
end
|
147
153
|
end
|
148
|
-
end
|
149
154
|
|
150
|
-
|
151
|
-
|
152
|
-
Array(destinations).each do |dest|
|
153
|
-
dest.__send__(:include, @module)
|
155
|
+
def self.optimize_helper?(route)
|
156
|
+
route.requirements.except(:controller, :action).empty?
|
154
157
|
end
|
155
|
-
end
|
156
158
|
|
157
|
-
|
158
|
-
|
159
|
-
:"#{name}_#{kind}"
|
160
|
-
end
|
159
|
+
class OptimizedUrlHelper < UrlHelper # :nodoc:
|
160
|
+
attr_reader :arg_size
|
161
161
|
|
162
|
-
|
163
|
-
|
164
|
-
|
162
|
+
def initialize(route, options)
|
163
|
+
super
|
164
|
+
@path_parts = @route.required_parts
|
165
|
+
@arg_size = @path_parts.size
|
166
|
+
@string_route = string_route(route)
|
167
|
+
end
|
165
168
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
169
|
+
def call(t, args)
|
170
|
+
if args.size == arg_size && !args.last.is_a?(Hash) && optimize_routes_generation?(t)
|
171
|
+
@options.merge!(t.url_options) if t.respond_to?(:url_options)
|
172
|
+
@options[:path] = optimized_helper(args)
|
173
|
+
ActionDispatch::Http::URL.url_for(@options)
|
174
|
+
else
|
175
|
+
super
|
176
|
+
end
|
171
177
|
end
|
172
|
-
end
|
173
178
|
|
174
|
-
|
175
|
-
selector = hash_access_name(name, kind)
|
179
|
+
private
|
176
180
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
181
|
+
def string_route(route)
|
182
|
+
string_route = route.ast.to_s.dup
|
183
|
+
while string_route.gsub!(/\([^\)]*\)/, "")
|
184
|
+
true
|
185
|
+
end
|
186
|
+
string_route
|
187
|
+
end
|
183
188
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
end
|
189
|
+
def optimized_helper(args)
|
190
|
+
path = @string_route.dup
|
191
|
+
klass = Journey::Router::Utils
|
188
192
|
|
189
|
-
|
193
|
+
@path_parts.zip(args) do |part, arg|
|
194
|
+
# Replace each route parameter
|
195
|
+
# e.g. :id for regular parameter or *path for globbing
|
196
|
+
# with ruby string interpolation code
|
197
|
+
path.gsub!(/(\*|:)#{part}/, klass.escape_fragment(arg.to_param))
|
190
198
|
end
|
191
|
-
|
192
|
-
|
193
|
-
|
199
|
+
path
|
200
|
+
end
|
201
|
+
|
202
|
+
def optimize_routes_generation?(t)
|
203
|
+
t.send(:optimize_routes_generation?)
|
204
|
+
end
|
194
205
|
end
|
195
206
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
remove_possible_method :#{selector}
|
215
|
-
def #{selector}(*args)
|
216
|
-
url_for(#{hash_access_method}(*args))
|
207
|
+
def initialize(route, options)
|
208
|
+
@options = options
|
209
|
+
@segment_keys = route.segment_keys
|
210
|
+
@route = route
|
211
|
+
end
|
212
|
+
|
213
|
+
def call(t, args)
|
214
|
+
t.url_for(handle_positional_args(t, args, @options, @segment_keys))
|
215
|
+
end
|
216
|
+
|
217
|
+
def handle_positional_args(t, args, options, keys)
|
218
|
+
inner_options = args.extract_options!
|
219
|
+
result = options.dup
|
220
|
+
|
221
|
+
if args.size > 0
|
222
|
+
if args.size < keys.size - 1 # take format into account
|
223
|
+
keys -= t.url_options.keys if t.respond_to?(:url_options)
|
224
|
+
keys -= options.keys
|
217
225
|
end
|
218
|
-
|
219
|
-
|
226
|
+
result.merge!(Hash[keys.zip(args)])
|
227
|
+
end
|
228
|
+
|
229
|
+
result.merge!(inner_options)
|
220
230
|
end
|
231
|
+
end
|
232
|
+
|
233
|
+
private
|
234
|
+
# Create a url helper allowing ordered parameters to be associated
|
235
|
+
# with corresponding dynamic segments, so you can do:
|
236
|
+
#
|
237
|
+
# foo_url(bar, baz, bang)
|
238
|
+
#
|
239
|
+
# Instead of:
|
240
|
+
#
|
241
|
+
# foo_url(bar: bar, baz: baz, bang: bang)
|
242
|
+
#
|
243
|
+
# Also allow options hash, so you can do:
|
244
|
+
#
|
245
|
+
# foo_url(bar, baz, bang, sort_by: 'baz')
|
246
|
+
#
|
247
|
+
def define_url_helper(route, name, options)
|
248
|
+
helper = UrlHelper.create(route, options.dup)
|
249
|
+
|
250
|
+
@module.remove_possible_method name
|
251
|
+
@module.module_eval do
|
252
|
+
define_method(name) do |*args|
|
253
|
+
helper.call self, args
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
helpers << name
|
258
|
+
end
|
259
|
+
|
260
|
+
def define_named_route_methods(name, route)
|
261
|
+
define_url_helper route, :"#{name}_path",
|
262
|
+
route.defaults.merge(:use_route => name, :only_path => true)
|
263
|
+
define_url_helper route, :"#{name}_url",
|
264
|
+
route.defaults.merge(:use_route => name, :only_path => false)
|
265
|
+
end
|
221
266
|
end
|
222
267
|
|
223
268
|
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
|
224
269
|
attr_accessor :disable_clear_and_finalize, :resources_path_names
|
225
|
-
attr_accessor :default_url_options, :request_class
|
270
|
+
attr_accessor :default_url_options, :request_class
|
226
271
|
|
227
272
|
alias :routes :set
|
228
273
|
|
@@ -234,17 +279,7 @@ module ActionDispatch
|
|
234
279
|
self.named_routes = NamedRouteCollection.new
|
235
280
|
self.resources_path_names = self.class.default_resources_path_names.dup
|
236
281
|
self.default_url_options = {}
|
237
|
-
|
238
282
|
self.request_class = request_class
|
239
|
-
@valid_conditions = {}
|
240
|
-
|
241
|
-
request_class.public_instance_methods.each { |m|
|
242
|
-
@valid_conditions[m.to_sym] = true
|
243
|
-
}
|
244
|
-
@valid_conditions[:controller] = true
|
245
|
-
@valid_conditions[:action] = true
|
246
|
-
|
247
|
-
self.valid_conditions.delete(:id)
|
248
283
|
|
249
284
|
@append = []
|
250
285
|
@prepend = []
|
@@ -300,14 +335,15 @@ module ActionDispatch
|
|
300
335
|
@prepend.each { |blk| eval_block(blk) }
|
301
336
|
end
|
302
337
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
end
|
307
|
-
|
308
|
-
module MountedHelpers
|
338
|
+
module MountedHelpers #:nodoc:
|
339
|
+
extend ActiveSupport::Concern
|
340
|
+
include UrlFor
|
309
341
|
end
|
310
342
|
|
343
|
+
# Contains all the mounted helpers accross different
|
344
|
+
# engines and the `main_app` helper for the application.
|
345
|
+
# You can include this in your classes if you want to
|
346
|
+
# access routes for other engines.
|
311
347
|
def mounted_helpers
|
312
348
|
MountedHelpers
|
313
349
|
end
|
@@ -318,13 +354,13 @@ module ActionDispatch
|
|
318
354
|
routes = self
|
319
355
|
MountedHelpers.class_eval do
|
320
356
|
define_method "_#{name}" do
|
321
|
-
RoutesProxy.new(routes,
|
357
|
+
RoutesProxy.new(routes, _routes_context)
|
322
358
|
end
|
323
359
|
end
|
324
360
|
|
325
|
-
MountedHelpers.class_eval
|
361
|
+
MountedHelpers.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
326
362
|
def #{name}
|
327
|
-
|
363
|
+
@_#{name} ||= _#{name}
|
328
364
|
end
|
329
365
|
RUBY
|
330
366
|
end
|
@@ -333,28 +369,36 @@ module ActionDispatch
|
|
333
369
|
@url_helpers ||= begin
|
334
370
|
routes = self
|
335
371
|
|
336
|
-
|
372
|
+
Module.new do
|
337
373
|
extend ActiveSupport::Concern
|
338
374
|
include UrlFor
|
339
375
|
|
376
|
+
# Define url_for in the singleton level so one can do:
|
377
|
+
# Rails.application.routes.url_helpers.url_for(args)
|
340
378
|
@_routes = routes
|
341
379
|
class << self
|
342
|
-
delegate :url_for, :to => '@_routes'
|
380
|
+
delegate :url_for, :optimize_routes_generation?, :to => '@_routes'
|
343
381
|
end
|
382
|
+
|
383
|
+
# Make named_routes available in the module singleton
|
384
|
+
# as well, so one can do:
|
385
|
+
# Rails.application.routes.url_helpers.posts_path
|
344
386
|
extend routes.named_routes.module
|
345
387
|
|
346
|
-
#
|
347
|
-
#
|
348
|
-
|
388
|
+
# Any class that includes this module will get all
|
389
|
+
# named routes...
|
390
|
+
include routes.named_routes.module
|
391
|
+
|
392
|
+
# plus a singleton class method called _routes ...
|
349
393
|
included do
|
350
|
-
routes.install_helpers(self)
|
351
394
|
singleton_class.send(:redefine_method, :_routes) { routes }
|
352
395
|
end
|
353
396
|
|
397
|
+
# And an instance method _routes. Note that
|
398
|
+
# UrlFor (included in this module) add extra
|
399
|
+
# conveniences for working with @_routes.
|
354
400
|
define_method(:_routes) { @_routes || routes }
|
355
401
|
end
|
356
|
-
|
357
|
-
helpers
|
358
402
|
end
|
359
403
|
end
|
360
404
|
|
@@ -366,10 +410,10 @@ module ActionDispatch
|
|
366
410
|
raise ArgumentError, "Invalid route name: '#{name}'" unless name.blank? || name.to_s.match(/^[_a-z]\w*$/i)
|
367
411
|
|
368
412
|
path = build_path(conditions.delete(:path_info), requirements, SEPARATORS, anchor)
|
369
|
-
conditions = build_conditions(conditions,
|
413
|
+
conditions = build_conditions(conditions, path.names.map { |x| x.to_sym })
|
370
414
|
|
371
415
|
route = @set.add_route(app, path, conditions, defaults, name)
|
372
|
-
named_routes[name] = route if name
|
416
|
+
named_routes[name] = route if name && !named_routes[name]
|
373
417
|
route
|
374
418
|
end
|
375
419
|
|
@@ -403,21 +447,22 @@ module ActionDispatch
|
|
403
447
|
end
|
404
448
|
private :build_path
|
405
449
|
|
406
|
-
def build_conditions(current_conditions,
|
450
|
+
def build_conditions(current_conditions, path_values)
|
407
451
|
conditions = current_conditions.dup
|
408
452
|
|
409
|
-
verbs = conditions[:request_method] || []
|
410
|
-
|
411
453
|
# Rack-Mount requires that :request_method be a regular expression.
|
412
454
|
# :request_method represents the HTTP verb that matches this route.
|
413
455
|
#
|
414
456
|
# Here we munge values before they get sent on to rack-mount.
|
457
|
+
verbs = conditions[:request_method] || []
|
415
458
|
unless verbs.empty?
|
416
459
|
conditions[:request_method] = %r[^#{verbs.join('|')}$]
|
417
460
|
end
|
418
|
-
conditions.delete_if { |k,v| !(req_predicates.include?(k) || path_values.include?(k)) }
|
419
461
|
|
420
|
-
conditions
|
462
|
+
conditions.keep_if do |k, _|
|
463
|
+
k == :action || k == :controller || k == :required_defaults ||
|
464
|
+
@request_class.public_method_defined?(k) || path_values.include?(k)
|
465
|
+
end
|
421
466
|
end
|
422
467
|
private :build_conditions
|
423
468
|
|
@@ -434,12 +479,11 @@ module ActionDispatch
|
|
434
479
|
|
435
480
|
attr_reader :options, :recall, :set, :named_route
|
436
481
|
|
437
|
-
def initialize(options, recall, set
|
482
|
+
def initialize(options, recall, set)
|
438
483
|
@named_route = options.delete(:use_route)
|
439
484
|
@options = options.dup
|
440
485
|
@recall = recall.dup
|
441
486
|
@set = set
|
442
|
-
@extras = extras
|
443
487
|
|
444
488
|
normalize_options!
|
445
489
|
normalize_controller_action_id!
|
@@ -458,9 +502,7 @@ module ActionDispatch
|
|
458
502
|
|
459
503
|
def use_recall_for(key)
|
460
504
|
if @recall[key] && (!@options.key?(key) || @options[key] == @recall[key])
|
461
|
-
if named_route_exists?
|
462
|
-
@options[key] = @recall.delete(key) if segment_keys.include?(key)
|
463
|
-
else
|
505
|
+
if !named_route_exists? || segment_keys.include?(key)
|
464
506
|
@options[key] = @recall.delete(key)
|
465
507
|
end
|
466
508
|
end
|
@@ -470,7 +512,7 @@ module ActionDispatch
|
|
470
512
|
# If an explicit :controller was given, always make :action explicit
|
471
513
|
# too, so that action expiry works as expected for things like
|
472
514
|
#
|
473
|
-
# generate({:
|
515
|
+
# generate({controller: 'content'}, {controller: 'content', action: 'show'})
|
474
516
|
#
|
475
517
|
# (the above is from the unit tests). In the above case, because the
|
476
518
|
# controller was explicitly given, but no action, the action is implied to
|
@@ -499,7 +541,7 @@ module ActionDispatch
|
|
499
541
|
use_recall_for(:id)
|
500
542
|
end
|
501
543
|
|
502
|
-
# if the current controller is "foo/bar/baz" and :
|
544
|
+
# if the current controller is "foo/bar/baz" and controller: "baz/bat"
|
503
545
|
# is specified, the controller becomes "foo/baz/bat"
|
504
546
|
def use_relative_controller!
|
505
547
|
if !named_route && different_controller? && !controller.start_with?("/")
|
@@ -515,8 +557,8 @@ module ActionDispatch
|
|
515
557
|
@options[:controller] = controller.sub(%r{^/}, '') if controller
|
516
558
|
end
|
517
559
|
|
518
|
-
# This handles the case of :
|
519
|
-
# It is identical to :
|
560
|
+
# This handles the case of action: nil being explicitly passed.
|
561
|
+
# It is identical to action: "index"
|
520
562
|
def handle_nil_action!
|
521
563
|
if options.has_key?(:action) && options[:action].nil?
|
522
564
|
options[:action] = 'index'
|
@@ -524,20 +566,10 @@ module ActionDispatch
|
|
524
566
|
recall[:action] = options.delete(:action) if options[:action] == 'index'
|
525
567
|
end
|
526
568
|
|
569
|
+
# Generates a path from routes, returns [path, params].
|
570
|
+
# If no route is generated the formatter will raise ActionController::UrlGenerationError
|
527
571
|
def generate
|
528
|
-
|
529
|
-
|
530
|
-
raise_routing_error unless path
|
531
|
-
|
532
|
-
return [path, params.keys] if @extras
|
533
|
-
|
534
|
-
[path, params]
|
535
|
-
rescue Journey::Router::RoutingError
|
536
|
-
raise_routing_error
|
537
|
-
end
|
538
|
-
|
539
|
-
def raise_routing_error
|
540
|
-
raise ActionController::RoutingError, "No route matches #{options.inspect}"
|
572
|
+
@set.formatter.generate(:path_info, named_route, options, recall, PARAMETERIZE)
|
541
573
|
end
|
542
574
|
|
543
575
|
def different_controller?
|
@@ -562,41 +594,53 @@ module ActionDispatch
|
|
562
594
|
end
|
563
595
|
|
564
596
|
def generate_extras(options, recall={})
|
565
|
-
generate(options, recall
|
597
|
+
path, params = generate(options, recall)
|
598
|
+
return path, params.keys
|
566
599
|
end
|
567
600
|
|
568
|
-
def generate(options, recall = {}
|
569
|
-
Generator.new(options, recall, self
|
601
|
+
def generate(options, recall = {})
|
602
|
+
Generator.new(options, recall, self).generate
|
570
603
|
end
|
571
604
|
|
572
605
|
RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length,
|
573
|
-
:trailing_slash, :anchor, :params, :only_path, :script_name
|
606
|
+
:trailing_slash, :anchor, :params, :only_path, :script_name,
|
607
|
+
:original_script_name]
|
608
|
+
|
609
|
+
def mounted?
|
610
|
+
false
|
611
|
+
end
|
612
|
+
|
613
|
+
def optimize_routes_generation?
|
614
|
+
!mounted? && default_url_options.empty?
|
615
|
+
end
|
574
616
|
|
575
617
|
def _generate_prefix(options = {})
|
576
618
|
nil
|
577
619
|
end
|
578
620
|
|
621
|
+
# The +options+ argument must be +nil+ or a hash whose keys are *symbols*.
|
579
622
|
def url_for(options)
|
580
|
-
|
581
|
-
options = (options || {}).reverse_merge!(default_url_options)
|
582
|
-
|
583
|
-
handle_positional_args(options)
|
623
|
+
options = default_url_options.merge(options || {})
|
584
624
|
|
585
625
|
user, password = extract_authentication(options)
|
586
|
-
|
587
|
-
|
626
|
+
recall = options.delete(:_recall)
|
627
|
+
|
628
|
+
original_script_name = options.delete(:original_script_name).presence
|
629
|
+
script_name = options.delete(:script_name).presence || _generate_prefix(options)
|
588
630
|
|
589
|
-
|
631
|
+
if script_name && original_script_name
|
632
|
+
script_name = original_script_name + script_name
|
633
|
+
end
|
590
634
|
|
591
635
|
path_options = options.except(*RESERVED_OPTIONS)
|
592
636
|
path_options = yield(path_options) if block_given?
|
593
637
|
|
594
|
-
|
595
|
-
path << path_addition
|
638
|
+
path, params = generate(path_options, recall || {})
|
596
639
|
params.merge!(options[:params] || {})
|
597
640
|
|
598
641
|
ActionDispatch::Http::URL.url_for(options.merge!({
|
599
642
|
:path => path,
|
643
|
+
:script_name => script_name,
|
600
644
|
:params => params,
|
601
645
|
:user => user,
|
602
646
|
:password => password
|
@@ -604,7 +648,6 @@ module ActionDispatch
|
|
604
648
|
end
|
605
649
|
|
606
650
|
def call(env)
|
607
|
-
finalize!
|
608
651
|
@router.call(env)
|
609
652
|
end
|
610
653
|
|
@@ -614,28 +657,34 @@ module ActionDispatch
|
|
614
657
|
extras = environment[:extras] || {}
|
615
658
|
|
616
659
|
begin
|
617
|
-
env = Rack::MockRequest.env_for(path, {:method => method
|
660
|
+
env = Rack::MockRequest.env_for(path, {:method => method})
|
618
661
|
rescue URI::InvalidURIError => e
|
619
662
|
raise ActionController::RoutingError, e.message
|
620
663
|
end
|
621
664
|
|
622
665
|
req = @request_class.new(env)
|
623
666
|
@router.recognize(req) do |route, matches, params|
|
667
|
+
params.merge!(extras)
|
624
668
|
params.each do |key, value|
|
625
669
|
if value.is_a?(String)
|
626
|
-
value = value.dup.force_encoding(Encoding::BINARY)
|
670
|
+
value = value.dup.force_encoding(Encoding::BINARY)
|
627
671
|
params[key] = URI.parser.unescape(value)
|
628
672
|
end
|
629
673
|
end
|
630
|
-
|
674
|
+
old_params = env[::ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
|
675
|
+
env[::ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] = (old_params || {}).merge(params)
|
631
676
|
dispatcher = route.app
|
632
677
|
while dispatcher.is_a?(Mapper::Constraints) && dispatcher.matches?(env) do
|
633
678
|
dispatcher = dispatcher.app
|
634
679
|
end
|
635
680
|
|
636
|
-
if dispatcher.is_a?(Dispatcher)
|
637
|
-
dispatcher.
|
638
|
-
|
681
|
+
if dispatcher.is_a?(Dispatcher)
|
682
|
+
if dispatcher.controller(params, false)
|
683
|
+
dispatcher.prepare_params!(params)
|
684
|
+
return params
|
685
|
+
else
|
686
|
+
raise ActionController::RoutingError, "A route matches #{path.inspect}, but references missing controller: #{params[:controller].camelize}Controller"
|
687
|
+
end
|
639
688
|
end
|
640
689
|
end
|
641
690
|
|
@@ -652,16 +701,6 @@ module ActionDispatch
|
|
652
701
|
end
|
653
702
|
end
|
654
703
|
|
655
|
-
def handle_positional_args(options)
|
656
|
-
return unless args = options.delete(:_positional_args)
|
657
|
-
|
658
|
-
keys = options.delete(:_positional_keys)
|
659
|
-
keys -= options.keys if args.size < keys.size - 1 # take format into account
|
660
|
-
|
661
|
-
# Tell url_for to skip default_url_options
|
662
|
-
options.merge!(Hash[args.zip(keys).map { |v, k| [k, v] }])
|
663
|
-
end
|
664
|
-
|
665
704
|
end
|
666
705
|
end
|
667
706
|
end
|