actionpack 3.2.19 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +850 -401
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -288
- 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 +25 -13
- data/lib/abstract_controller/layouts.rb +74 -74
- data/lib/abstract_controller/logger.rb +1 -2
- data/lib/abstract_controller/rendering.rb +30 -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/abstract_controller.rb +1 -8
- data/lib/action_controller/base.rb +46 -22
- data/lib/action_controller/caching/fragments.rb +23 -53
- data/lib/action_controller/caching.rb +46 -33
- data/lib/action_controller/deprecated/integration_test.rb +3 -0
- data/lib/action_controller/deprecated.rb +5 -1
- data/lib/action_controller/log_subscriber.rb +16 -8
- 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 +70 -12
- data/lib/action_controller/metal/head.rb +25 -4
- data/lib/action_controller/metal/helpers.rb +5 -9
- data/lib/action_controller/metal/hide_actions.rb +0 -1
- data/lib/action_controller/metal/http_authentication.rb +107 -83
- 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 +175 -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 +9 -1
- 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 +520 -0
- data/lib/action_controller/metal/testing.rb +13 -18
- data/lib/action_controller/metal/url_for.rb +28 -25
- data/lib/action_controller/metal.rb +17 -32
- 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 +251 -131
- data/lib/action_controller/vendor/html-scanner.rb +4 -19
- data/lib/action_controller.rb +15 -6
- 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 +49 -17
- data/lib/action_dispatch/http/mime_negotiation.rb +24 -1
- data/lib/action_dispatch/http/mime_type.rb +154 -100
- 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 +28 -28
- data/lib/action_dispatch/http/rack_cache.rb +2 -3
- data/lib/action_dispatch/http/request.rb +64 -18
- data/lib/action_dispatch/http/response.rb +130 -35
- data/lib/action_dispatch/http/upload.rb +63 -20
- data/lib/action_dispatch/http/url.rb +98 -35
- 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 +124 -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/router.rb +166 -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 +197 -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/journey.rb +5 -0
- data/lib/action_dispatch/middleware/callbacks.rb +9 -4
- data/lib/action_dispatch/middleware/cookies.rb +259 -114
- data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -17
- data/lib/action_dispatch/middleware/exception_wrapper.rb +29 -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 +30 -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/cookie_store.rb +82 -28
- 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 +2 -1
- 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 +7 -9
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +15 -9
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +127 -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/inspector.rb +240 -0
- data/lib/action_dispatch/routing/mapper.rb +540 -291
- 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 +207 -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/routing.rb +48 -83
- 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 +42 -41
- data/lib/action_dispatch/testing/assertions/selector.rb +17 -22
- data/lib/action_dispatch/testing/assertions/tag.rb +20 -23
- data/lib/action_dispatch/testing/integration.rb +65 -51
- data/lib/action_dispatch/testing/test_process.rb +9 -6
- data/lib/action_dispatch/testing/test_request.rb +7 -3
- data/lib/action_dispatch.rb +21 -15
- data/lib/action_pack/version.rb +7 -6
- data/lib/action_pack.rb +1 -1
- data/lib/action_view/base.rb +15 -34
- data/lib/action_view/buffers.rb +7 -1
- data/lib/action_view/context.rb +4 -4
- data/lib/action_view/dependency_tracker.rb +93 -0
- data/lib/action_view/digestor.rb +85 -0
- data/lib/action_view/flows.rb +1 -4
- data/lib/action_view/helpers/active_model_helper.rb +3 -4
- data/lib/action_view/helpers/asset_tag_helper.rb +215 -352
- data/lib/action_view/helpers/asset_url_helper.rb +355 -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 +44 -31
- data/lib/action_view/helpers/csrf_helper.rb +0 -2
- data/lib/action_view/helpers/date_helper.rb +269 -248
- data/lib/action_view/helpers/debug_helper.rb +10 -11
- data/lib/action_view/helpers/form_helper.rb +931 -537
- data/lib/action_view/helpers/form_options_helper.rb +341 -166
- data/lib/action_view/helpers/form_tag_helper.rb +190 -90
- data/lib/action_view/helpers/javascript_helper.rb +23 -16
- data/lib/action_view/helpers/number_helper.rb +148 -329
- 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 -2
- data/lib/action_view/helpers/sanitize_helper.rb +3 -6
- data/lib/action_view/helpers/tag_helper.rb +46 -33
- data/lib/action_view/helpers/tags/base.rb +147 -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 +40 -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/tags.rb +39 -0
- data/lib/action_view/helpers/text_helper.rb +130 -114
- data/lib/action_view/helpers/translation_helper.rb +32 -16
- data/lib/action_view/helpers/url_helper.rb +211 -270
- data/lib/action_view/helpers.rb +2 -4
- 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 -28
- data/lib/action_view/model_naming.rb +12 -0
- data/lib/action_view/path_set.rb +8 -20
- 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 +25 -19
- data/lib/action_view/renderer/partial_renderer.rb +158 -81
- data/lib/action_view/renderer/renderer.rb +8 -12
- data/lib/action_view/renderer/streaming_template_renderer.rb +2 -5
- data/lib/action_view/renderer/template_renderer.rb +12 -10
- data/lib/action_view/routing_url_for.rb +107 -0
- data/lib/action_view/template/error.rb +22 -12
- data/lib/action_view/template/handlers/builder.rb +1 -1
- data/lib/action_view/template/handlers/erb.rb +40 -19
- data/lib/action_view/template/handlers/raw.rb +11 -0
- data/lib/action_view/template/handlers.rb +12 -9
- data/lib/action_view/template/resolver.rb +107 -53
- data/lib/action_view/template/text.rb +12 -8
- data/lib/action_view/template/types.rb +57 -0
- data/lib/action_view/template.rb +25 -23
- data/lib/action_view/test_case.rb +67 -42
- 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 +13 -2
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/selector.rb +9 -9
- 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
- data/lib/action_view/vendor/html-scanner.rb +20 -0
- data/lib/action_view.rb +17 -8
- metadata +184 -214
- 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/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,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,22 @@ 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
|
+
next unless value.respond_to?(:valid_encoding?)
|
|
35
|
+
|
|
36
|
+
unless value.valid_encoding?
|
|
37
|
+
raise ActionController::BadRequest, "Invalid parameter: #{key} => #{value}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
29
41
|
prepare_params!(params)
|
|
30
42
|
|
|
31
43
|
# Just raise undefined constant errors if a controller was specified as default.
|
|
@@ -60,13 +72,8 @@ module ActionDispatch
|
|
|
60
72
|
private
|
|
61
73
|
|
|
62
74
|
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)
|
|
75
|
+
const_name = @controller_class_names[controller_param] ||= "#{controller_param.camelize}Controller"
|
|
76
|
+
ActiveSupport::Dependencies.constantize(const_name)
|
|
70
77
|
end
|
|
71
78
|
|
|
72
79
|
def dispatch(controller, action, env)
|
|
@@ -94,14 +101,13 @@ module ActionDispatch
|
|
|
94
101
|
attr_reader :routes, :helpers, :module
|
|
95
102
|
|
|
96
103
|
def initialize
|
|
97
|
-
@routes
|
|
104
|
+
@routes = {}
|
|
98
105
|
@helpers = []
|
|
99
|
-
|
|
100
|
-
@module = Module.new
|
|
106
|
+
@module = Module.new
|
|
101
107
|
end
|
|
102
108
|
|
|
103
109
|
def helper_names
|
|
104
|
-
|
|
110
|
+
@helpers.map(&:to_s)
|
|
105
111
|
end
|
|
106
112
|
|
|
107
113
|
def clear!
|
|
@@ -139,90 +145,125 @@ module ActionDispatch
|
|
|
139
145
|
routes.length
|
|
140
146
|
end
|
|
141
147
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
148
|
+
class UrlHelper # :nodoc:
|
|
149
|
+
def self.create(route, options)
|
|
150
|
+
if optimize_helper?(route)
|
|
151
|
+
OptimizedUrlHelper.new(route, options)
|
|
152
|
+
else
|
|
153
|
+
new route, options
|
|
154
|
+
end
|
|
147
155
|
end
|
|
148
|
-
end
|
|
149
156
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
Array(destinations).each do |dest|
|
|
153
|
-
dest.__send__(:include, @module)
|
|
157
|
+
def self.optimize_helper?(route)
|
|
158
|
+
route.requirements.except(:controller, :action).empty?
|
|
154
159
|
end
|
|
155
|
-
end
|
|
156
160
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
:"#{name}_#{kind}"
|
|
160
|
-
end
|
|
161
|
+
class OptimizedUrlHelper < UrlHelper # :nodoc:
|
|
162
|
+
attr_reader :arg_size
|
|
161
163
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
def initialize(route, options)
|
|
165
|
+
super
|
|
166
|
+
@path_parts = @route.required_parts
|
|
167
|
+
@arg_size = @path_parts.size
|
|
168
|
+
@string_route = @route.optimized_path
|
|
169
|
+
end
|
|
165
170
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
+
def call(t, args)
|
|
172
|
+
if args.size == arg_size && !args.last.is_a?(Hash) && optimize_routes_generation?(t)
|
|
173
|
+
options = @options.dup
|
|
174
|
+
options.merge!(t.url_options) if t.respond_to?(:url_options)
|
|
175
|
+
options[:path] = optimized_helper(args)
|
|
176
|
+
ActionDispatch::Http::URL.url_for(options)
|
|
177
|
+
else
|
|
178
|
+
super
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
private
|
|
183
|
+
|
|
184
|
+
def optimized_helper(args)
|
|
185
|
+
path = @string_route.dup
|
|
186
|
+
klass = Journey::Router::Utils
|
|
187
|
+
|
|
188
|
+
@path_parts.zip(args) do |part, arg|
|
|
189
|
+
# Replace each route parameter
|
|
190
|
+
# e.g. :id for regular parameter or *path for globbing
|
|
191
|
+
# with ruby string interpolation code
|
|
192
|
+
path.gsub!(/(\*|:)#{part}/, klass.escape_fragment(arg.to_param))
|
|
193
|
+
end
|
|
194
|
+
path
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def optimize_routes_generation?(t)
|
|
198
|
+
t.send(:optimize_routes_generation?)
|
|
171
199
|
end
|
|
172
200
|
end
|
|
173
201
|
|
|
174
|
-
def
|
|
175
|
-
|
|
202
|
+
def initialize(route, options)
|
|
203
|
+
@options = options
|
|
204
|
+
@segment_keys = route.segment_keys
|
|
205
|
+
@route = route
|
|
206
|
+
end
|
|
176
207
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
def #{selector}(*args)
|
|
181
|
-
options = args.extract_options!
|
|
182
|
-
result = #{options.inspect}
|
|
208
|
+
def call(t, args)
|
|
209
|
+
t.url_for(handle_positional_args(t, args, @options, @segment_keys))
|
|
210
|
+
end
|
|
183
211
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
end
|
|
212
|
+
def handle_positional_args(t, args, options, keys)
|
|
213
|
+
inner_options = args.extract_options!
|
|
214
|
+
result = options.dup
|
|
188
215
|
|
|
189
|
-
|
|
216
|
+
if args.size > 0
|
|
217
|
+
if args.size < keys.size - 1 # take format into account
|
|
218
|
+
keys -= t.url_options.keys if t.respond_to?(:url_options)
|
|
219
|
+
keys -= options.keys
|
|
190
220
|
end
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
221
|
+
keys -= inner_options.keys
|
|
222
|
+
result.merge!(Hash[keys.zip(args)])
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
result.merge!(inner_options)
|
|
194
226
|
end
|
|
227
|
+
end
|
|
195
228
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
END_EVAL
|
|
219
|
-
helpers << selector
|
|
229
|
+
private
|
|
230
|
+
# Create a url helper allowing ordered parameters to be associated
|
|
231
|
+
# with corresponding dynamic segments, so you can do:
|
|
232
|
+
#
|
|
233
|
+
# foo_url(bar, baz, bang)
|
|
234
|
+
#
|
|
235
|
+
# Instead of:
|
|
236
|
+
#
|
|
237
|
+
# foo_url(bar: bar, baz: baz, bang: bang)
|
|
238
|
+
#
|
|
239
|
+
# Also allow options hash, so you can do:
|
|
240
|
+
#
|
|
241
|
+
# foo_url(bar, baz, bang, sort_by: 'baz')
|
|
242
|
+
#
|
|
243
|
+
def define_url_helper(route, name, options)
|
|
244
|
+
helper = UrlHelper.create(route, options.dup)
|
|
245
|
+
|
|
246
|
+
@module.remove_possible_method name
|
|
247
|
+
@module.module_eval do
|
|
248
|
+
define_method(name) do |*args|
|
|
249
|
+
helper.call self, args
|
|
250
|
+
end
|
|
220
251
|
end
|
|
252
|
+
|
|
253
|
+
helpers << name
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def define_named_route_methods(name, route)
|
|
257
|
+
define_url_helper route, :"#{name}_path",
|
|
258
|
+
route.defaults.merge(:use_route => name, :only_path => true)
|
|
259
|
+
define_url_helper route, :"#{name}_url",
|
|
260
|
+
route.defaults.merge(:use_route => name, :only_path => false)
|
|
261
|
+
end
|
|
221
262
|
end
|
|
222
263
|
|
|
223
264
|
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
|
|
224
265
|
attr_accessor :disable_clear_and_finalize, :resources_path_names
|
|
225
|
-
attr_accessor :default_url_options, :request_class
|
|
266
|
+
attr_accessor :default_url_options, :request_class
|
|
226
267
|
|
|
227
268
|
alias :routes :set
|
|
228
269
|
|
|
@@ -234,17 +275,7 @@ module ActionDispatch
|
|
|
234
275
|
self.named_routes = NamedRouteCollection.new
|
|
235
276
|
self.resources_path_names = self.class.default_resources_path_names.dup
|
|
236
277
|
self.default_url_options = {}
|
|
237
|
-
|
|
238
278
|
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
279
|
|
|
249
280
|
@append = []
|
|
250
281
|
@prepend = []
|
|
@@ -300,14 +331,15 @@ module ActionDispatch
|
|
|
300
331
|
@prepend.each { |blk| eval_block(blk) }
|
|
301
332
|
end
|
|
302
333
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
module MountedHelpers
|
|
334
|
+
module MountedHelpers #:nodoc:
|
|
335
|
+
extend ActiveSupport::Concern
|
|
336
|
+
include UrlFor
|
|
309
337
|
end
|
|
310
338
|
|
|
339
|
+
# Contains all the mounted helpers accross different
|
|
340
|
+
# engines and the `main_app` helper for the application.
|
|
341
|
+
# You can include this in your classes if you want to
|
|
342
|
+
# access routes for other engines.
|
|
311
343
|
def mounted_helpers
|
|
312
344
|
MountedHelpers
|
|
313
345
|
end
|
|
@@ -318,13 +350,13 @@ module ActionDispatch
|
|
|
318
350
|
routes = self
|
|
319
351
|
MountedHelpers.class_eval do
|
|
320
352
|
define_method "_#{name}" do
|
|
321
|
-
RoutesProxy.new(routes,
|
|
353
|
+
RoutesProxy.new(routes, _routes_context)
|
|
322
354
|
end
|
|
323
355
|
end
|
|
324
356
|
|
|
325
|
-
MountedHelpers.class_eval
|
|
357
|
+
MountedHelpers.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
326
358
|
def #{name}
|
|
327
|
-
|
|
359
|
+
@_#{name} ||= _#{name}
|
|
328
360
|
end
|
|
329
361
|
RUBY
|
|
330
362
|
end
|
|
@@ -333,28 +365,36 @@ module ActionDispatch
|
|
|
333
365
|
@url_helpers ||= begin
|
|
334
366
|
routes = self
|
|
335
367
|
|
|
336
|
-
|
|
368
|
+
Module.new do
|
|
337
369
|
extend ActiveSupport::Concern
|
|
338
370
|
include UrlFor
|
|
339
371
|
|
|
372
|
+
# Define url_for in the singleton level so one can do:
|
|
373
|
+
# Rails.application.routes.url_helpers.url_for(args)
|
|
340
374
|
@_routes = routes
|
|
341
375
|
class << self
|
|
342
|
-
delegate :url_for, :to => '@_routes'
|
|
376
|
+
delegate :url_for, :optimize_routes_generation?, :to => '@_routes'
|
|
343
377
|
end
|
|
378
|
+
|
|
379
|
+
# Make named_routes available in the module singleton
|
|
380
|
+
# as well, so one can do:
|
|
381
|
+
# Rails.application.routes.url_helpers.posts_path
|
|
344
382
|
extend routes.named_routes.module
|
|
345
383
|
|
|
346
|
-
#
|
|
347
|
-
#
|
|
348
|
-
|
|
384
|
+
# Any class that includes this module will get all
|
|
385
|
+
# named routes...
|
|
386
|
+
include routes.named_routes.module
|
|
387
|
+
|
|
388
|
+
# plus a singleton class method called _routes ...
|
|
349
389
|
included do
|
|
350
|
-
routes.install_helpers(self)
|
|
351
390
|
singleton_class.send(:redefine_method, :_routes) { routes }
|
|
352
391
|
end
|
|
353
392
|
|
|
393
|
+
# And an instance method _routes. Note that
|
|
394
|
+
# UrlFor (included in this module) add extra
|
|
395
|
+
# conveniences for working with @_routes.
|
|
354
396
|
define_method(:_routes) { @_routes || routes }
|
|
355
397
|
end
|
|
356
|
-
|
|
357
|
-
helpers
|
|
358
398
|
end
|
|
359
399
|
end
|
|
360
400
|
|
|
@@ -365,8 +405,16 @@ module ActionDispatch
|
|
|
365
405
|
def add_route(app, conditions = {}, requirements = {}, defaults = {}, name = nil, anchor = true)
|
|
366
406
|
raise ArgumentError, "Invalid route name: '#{name}'" unless name.blank? || name.to_s.match(/^[_a-z]\w*$/i)
|
|
367
407
|
|
|
408
|
+
if name && named_routes[name]
|
|
409
|
+
raise ArgumentError, "Invalid route name, already in use: '#{name}' \n" \
|
|
410
|
+
"You may have defined two routes with the same name using the `:as` option, or " \
|
|
411
|
+
"you may be overriding a route already defined by a resource with the same naming. " \
|
|
412
|
+
"For the latter, you can restrict the routes created with `resources` as explained here: \n" \
|
|
413
|
+
"http://guides.rubyonrails.org/routing.html#restricting-the-routes-created"
|
|
414
|
+
end
|
|
415
|
+
|
|
368
416
|
path = build_path(conditions.delete(:path_info), requirements, SEPARATORS, anchor)
|
|
369
|
-
conditions = build_conditions(conditions,
|
|
417
|
+
conditions = build_conditions(conditions, path.names.map { |x| x.to_sym })
|
|
370
418
|
|
|
371
419
|
route = @set.add_route(app, path, conditions, defaults, name)
|
|
372
420
|
named_routes[name] = route if name
|
|
@@ -403,21 +451,22 @@ module ActionDispatch
|
|
|
403
451
|
end
|
|
404
452
|
private :build_path
|
|
405
453
|
|
|
406
|
-
def build_conditions(current_conditions,
|
|
454
|
+
def build_conditions(current_conditions, path_values)
|
|
407
455
|
conditions = current_conditions.dup
|
|
408
456
|
|
|
409
|
-
verbs = conditions[:request_method] || []
|
|
410
|
-
|
|
411
457
|
# Rack-Mount requires that :request_method be a regular expression.
|
|
412
458
|
# :request_method represents the HTTP verb that matches this route.
|
|
413
459
|
#
|
|
414
460
|
# Here we munge values before they get sent on to rack-mount.
|
|
461
|
+
verbs = conditions[:request_method] || []
|
|
415
462
|
unless verbs.empty?
|
|
416
463
|
conditions[:request_method] = %r[^#{verbs.join('|')}$]
|
|
417
464
|
end
|
|
418
|
-
conditions.delete_if { |k,v| !(req_predicates.include?(k) || path_values.include?(k)) }
|
|
419
465
|
|
|
420
|
-
conditions
|
|
466
|
+
conditions.keep_if do |k, _|
|
|
467
|
+
k == :action || k == :controller || k == :required_defaults ||
|
|
468
|
+
@request_class.public_method_defined?(k) || path_values.include?(k)
|
|
469
|
+
end
|
|
421
470
|
end
|
|
422
471
|
private :build_conditions
|
|
423
472
|
|
|
@@ -434,12 +483,11 @@ module ActionDispatch
|
|
|
434
483
|
|
|
435
484
|
attr_reader :options, :recall, :set, :named_route
|
|
436
485
|
|
|
437
|
-
def initialize(options, recall, set
|
|
486
|
+
def initialize(options, recall, set)
|
|
438
487
|
@named_route = options.delete(:use_route)
|
|
439
488
|
@options = options.dup
|
|
440
489
|
@recall = recall.dup
|
|
441
490
|
@set = set
|
|
442
|
-
@extras = extras
|
|
443
491
|
|
|
444
492
|
normalize_options!
|
|
445
493
|
normalize_controller_action_id!
|
|
@@ -458,9 +506,7 @@ module ActionDispatch
|
|
|
458
506
|
|
|
459
507
|
def use_recall_for(key)
|
|
460
508
|
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
|
|
509
|
+
if !named_route_exists? || segment_keys.include?(key)
|
|
464
510
|
@options[key] = @recall.delete(key)
|
|
465
511
|
end
|
|
466
512
|
end
|
|
@@ -470,7 +516,7 @@ module ActionDispatch
|
|
|
470
516
|
# If an explicit :controller was given, always make :action explicit
|
|
471
517
|
# too, so that action expiry works as expected for things like
|
|
472
518
|
#
|
|
473
|
-
# generate({:
|
|
519
|
+
# generate({controller: 'content'}, {controller: 'content', action: 'show'})
|
|
474
520
|
#
|
|
475
521
|
# (the above is from the unit tests). In the above case, because the
|
|
476
522
|
# controller was explicitly given, but no action, the action is implied to
|
|
@@ -499,7 +545,7 @@ module ActionDispatch
|
|
|
499
545
|
use_recall_for(:id)
|
|
500
546
|
end
|
|
501
547
|
|
|
502
|
-
# if the current controller is "foo/bar/baz" and :
|
|
548
|
+
# if the current controller is "foo/bar/baz" and controller: "baz/bat"
|
|
503
549
|
# is specified, the controller becomes "foo/baz/bat"
|
|
504
550
|
def use_relative_controller!
|
|
505
551
|
if !named_route && different_controller? && !controller.start_with?("/")
|
|
@@ -515,8 +561,8 @@ module ActionDispatch
|
|
|
515
561
|
@options[:controller] = controller.sub(%r{^/}, '') if controller
|
|
516
562
|
end
|
|
517
563
|
|
|
518
|
-
# This handles the case of :
|
|
519
|
-
# It is identical to :
|
|
564
|
+
# This handles the case of action: nil being explicitly passed.
|
|
565
|
+
# It is identical to action: "index"
|
|
520
566
|
def handle_nil_action!
|
|
521
567
|
if options.has_key?(:action) && options[:action].nil?
|
|
522
568
|
options[:action] = 'index'
|
|
@@ -524,20 +570,10 @@ module ActionDispatch
|
|
|
524
570
|
recall[:action] = options.delete(:action) if options[:action] == 'index'
|
|
525
571
|
end
|
|
526
572
|
|
|
573
|
+
# Generates a path from routes, returns [path, params].
|
|
574
|
+
# If no route is generated the formatter will raise ActionController::UrlGenerationError
|
|
527
575
|
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}"
|
|
576
|
+
@set.formatter.generate(:path_info, named_route, options, recall, PARAMETERIZE)
|
|
541
577
|
end
|
|
542
578
|
|
|
543
579
|
def different_controller?
|
|
@@ -562,41 +598,53 @@ module ActionDispatch
|
|
|
562
598
|
end
|
|
563
599
|
|
|
564
600
|
def generate_extras(options, recall={})
|
|
565
|
-
generate(options, recall
|
|
601
|
+
path, params = generate(options, recall)
|
|
602
|
+
return path, params.keys
|
|
566
603
|
end
|
|
567
604
|
|
|
568
|
-
def generate(options, recall = {}
|
|
569
|
-
Generator.new(options, recall, self
|
|
605
|
+
def generate(options, recall = {})
|
|
606
|
+
Generator.new(options, recall, self).generate
|
|
570
607
|
end
|
|
571
608
|
|
|
572
609
|
RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length,
|
|
573
|
-
:trailing_slash, :anchor, :params, :only_path, :script_name
|
|
610
|
+
:trailing_slash, :anchor, :params, :only_path, :script_name,
|
|
611
|
+
:original_script_name]
|
|
612
|
+
|
|
613
|
+
def mounted?
|
|
614
|
+
false
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
def optimize_routes_generation?
|
|
618
|
+
!mounted? && default_url_options.empty?
|
|
619
|
+
end
|
|
574
620
|
|
|
575
621
|
def _generate_prefix(options = {})
|
|
576
622
|
nil
|
|
577
623
|
end
|
|
578
624
|
|
|
625
|
+
# The +options+ argument must be +nil+ or a hash whose keys are *symbols*.
|
|
579
626
|
def url_for(options)
|
|
580
|
-
|
|
581
|
-
options = (options || {}).reverse_merge!(default_url_options)
|
|
582
|
-
|
|
583
|
-
handle_positional_args(options)
|
|
627
|
+
options = default_url_options.merge(options || {})
|
|
584
628
|
|
|
585
629
|
user, password = extract_authentication(options)
|
|
586
|
-
|
|
587
|
-
|
|
630
|
+
recall = options.delete(:_recall)
|
|
631
|
+
|
|
632
|
+
original_script_name = options.delete(:original_script_name).presence
|
|
633
|
+
script_name = options.delete(:script_name).presence || _generate_prefix(options)
|
|
588
634
|
|
|
589
|
-
|
|
635
|
+
if script_name && original_script_name
|
|
636
|
+
script_name = original_script_name + script_name
|
|
637
|
+
end
|
|
590
638
|
|
|
591
639
|
path_options = options.except(*RESERVED_OPTIONS)
|
|
592
640
|
path_options = yield(path_options) if block_given?
|
|
593
641
|
|
|
594
|
-
|
|
595
|
-
path << path_addition
|
|
642
|
+
path, params = generate(path_options, recall || {})
|
|
596
643
|
params.merge!(options[:params] || {})
|
|
597
644
|
|
|
598
645
|
ActionDispatch::Http::URL.url_for(options.merge!({
|
|
599
646
|
:path => path,
|
|
647
|
+
:script_name => script_name,
|
|
600
648
|
:params => params,
|
|
601
649
|
:user => user,
|
|
602
650
|
:password => password
|
|
@@ -604,7 +652,6 @@ module ActionDispatch
|
|
|
604
652
|
end
|
|
605
653
|
|
|
606
654
|
def call(env)
|
|
607
|
-
finalize!
|
|
608
655
|
@router.call(env)
|
|
609
656
|
end
|
|
610
657
|
|
|
@@ -614,28 +661,34 @@ module ActionDispatch
|
|
|
614
661
|
extras = environment[:extras] || {}
|
|
615
662
|
|
|
616
663
|
begin
|
|
617
|
-
env = Rack::MockRequest.env_for(path, {:method => method
|
|
664
|
+
env = Rack::MockRequest.env_for(path, {:method => method})
|
|
618
665
|
rescue URI::InvalidURIError => e
|
|
619
666
|
raise ActionController::RoutingError, e.message
|
|
620
667
|
end
|
|
621
668
|
|
|
622
669
|
req = @request_class.new(env)
|
|
623
|
-
@router.recognize(req) do |route,
|
|
670
|
+
@router.recognize(req) do |route, _matches, params|
|
|
671
|
+
params.merge!(extras)
|
|
624
672
|
params.each do |key, value|
|
|
625
673
|
if value.is_a?(String)
|
|
626
|
-
value = value.dup.force_encoding(Encoding::BINARY)
|
|
674
|
+
value = value.dup.force_encoding(Encoding::BINARY)
|
|
627
675
|
params[key] = URI.parser.unescape(value)
|
|
628
676
|
end
|
|
629
677
|
end
|
|
630
|
-
|
|
678
|
+
old_params = env[::ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
|
|
679
|
+
env[::ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] = (old_params || {}).merge(params)
|
|
631
680
|
dispatcher = route.app
|
|
632
681
|
while dispatcher.is_a?(Mapper::Constraints) && dispatcher.matches?(env) do
|
|
633
682
|
dispatcher = dispatcher.app
|
|
634
683
|
end
|
|
635
684
|
|
|
636
|
-
if dispatcher.is_a?(Dispatcher)
|
|
637
|
-
dispatcher.
|
|
638
|
-
|
|
685
|
+
if dispatcher.is_a?(Dispatcher)
|
|
686
|
+
if dispatcher.controller(params, false)
|
|
687
|
+
dispatcher.prepare_params!(params)
|
|
688
|
+
return params
|
|
689
|
+
else
|
|
690
|
+
raise ActionController::RoutingError, "A route matches #{path.inspect}, but references missing controller: #{params[:controller].camelize}Controller"
|
|
691
|
+
end
|
|
639
692
|
end
|
|
640
693
|
end
|
|
641
694
|
|
|
@@ -652,16 +705,6 @@ module ActionDispatch
|
|
|
652
705
|
end
|
|
653
706
|
end
|
|
654
707
|
|
|
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
708
|
end
|
|
666
709
|
end
|
|
667
710
|
end
|