actionpack 3.2.19 → 4.2.11.3
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 +7 -0
- data/CHANGELOG.md +412 -503
- data/MIT-LICENSE +1 -1
- data/README.rdoc +11 -294
- data/lib/abstract_controller/asset_paths.rb +2 -2
- data/lib/abstract_controller/base.rb +52 -18
- data/lib/abstract_controller/callbacks.rb +87 -89
- data/lib/abstract_controller/collector.rb +17 -3
- data/lib/abstract_controller/helpers.rb +41 -14
- data/lib/abstract_controller/logger.rb +1 -2
- data/lib/abstract_controller/railties/routes_helpers.rb +3 -3
- data/lib/abstract_controller/rendering.rb +65 -118
- data/lib/abstract_controller/translation.rb +16 -1
- data/lib/abstract_controller/url_for.rb +7 -7
- data/lib/abstract_controller.rb +2 -10
- data/lib/action_controller/base.rb +61 -28
- data/lib/action_controller/caching/fragments.rb +30 -54
- data/lib/action_controller/caching.rb +38 -35
- data/lib/action_controller/log_subscriber.rb +35 -18
- data/lib/action_controller/metal/conditional_get.rb +103 -34
- data/lib/action_controller/metal/data_streaming.rb +20 -26
- data/lib/action_controller/metal/etag_with_template_digest.rb +50 -0
- data/lib/action_controller/metal/exceptions.rb +19 -6
- data/lib/action_controller/metal/flash.rb +41 -9
- data/lib/action_controller/metal/force_ssl.rb +70 -12
- data/lib/action_controller/metal/head.rb +30 -7
- data/lib/action_controller/metal/helpers.rb +11 -11
- data/lib/action_controller/metal/hide_actions.rb +0 -1
- data/lib/action_controller/metal/http_authentication.rb +140 -94
- data/lib/action_controller/metal/implicit_render.rb +1 -1
- data/lib/action_controller/metal/instrumentation.rb +11 -7
- data/lib/action_controller/metal/live.rb +328 -0
- data/lib/action_controller/metal/mime_responds.rb +161 -152
- data/lib/action_controller/metal/params_wrapper.rb +126 -81
- data/lib/action_controller/metal/rack_delegation.rb +10 -4
- data/lib/action_controller/metal/redirecting.rb +44 -41
- data/lib/action_controller/metal/renderers.rb +48 -19
- data/lib/action_controller/metal/rendering.rb +46 -11
- data/lib/action_controller/metal/request_forgery_protection.rb +250 -29
- data/lib/action_controller/metal/streaming.rb +30 -38
- data/lib/action_controller/metal/strong_parameters.rb +669 -0
- data/lib/action_controller/metal/testing.rb +12 -18
- data/lib/action_controller/metal/url_for.rb +31 -29
- data/lib/action_controller/metal.rb +31 -40
- data/lib/action_controller/model_naming.rb +12 -0
- data/lib/action_controller/railtie.rb +38 -18
- data/lib/action_controller/railties/helpers.rb +22 -0
- data/lib/action_controller/test_case.rb +359 -173
- data/lib/action_controller.rb +9 -16
- data/lib/action_dispatch/http/cache.rb +64 -11
- data/lib/action_dispatch/http/filter_parameters.rb +20 -10
- data/lib/action_dispatch/http/filter_redirect.rb +38 -0
- data/lib/action_dispatch/http/headers.rb +85 -17
- data/lib/action_dispatch/http/mime_negotiation.rb +55 -5
- data/lib/action_dispatch/http/mime_type.rb +167 -114
- data/lib/action_dispatch/http/mime_types.rb +2 -1
- data/lib/action_dispatch/http/parameter_filter.rb +44 -46
- data/lib/action_dispatch/http/parameters.rb +30 -46
- data/lib/action_dispatch/http/rack_cache.rb +2 -3
- data/lib/action_dispatch/http/request.rb +108 -45
- data/lib/action_dispatch/http/response.rb +247 -48
- data/lib/action_dispatch/http/upload.rb +60 -29
- data/lib/action_dispatch/http/url.rb +135 -45
- data/lib/action_dispatch/journey/backwards.rb +5 -0
- data/lib/action_dispatch/journey/formatter.rb +166 -0
- data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +47 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +157 -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 +128 -0
- data/lib/action_dispatch/journey/parser.rb +198 -0
- data/lib/action_dispatch/journey/parser.y +49 -0
- data/lib/action_dispatch/journey/parser_extras.rb +23 -0
- data/lib/action_dispatch/journey/path/pattern.rb +193 -0
- data/lib/action_dispatch/journey/route.rb +125 -0
- data/lib/action_dispatch/journey/router/strexp.rb +27 -0
- data/lib/action_dispatch/journey/router/utils.rb +93 -0
- data/lib/action_dispatch/journey/router.rb +144 -0
- data/lib/action_dispatch/journey/routes.rb +80 -0
- data/lib/action_dispatch/journey/scanner.rb +61 -0
- data/lib/action_dispatch/journey/visitors.rb +221 -0
- data/lib/action_dispatch/journey/visualizer/fsm.css +30 -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/journey.rb +5 -0
- data/lib/action_dispatch/middleware/callbacks.rb +16 -11
- data/lib/action_dispatch/middleware/cookies.rb +346 -125
- data/lib/action_dispatch/middleware/debug_exceptions.rb +52 -24
- data/lib/action_dispatch/middleware/exception_wrapper.rb +75 -9
- data/lib/action_dispatch/middleware/flash.rb +85 -72
- data/lib/action_dispatch/middleware/params_parser.rb +16 -31
- data/lib/action_dispatch/middleware/public_exceptions.rb +39 -14
- data/lib/action_dispatch/middleware/reloader.rb +16 -7
- data/lib/action_dispatch/middleware/remote_ip.rb +132 -40
- data/lib/action_dispatch/middleware/request_id.rb +3 -7
- 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 +84 -29
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +15 -44
- data/lib/action_dispatch/middleware/ssl.rb +72 -0
- data/lib/action_dispatch/middleware/stack.rb +6 -1
- data/lib/action_dispatch/middleware/static.rb +80 -23
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +34 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +27 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +133 -5
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +200 -0
- data/lib/action_dispatch/railtie.rb +19 -6
- data/lib/action_dispatch/request/session.rb +193 -0
- data/lib/action_dispatch/request/utils.rb +35 -0
- data/lib/action_dispatch/routing/endpoint.rb +10 -0
- data/lib/action_dispatch/routing/inspector.rb +234 -0
- data/lib/action_dispatch/routing/mapper.rb +897 -436
- data/lib/action_dispatch/routing/polymorphic_routes.rb +213 -92
- data/lib/action_dispatch/routing/redirection.rb +97 -37
- data/lib/action_dispatch/routing/route_set.rb +432 -239
- data/lib/action_dispatch/routing/routes_proxy.rb +7 -4
- data/lib/action_dispatch/routing/url_for.rb +63 -34
- data/lib/action_dispatch/routing.rb +57 -89
- data/lib/action_dispatch/testing/assertions/dom.rb +2 -36
- data/lib/action_dispatch/testing/assertions/response.rb +24 -38
- data/lib/action_dispatch/testing/assertions/routing.rb +55 -54
- data/lib/action_dispatch/testing/assertions/selector.rb +2 -434
- data/lib/action_dispatch/testing/assertions/tag.rb +2 -137
- data/lib/action_dispatch/testing/assertions.rb +11 -7
- data/lib/action_dispatch/testing/integration.rb +88 -72
- data/lib/action_dispatch/testing/test_process.rb +9 -6
- data/lib/action_dispatch/testing/test_request.rb +13 -9
- data/lib/action_dispatch/testing/test_response.rb +1 -5
- data/lib/action_dispatch.rb +24 -21
- data/lib/action_pack/gem_version.rb +15 -0
- data/lib/action_pack/version.rb +5 -7
- data/lib/action_pack.rb +1 -1
- metadata +181 -292
- data/lib/abstract_controller/layouts.rb +0 -423
- data/lib/abstract_controller/view_paths.rb +0 -96
- 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/integration_test.rb +0 -2
- data/lib/action_controller/deprecated/performance_test.rb +0 -1
- data/lib/action_controller/deprecated.rb +0 -3
- data/lib/action_controller/metal/compatibility.rb +0 -65
- data/lib/action_controller/metal/responder.rb +0 -286
- data/lib/action_controller/metal/session_management.rb +0 -14
- data/lib/action_controller/railties/paths.rb +0 -25
- data/lib/action_controller/record_identifier.rb +0 -85
- data/lib/action_controller/vendor/html-scanner/html/document.rb +0 -68
- data/lib/action_controller/vendor/html-scanner/html/node.rb +0 -532
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +0 -177
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +0 -830
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +0 -107
- data/lib/action_controller/vendor/html-scanner/html/version.rb +0 -11
- data/lib/action_controller/vendor/html-scanner.rb +0 -20
- 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/middleware/templates/rescues/_request_and_response.erb +0 -31
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -26
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +0 -10
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +0 -15
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -17
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +0 -2
- data/lib/action_dispatch/testing/performance_test.rb +0 -10
- data/lib/action_view/asset_paths.rb +0 -142
- data/lib/action_view/base.rb +0 -220
- data/lib/action_view/buffers.rb +0 -43
- data/lib/action_view/context.rb +0 -36
- data/lib/action_view/flows.rb +0 -79
- data/lib/action_view/helpers/active_model_helper.rb +0 -50
- data/lib/action_view/helpers/asset_paths.rb +0 -7
- data/lib/action_view/helpers/asset_tag_helper.rb +0 -457
- 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/action_view/helpers/atom_feed_helper.rb +0 -200
- data/lib/action_view/helpers/cache_helper.rb +0 -64
- data/lib/action_view/helpers/capture_helper.rb +0 -203
- data/lib/action_view/helpers/controller_helper.rb +0 -25
- data/lib/action_view/helpers/csrf_helper.rb +0 -32
- data/lib/action_view/helpers/date_helper.rb +0 -1062
- data/lib/action_view/helpers/debug_helper.rb +0 -40
- data/lib/action_view/helpers/form_helper.rb +0 -1486
- data/lib/action_view/helpers/form_options_helper.rb +0 -658
- data/lib/action_view/helpers/form_tag_helper.rb +0 -685
- data/lib/action_view/helpers/javascript_helper.rb +0 -110
- data/lib/action_view/helpers/number_helper.rb +0 -622
- data/lib/action_view/helpers/output_safety_helper.rb +0 -38
- data/lib/action_view/helpers/record_tag_helper.rb +0 -111
- data/lib/action_view/helpers/rendering_helper.rb +0 -90
- data/lib/action_view/helpers/sanitize_helper.rb +0 -259
- data/lib/action_view/helpers/tag_helper.rb +0 -160
- data/lib/action_view/helpers/text_helper.rb +0 -426
- data/lib/action_view/helpers/translation_helper.rb +0 -91
- data/lib/action_view/helpers/url_helper.rb +0 -693
- data/lib/action_view/helpers.rb +0 -60
- data/lib/action_view/locale/en.yml +0 -160
- data/lib/action_view/log_subscriber.rb +0 -28
- data/lib/action_view/lookup_context.rb +0 -254
- data/lib/action_view/path_set.rb +0 -89
- data/lib/action_view/railtie.rb +0 -55
- data/lib/action_view/renderer/abstract_renderer.rb +0 -41
- data/lib/action_view/renderer/partial_renderer.rb +0 -415
- data/lib/action_view/renderer/renderer.rb +0 -54
- data/lib/action_view/renderer/streaming_template_renderer.rb +0 -106
- data/lib/action_view/renderer/template_renderer.rb +0 -94
- data/lib/action_view/template/error.rb +0 -128
- data/lib/action_view/template/handlers/builder.rb +0 -26
- data/lib/action_view/template/handlers/erb.rb +0 -125
- data/lib/action_view/template/handlers.rb +0 -50
- data/lib/action_view/template/resolver.rb +0 -272
- data/lib/action_view/template/text.rb +0 -30
- data/lib/action_view/template.rb +0 -337
- data/lib/action_view/test_case.rb +0 -245
- data/lib/action_view/testing/resolvers.rb +0 -50
- data/lib/action_view.rb +0 -84
- 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/isolated_helper.rb +0 -13
- data/lib/sprockets/helpers/rails_helper.rb +0 -182
- data/lib/sprockets/helpers.rb +0 -6
- 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,7 +74,18 @@ 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
|
-
#
|
77
|
+
# Also includes all the options from <tt>url_for</tt>. These include such
|
78
|
+
# things as <tt>:anchor</tt> or <tt>:trailing_slash</tt>. Example usage
|
79
|
+
# is given below:
|
80
|
+
#
|
81
|
+
# polymorphic_url([blog, post], anchor: 'my_anchor')
|
82
|
+
# # => "http://example.com/blogs/1/posts/1#my_anchor"
|
83
|
+
# polymorphic_url([blog, post], anchor: 'my_anchor', script_name: "/my_app")
|
84
|
+
# # => "http://example.com/my_app/blogs/1/posts/1#my_anchor"
|
85
|
+
#
|
86
|
+
# For all of these options, see the documentation for <tt>url_for</tt>.
|
87
|
+
#
|
88
|
+
# ==== Functionality
|
76
89
|
#
|
77
90
|
# # an Article record
|
78
91
|
# polymorphic_url(record) # same as article_url(record)
|
@@ -88,122 +101,230 @@ module ActionDispatch
|
|
88
101
|
# polymorphic_url(Comment) # same as comments_url()
|
89
102
|
#
|
90
103
|
def polymorphic_url(record_or_hash_or_array, options = {})
|
91
|
-
if record_or_hash_or_array
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
96
|
-
record_or_hash_or_array = record_or_hash_or_array[0] if record_or_hash_or_array.size == 1
|
104
|
+
if Hash === record_or_hash_or_array
|
105
|
+
options = record_or_hash_or_array.merge(options)
|
106
|
+
record = options.delete :id
|
107
|
+
return polymorphic_url record, options
|
97
108
|
end
|
98
109
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
args = Array === record_or_hash_or_array ?
|
103
|
-
record_or_hash_or_array.dup :
|
104
|
-
[ record_or_hash_or_array ]
|
105
|
-
|
106
|
-
inflection = if options[:action] && options[:action].to_s == "new"
|
107
|
-
args.pop
|
108
|
-
:singular
|
109
|
-
elsif (record.respond_to?(:persisted?) && !record.persisted?)
|
110
|
-
args.pop
|
111
|
-
:plural
|
112
|
-
elsif record.is_a?(Class)
|
113
|
-
args.pop
|
114
|
-
:plural
|
115
|
-
else
|
116
|
-
:singular
|
117
|
-
end
|
110
|
+
opts = options.dup
|
111
|
+
action = opts.delete :action
|
112
|
+
type = opts.delete(:routing_type) || :url
|
118
113
|
|
119
|
-
|
120
|
-
|
114
|
+
HelperMethodBuilder.polymorphic_method self,
|
115
|
+
record_or_hash_or_array,
|
116
|
+
action,
|
117
|
+
type,
|
118
|
+
opts
|
119
|
+
end
|
121
120
|
|
122
|
-
|
123
|
-
|
124
|
-
|
121
|
+
# Returns the path component of a URL for the given record. It uses
|
122
|
+
# <tt>polymorphic_url</tt> with <tt>routing_type: :path</tt>.
|
123
|
+
def polymorphic_path(record_or_hash_or_array, options = {})
|
124
|
+
if Hash === record_or_hash_or_array
|
125
|
+
options = record_or_hash_or_array.merge(options)
|
126
|
+
record = options.delete :id
|
127
|
+
return polymorphic_path record, options
|
125
128
|
end
|
126
129
|
|
127
|
-
|
130
|
+
opts = options.dup
|
131
|
+
action = opts.delete :action
|
132
|
+
type = :path
|
128
133
|
|
129
|
-
|
134
|
+
HelperMethodBuilder.polymorphic_method self,
|
135
|
+
record_or_hash_or_array,
|
136
|
+
action,
|
137
|
+
type,
|
138
|
+
opts
|
130
139
|
end
|
131
140
|
|
132
|
-
# Returns the path component of a URL for the given record. It uses
|
133
|
-
# <tt>polymorphic_url</tt> with <tt>:routing_type => :path</tt>.
|
134
|
-
def polymorphic_path(record_or_hash_or_array, options = {})
|
135
|
-
polymorphic_url(record_or_hash_or_array, options.merge(:routing_type => :path))
|
136
|
-
end
|
137
141
|
|
138
142
|
%w(edit new).each do |action|
|
139
143
|
module_eval <<-EOT, __FILE__, __LINE__ + 1
|
140
|
-
def #{action}_polymorphic_url(record_or_hash, options = {})
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
polymorphic_url( # polymorphic_url(
|
148
|
-
record_or_hash, # record_or_hash,
|
149
|
-
options.merge(:action => "#{action}", :routing_type => :path)) # options.merge(:action => "edit", :routing_type => :path))
|
150
|
-
end # end
|
144
|
+
def #{action}_polymorphic_url(record_or_hash, options = {})
|
145
|
+
polymorphic_url_for_action("#{action}", record_or_hash, options)
|
146
|
+
end
|
147
|
+
|
148
|
+
def #{action}_polymorphic_path(record_or_hash, options = {})
|
149
|
+
polymorphic_path_for_action("#{action}", record_or_hash, options)
|
150
|
+
end
|
151
151
|
EOT
|
152
152
|
end
|
153
153
|
|
154
154
|
private
|
155
|
-
|
156
|
-
|
155
|
+
|
156
|
+
def polymorphic_url_for_action(action, record_or_hash, options)
|
157
|
+
polymorphic_url(record_or_hash, options.merge(:action => action))
|
158
|
+
end
|
159
|
+
|
160
|
+
def polymorphic_path_for_action(action, record_or_hash, options)
|
161
|
+
polymorphic_path(record_or_hash, options.merge(:action => action))
|
162
|
+
end
|
163
|
+
|
164
|
+
class HelperMethodBuilder # :nodoc:
|
165
|
+
CACHE = { 'path' => {}, 'url' => {} }
|
166
|
+
|
167
|
+
def self.get(action, type)
|
168
|
+
type = type.to_s
|
169
|
+
CACHE[type].fetch(action) { build action, type }
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.url; CACHE['url'.freeze][nil]; end
|
173
|
+
def self.path; CACHE['path'.freeze][nil]; end
|
174
|
+
|
175
|
+
def self.build(action, type)
|
176
|
+
prefix = action ? "#{action}_" : ""
|
177
|
+
suffix = type
|
178
|
+
if action.to_s == 'new'
|
179
|
+
HelperMethodBuilder.singular prefix, suffix
|
180
|
+
else
|
181
|
+
HelperMethodBuilder.plural prefix, suffix
|
182
|
+
end
|
157
183
|
end
|
158
184
|
|
159
|
-
def
|
160
|
-
|
185
|
+
def self.singular(prefix, suffix)
|
186
|
+
new(->(name) { name.singular_route_key }, prefix, suffix)
|
161
187
|
end
|
162
188
|
|
163
|
-
def
|
164
|
-
|
189
|
+
def self.plural(prefix, suffix)
|
190
|
+
new(->(name) { name.route_key }, prefix, suffix)
|
165
191
|
end
|
166
192
|
|
167
|
-
def
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
193
|
+
def self.polymorphic_method(recipient, record_or_hash_or_array, action, type, options)
|
194
|
+
builder = get action, type
|
195
|
+
|
196
|
+
case record_or_hash_or_array
|
197
|
+
when Array
|
198
|
+
record_or_hash_or_array = record_or_hash_or_array.compact
|
199
|
+
if record_or_hash_or_array.empty?
|
200
|
+
raise ArgumentError, "Nil location provided. Can't build URI."
|
201
|
+
end
|
202
|
+
if record_or_hash_or_array.first.is_a?(ActionDispatch::Routing::RoutesProxy)
|
203
|
+
recipient = record_or_hash_or_array.shift
|
176
204
|
end
|
205
|
+
|
206
|
+
method, args = builder.handle_list record_or_hash_or_array
|
207
|
+
when String, Symbol
|
208
|
+
method, args = builder.handle_string record_or_hash_or_array
|
209
|
+
when Class
|
210
|
+
method, args = builder.handle_class record_or_hash_or_array
|
211
|
+
|
212
|
+
when nil
|
213
|
+
raise ArgumentError, "Nil location provided. Can't build URI."
|
214
|
+
else
|
215
|
+
method, args = builder.handle_model record_or_hash_or_array
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
if options.empty?
|
220
|
+
recipient.send(method, *args)
|
177
221
|
else
|
178
|
-
|
179
|
-
route = []
|
222
|
+
recipient.send(method, *args, options)
|
180
223
|
end
|
224
|
+
end
|
225
|
+
|
226
|
+
attr_reader :suffix, :prefix
|
181
227
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
228
|
+
def initialize(key_strategy, prefix, suffix)
|
229
|
+
@key_strategy = key_strategy
|
230
|
+
@prefix = prefix
|
231
|
+
@suffix = suffix
|
232
|
+
end
|
233
|
+
|
234
|
+
def handle_string(record)
|
235
|
+
[get_method_for_string(record), []]
|
236
|
+
end
|
237
|
+
|
238
|
+
def handle_string_call(target, str)
|
239
|
+
target.send get_method_for_string str
|
240
|
+
end
|
241
|
+
|
242
|
+
def handle_class(klass)
|
243
|
+
[get_method_for_class(klass), []]
|
244
|
+
end
|
245
|
+
|
246
|
+
def handle_class_call(target, klass)
|
247
|
+
target.send get_method_for_class klass
|
248
|
+
end
|
249
|
+
|
250
|
+
def handle_model(record)
|
251
|
+
args = []
|
252
|
+
|
253
|
+
model = record.to_model
|
254
|
+
name = if model.persisted?
|
255
|
+
args << model
|
256
|
+
model.model_name.singular_route_key
|
257
|
+
else
|
258
|
+
@key_strategy.call model.model_name
|
259
|
+
end
|
260
|
+
|
261
|
+
named_route = prefix + "#{name}_#{suffix}"
|
262
|
+
|
263
|
+
[named_route, args]
|
264
|
+
end
|
265
|
+
|
266
|
+
def handle_model_call(target, model)
|
267
|
+
method, args = handle_model model
|
268
|
+
target.send(method, *args)
|
269
|
+
end
|
270
|
+
|
271
|
+
def handle_list(list)
|
272
|
+
record_list = list.dup
|
273
|
+
record = record_list.pop
|
274
|
+
|
275
|
+
args = []
|
276
|
+
|
277
|
+
route = record_list.map { |parent|
|
278
|
+
case parent
|
279
|
+
when Symbol, String
|
280
|
+
parent.to_s
|
281
|
+
when Class
|
282
|
+
args << parent
|
283
|
+
parent.model_name.singular_route_key
|
187
284
|
else
|
188
|
-
|
285
|
+
args << parent.to_model
|
286
|
+
parent.to_model.model_name.singular_route_key
|
189
287
|
end
|
288
|
+
}
|
289
|
+
|
290
|
+
route <<
|
291
|
+
case record
|
292
|
+
when Symbol, String
|
293
|
+
record.to_s
|
294
|
+
when Class
|
295
|
+
@key_strategy.call record.model_name
|
190
296
|
else
|
191
|
-
|
297
|
+
model = record.to_model
|
298
|
+
if model.persisted?
|
299
|
+
args << model
|
300
|
+
model.model_name.singular_route_key
|
301
|
+
else
|
302
|
+
@key_strategy.call model.model_name
|
303
|
+
end
|
192
304
|
end
|
193
305
|
|
194
|
-
route <<
|
306
|
+
route << suffix
|
195
307
|
|
196
|
-
|
308
|
+
named_route = prefix + route.join("_")
|
309
|
+
[named_route, args]
|
197
310
|
end
|
198
311
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
312
|
+
private
|
313
|
+
|
314
|
+
def get_method_for_class(klass)
|
315
|
+
name = @key_strategy.call klass.model_name
|
316
|
+
prefix + "#{name}_#{suffix}"
|
317
|
+
end
|
318
|
+
|
319
|
+
def get_method_for_string(str)
|
320
|
+
prefix + "#{str}_#{suffix}"
|
205
321
|
end
|
322
|
+
|
323
|
+
[nil, 'new', 'edit'].each do |action|
|
324
|
+
CACHE['url'][action] = build action, 'url'
|
325
|
+
CACHE['path'][action] = build action, 'path'
|
326
|
+
end
|
327
|
+
end
|
206
328
|
end
|
207
329
|
end
|
208
330
|
end
|
209
|
-
|
@@ -1,10 +1,13 @@
|
|
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'
|
6
|
+
require 'action_dispatch/routing/endpoint'
|
4
7
|
|
5
8
|
module ActionDispatch
|
6
9
|
module Routing
|
7
|
-
class Redirect # :nodoc:
|
10
|
+
class Redirect < Endpoint # :nodoc:
|
8
11
|
attr_reader :status, :block
|
9
12
|
|
10
13
|
def initialize(status, block)
|
@@ -12,15 +15,29 @@ module ActionDispatch
|
|
12
15
|
@block = block
|
13
16
|
end
|
14
17
|
|
18
|
+
def redirect?; true; end
|
19
|
+
|
15
20
|
def call(env)
|
16
|
-
|
21
|
+
serve Request.new env
|
22
|
+
end
|
17
23
|
|
18
|
-
|
24
|
+
def serve(req)
|
25
|
+
req.check_path_parameters!
|
26
|
+
uri = URI.parse(path(req.path_parameters, req))
|
27
|
+
|
28
|
+
unless uri.host
|
29
|
+
if relative_path?(uri.path)
|
30
|
+
uri.path = "#{req.script_name}/#{uri.path}"
|
31
|
+
elsif uri.path.empty?
|
32
|
+
uri.path = req.script_name.empty? ? "/" : req.script_name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
19
36
|
uri.scheme ||= req.scheme
|
20
37
|
uri.host ||= req.host
|
21
38
|
uri.port ||= req.port unless req.standard_port?
|
22
39
|
|
23
|
-
body = %(<html><body>You are being <a href="#{ERB::Util.
|
40
|
+
body = %(<html><body>You are being <a href="#{ERB::Util.unwrapped_html_escape(uri.to_s)}">redirected</a>.</body></html>)
|
24
41
|
|
25
42
|
headers = {
|
26
43
|
'Location' => uri.to_s,
|
@@ -34,6 +51,52 @@ module ActionDispatch
|
|
34
51
|
def path(params, request)
|
35
52
|
block.call params, request
|
36
53
|
end
|
54
|
+
|
55
|
+
def inspect
|
56
|
+
"redirect(#{status})"
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def relative_path?(path)
|
61
|
+
path && !path.empty? && path[0] != '/'
|
62
|
+
end
|
63
|
+
|
64
|
+
def escape(params)
|
65
|
+
Hash[params.map{ |k,v| [k, Rack::Utils.escape(v)] }]
|
66
|
+
end
|
67
|
+
|
68
|
+
def escape_fragment(params)
|
69
|
+
Hash[params.map{ |k,v| [k, Journey::Router::Utils.escape_fragment(v)] }]
|
70
|
+
end
|
71
|
+
|
72
|
+
def escape_path(params)
|
73
|
+
Hash[params.map{ |k,v| [k, Journey::Router::Utils.escape_path(v)] }]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class PathRedirect < Redirect
|
78
|
+
URL_PARTS = /\A([^?]+)?(\?[^#]+)?(#.+)?\z/
|
79
|
+
|
80
|
+
def path(params, request)
|
81
|
+
if block.match(URL_PARTS)
|
82
|
+
path = interpolation_required?($1, params) ? $1 % escape_path(params) : $1
|
83
|
+
query = interpolation_required?($2, params) ? $2 % escape(params) : $2
|
84
|
+
fragment = interpolation_required?($3, params) ? $3 % escape_fragment(params) : $3
|
85
|
+
|
86
|
+
"#{path}#{query}#{fragment}"
|
87
|
+
else
|
88
|
+
interpolation_required?(block, params) ? block % escape(params) : block
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def inspect
|
93
|
+
"redirect(#{status}, #{block})"
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def interpolation_required?(string, params)
|
98
|
+
!params.empty? && string && string.match(/%\{\w*\}/)
|
99
|
+
end
|
37
100
|
end
|
38
101
|
|
39
102
|
class OptionRedirect < Redirect # :nodoc:
|
@@ -46,30 +109,43 @@ module ActionDispatch
|
|
46
109
|
:port => request.optional_port,
|
47
110
|
:path => request.path,
|
48
111
|
:params => request.query_parameters
|
49
|
-
}.merge options
|
112
|
+
}.merge! options
|
50
113
|
|
51
114
|
if !params.empty? && url_options[:path].match(/%\{\w*\}/)
|
52
115
|
url_options[:path] = (url_options[:path] % escape_path(params))
|
53
116
|
end
|
54
117
|
|
118
|
+
unless options[:host] || options[:domain]
|
119
|
+
if relative_path?(url_options[:path])
|
120
|
+
url_options[:path] = "/#{url_options[:path]}"
|
121
|
+
url_options[:script_name] = request.script_name
|
122
|
+
elsif url_options[:path].empty?
|
123
|
+
url_options[:path] = request.script_name.empty? ? "/" : ""
|
124
|
+
url_options[:script_name] = request.script_name
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
55
128
|
ActionDispatch::Http::URL.url_for url_options
|
56
129
|
end
|
57
130
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
131
|
+
def inspect
|
132
|
+
"redirect(#{status}, #{options.map{ |k,v| "#{k}: #{v}" }.join(', ')})"
|
133
|
+
end
|
62
134
|
end
|
63
135
|
|
64
136
|
module Redirection
|
65
137
|
|
66
138
|
# Redirect any path to another path:
|
67
139
|
#
|
68
|
-
#
|
140
|
+
# get "/stories" => redirect("/posts")
|
69
141
|
#
|
70
142
|
# You can also use interpolation in the supplied redirect argument:
|
71
143
|
#
|
72
|
-
#
|
144
|
+
# get 'docs/:article', to: redirect('/wiki/%{article}')
|
145
|
+
#
|
146
|
+
# Note that if you return a path without a leading slash then the url is prefixed with the
|
147
|
+
# current SCRIPT_NAME environment variable. This is typically '/' but may be different in
|
148
|
+
# a mounted engine or where the application is deployed to a subdirectory of a website.
|
73
149
|
#
|
74
150
|
# Alternatively you can use one of the other syntaxes:
|
75
151
|
#
|
@@ -78,54 +154,38 @@ module ActionDispatch
|
|
78
154
|
# params, depending of how many arguments your block accepts. A string is required as a
|
79
155
|
# return value.
|
80
156
|
#
|
81
|
-
#
|
157
|
+
# get 'jokes/:number', to: redirect { |params, request|
|
82
158
|
# path = (params[:number].to_i.even? ? "wheres-the-beef" : "i-love-lamp")
|
83
159
|
# "http://#{request.host_with_port}/#{path}"
|
84
160
|
# }
|
85
161
|
#
|
162
|
+
# Note that the +do end+ syntax for the redirect block wouldn't work, as Ruby would pass
|
163
|
+
# the block to +get+ instead of +redirect+. Use <tt>{ ... }</tt> instead.
|
164
|
+
#
|
86
165
|
# The options version of redirect allows you to supply only the parts of the url which need
|
87
166
|
# to change, it also supports interpolation of the path similar to the first example.
|
88
167
|
#
|
89
|
-
#
|
90
|
-
#
|
168
|
+
# get 'stores/:name', to: redirect(subdomain: 'stores', path: '/%{name}')
|
169
|
+
# get 'stores/:name(*all)', to: redirect(subdomain: 'stores', path: '/%{name}%{all}')
|
91
170
|
#
|
92
171
|
# Finally, an object which responds to call can be supplied to redirect, allowing you to reuse
|
93
172
|
# common redirect routes. The call method must accept two arguments, params and request, and return
|
94
173
|
# a string.
|
95
174
|
#
|
96
|
-
#
|
175
|
+
# get 'accounts/:name' => redirect(SubdomainRedirector.new('api'))
|
97
176
|
#
|
98
177
|
def redirect(*args, &block)
|
99
|
-
options = args.
|
178
|
+
options = args.extract_options!
|
100
179
|
status = options.delete(:status) || 301
|
180
|
+
path = args.shift
|
101
181
|
|
102
182
|
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
|
183
|
+
return PathRedirect.new(status, path) if String === path
|
109
184
|
|
110
185
|
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
186
|
raise ArgumentError, "redirection argument not supported" unless block
|
121
|
-
|
122
187
|
Redirect.new status, block
|
123
188
|
end
|
124
|
-
|
125
|
-
private
|
126
|
-
def escape(params)
|
127
|
-
Hash[params.map{ |k,v| [k, Rack::Utils.escape(v)] }]
|
128
|
-
end
|
129
189
|
end
|
130
190
|
end
|
131
191
|
end
|