actionpack 4.2.10 → 7.2.0.rc1

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.

Files changed (202) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +86 -600
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +13 -14
  5. data/lib/abstract_controller/asset_paths.rb +5 -1
  6. data/lib/abstract_controller/base.rb +166 -136
  7. data/lib/abstract_controller/caching/fragments.rb +149 -0
  8. data/lib/abstract_controller/caching.rb +68 -0
  9. data/lib/abstract_controller/callbacks.rb +126 -57
  10. data/lib/abstract_controller/collector.rb +13 -15
  11. data/lib/abstract_controller/deprecator.rb +9 -0
  12. data/lib/abstract_controller/error.rb +8 -0
  13. data/lib/abstract_controller/helpers.rb +181 -132
  14. data/lib/abstract_controller/logger.rb +5 -1
  15. data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
  16. data/lib/abstract_controller/rendering.rb +56 -56
  17. data/lib/abstract_controller/translation.rb +29 -15
  18. data/lib/abstract_controller/url_for.rb +15 -11
  19. data/lib/abstract_controller.rb +21 -5
  20. data/lib/action_controller/api/api_rendering.rb +18 -0
  21. data/lib/action_controller/api.rb +154 -0
  22. data/lib/action_controller/base.rb +219 -155
  23. data/lib/action_controller/caching.rb +28 -68
  24. data/lib/action_controller/deprecator.rb +9 -0
  25. data/lib/action_controller/form_builder.rb +55 -0
  26. data/lib/action_controller/log_subscriber.rb +35 -22
  27. data/lib/action_controller/metal/allow_browser.rb +119 -0
  28. data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
  29. data/lib/action_controller/metal/conditional_get.rb +259 -122
  30. data/lib/action_controller/metal/content_security_policy.rb +86 -0
  31. data/lib/action_controller/metal/cookies.rb +9 -5
  32. data/lib/action_controller/metal/data_streaming.rb +87 -104
  33. data/lib/action_controller/metal/default_headers.rb +21 -0
  34. data/lib/action_controller/metal/etag_with_flash.rb +22 -0
  35. data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
  36. data/lib/action_controller/metal/exceptions.rb +71 -24
  37. data/lib/action_controller/metal/flash.rb +26 -19
  38. data/lib/action_controller/metal/head.rb +45 -36
  39. data/lib/action_controller/metal/helpers.rb +80 -64
  40. data/lib/action_controller/metal/http_authentication.rb +297 -244
  41. data/lib/action_controller/metal/implicit_render.rb +57 -9
  42. data/lib/action_controller/metal/instrumentation.rb +76 -64
  43. data/lib/action_controller/metal/live.rb +238 -176
  44. data/lib/action_controller/metal/logging.rb +22 -0
  45. data/lib/action_controller/metal/mime_responds.rb +177 -166
  46. data/lib/action_controller/metal/parameter_encoding.rb +84 -0
  47. data/lib/action_controller/metal/params_wrapper.rb +145 -118
  48. data/lib/action_controller/metal/permissions_policy.rb +38 -0
  49. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  50. data/lib/action_controller/metal/redirecting.rb +203 -64
  51. data/lib/action_controller/metal/renderers.rb +108 -65
  52. data/lib/action_controller/metal/rendering.rb +216 -56
  53. data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
  54. data/lib/action_controller/metal/rescue.rb +19 -21
  55. data/lib/action_controller/metal/streaming.rb +179 -138
  56. data/lib/action_controller/metal/strong_parameters.rb +1058 -382
  57. data/lib/action_controller/metal/testing.rb +11 -17
  58. data/lib/action_controller/metal/url_for.rb +37 -21
  59. data/lib/action_controller/metal.rb +236 -138
  60. data/lib/action_controller/railtie.rb +89 -11
  61. data/lib/action_controller/railties/helpers.rb +5 -1
  62. data/lib/action_controller/renderer.rb +161 -0
  63. data/lib/action_controller/template_assertions.rb +13 -0
  64. data/lib/action_controller/test_case.rb +425 -497
  65. data/lib/action_controller.rb +44 -22
  66. data/lib/action_dispatch/constants.rb +34 -0
  67. data/lib/action_dispatch/deprecator.rb +9 -0
  68. data/lib/action_dispatch/http/cache.rb +119 -63
  69. data/lib/action_dispatch/http/content_disposition.rb +47 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +364 -0
  71. data/lib/action_dispatch/http/filter_parameters.rb +36 -34
  72. data/lib/action_dispatch/http/filter_redirect.rb +24 -12
  73. data/lib/action_dispatch/http/headers.rb +66 -31
  74. data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
  75. data/lib/action_dispatch/http/mime_type.rb +196 -136
  76. data/lib/action_dispatch/http/mime_types.rb +25 -7
  77. data/lib/action_dispatch/http/parameters.rb +97 -45
  78. data/lib/action_dispatch/http/permissions_policy.rb +187 -0
  79. data/lib/action_dispatch/http/rack_cache.rb +6 -0
  80. data/lib/action_dispatch/http/request.rb +299 -170
  81. data/lib/action_dispatch/http/response.rb +311 -160
  82. data/lib/action_dispatch/http/upload.rb +52 -23
  83. data/lib/action_dispatch/http/url.rb +201 -125
  84. data/lib/action_dispatch/journey/formatter.rb +110 -50
  85. data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
  86. data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
  87. data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
  88. data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
  89. data/lib/action_dispatch/journey/nodes/node.rb +100 -20
  90. data/lib/action_dispatch/journey/parser.rb +19 -17
  91. data/lib/action_dispatch/journey/parser.y +4 -3
  92. data/lib/action_dispatch/journey/parser_extras.rb +14 -4
  93. data/lib/action_dispatch/journey/path/pattern.rb +79 -63
  94. data/lib/action_dispatch/journey/route.rb +108 -44
  95. data/lib/action_dispatch/journey/router/utils.rb +41 -29
  96. data/lib/action_dispatch/journey/router.rb +64 -57
  97. data/lib/action_dispatch/journey/routes.rb +23 -21
  98. data/lib/action_dispatch/journey/scanner.rb +28 -17
  99. data/lib/action_dispatch/journey/visitors.rb +100 -54
  100. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  101. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  102. data/lib/action_dispatch/journey.rb +7 -5
  103. data/lib/action_dispatch/log_subscriber.rb +25 -0
  104. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  105. data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
  106. data/lib/action_dispatch/middleware/callbacks.rb +7 -6
  107. data/lib/action_dispatch/middleware/cookies.rb +471 -328
  108. data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
  109. data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
  110. data/lib/action_dispatch/middleware/debug_view.rb +73 -0
  111. data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
  112. data/lib/action_dispatch/middleware/executor.rb +32 -0
  113. data/lib/action_dispatch/middleware/flash.rb +143 -101
  114. data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
  115. data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
  116. data/lib/action_dispatch/middleware/reloader.rb +10 -92
  117. data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
  118. data/lib/action_dispatch/middleware/request_id.rb +29 -15
  119. data/lib/action_dispatch/middleware/server_timing.rb +78 -0
  120. data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
  121. data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
  122. data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
  123. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
  124. data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
  125. data/lib/action_dispatch/middleware/ssl.rb +134 -36
  126. data/lib/action_dispatch/middleware/stack.rb +109 -44
  127. data/lib/action_dispatch/middleware/static.rb +159 -90
  128. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
  132. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  133. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
  136. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
  137. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
  138. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
  139. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
  140. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  141. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
  142. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
  143. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
  144. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  145. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
  146. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
  147. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
  148. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  149. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
  150. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  151. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
  152. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
  153. data/lib/action_dispatch/railtie.rb +44 -16
  154. data/lib/action_dispatch/request/session.rb +159 -69
  155. data/lib/action_dispatch/request/utils.rb +97 -23
  156. data/lib/action_dispatch/routing/endpoint.rb +11 -2
  157. data/lib/action_dispatch/routing/inspector.rb +195 -106
  158. data/lib/action_dispatch/routing/mapper.rb +1338 -955
  159. data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
  160. data/lib/action_dispatch/routing/redirection.rb +78 -51
  161. data/lib/action_dispatch/routing/route_set.rb +460 -374
  162. data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
  163. data/lib/action_dispatch/routing/url_for.rb +172 -124
  164. data/lib/action_dispatch/routing.rb +159 -158
  165. data/lib/action_dispatch/system_test_case.rb +206 -0
  166. data/lib/action_dispatch/system_testing/browser.rb +84 -0
  167. data/lib/action_dispatch/system_testing/driver.rb +85 -0
  168. data/lib/action_dispatch/system_testing/server.rb +33 -0
  169. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
  170. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
  171. data/lib/action_dispatch/testing/assertion_response.rb +48 -0
  172. data/lib/action_dispatch/testing/assertions/response.rb +71 -39
  173. data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
  174. data/lib/action_dispatch/testing/assertions.rb +9 -6
  175. data/lib/action_dispatch/testing/integration.rb +486 -306
  176. data/lib/action_dispatch/testing/request_encoder.rb +60 -0
  177. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  178. data/lib/action_dispatch/testing/test_process.rb +35 -22
  179. data/lib/action_dispatch/testing/test_request.rb +29 -34
  180. data/lib/action_dispatch/testing/test_response.rb +48 -15
  181. data/lib/action_dispatch.rb +82 -40
  182. data/lib/action_pack/gem_version.rb +8 -4
  183. data/lib/action_pack/version.rb +6 -2
  184. data/lib/action_pack.rb +21 -18
  185. metadata +146 -56
  186. data/lib/action_controller/caching/fragments.rb +0 -103
  187. data/lib/action_controller/metal/force_ssl.rb +0 -97
  188. data/lib/action_controller/metal/hide_actions.rb +0 -40
  189. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  190. data/lib/action_controller/middleware.rb +0 -39
  191. data/lib/action_controller/model_naming.rb +0 -12
  192. data/lib/action_dispatch/http/parameter_filter.rb +0 -72
  193. data/lib/action_dispatch/journey/backwards.rb +0 -5
  194. data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
  195. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
  196. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
  197. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  198. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  199. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
  200. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  201. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  202. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,16 +1,21 @@
1
- require 'active_support/core_ext/array/extract_options'
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ require "active_support/core_ext/array/extract_options"
2
6
 
3
7
  module ActionDispatch
4
8
  module Routing
5
- class RoutesProxy #:nodoc:
9
+ class RoutesProxy # :nodoc:
6
10
  include ActionDispatch::Routing::UrlFor
7
11
 
8
12
  attr_accessor :scope, :routes
9
13
  alias :_routes :routes
10
14
 
11
- def initialize(routes, scope, helpers)
15
+ def initialize(routes, scope, helpers, script_namer = nil)
12
16
  @routes, @scope = routes, scope
13
17
  @helpers = helpers
18
+ @script_namer = script_namer
14
19
  end
15
20
 
16
21
  def url_options
@@ -19,24 +24,43 @@ module ActionDispatch
19
24
  end
20
25
  end
21
26
 
22
- def respond_to?(method, include_private = false)
27
+ private
28
+ def respond_to_missing?(method, _)
23
29
  super || @helpers.respond_to?(method)
24
30
  end
25
31
 
26
32
  def method_missing(method, *args)
27
33
  if @helpers.respond_to?(method)
28
- self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
29
- def #{method}(*args)
30
- options = args.extract_options!
31
- args << url_options.merge((options || {}).symbolize_keys)
32
- @helpers.#{method}(*args)
33
- end
34
- RUBY
35
- send(method, *args)
34
+ options = args.extract_options!
35
+ options = url_options.merge((options || {}).symbolize_keys)
36
+
37
+ if @script_namer
38
+ options[:script_name] = merge_script_names(
39
+ options[:script_name],
40
+ @script_namer.call(options)
41
+ )
42
+ end
43
+
44
+ args << options
45
+ @helpers.public_send(method, *args)
36
46
  else
37
47
  super
38
48
  end
39
49
  end
50
+
51
+ # Keeps the part of the script name provided by the global context via
52
+ # [ENV]("SCRIPT_NAME"), which `mount` doesn't know about since it depends on the
53
+ # specific request, but use our script name resolver for the mount point
54
+ # dependent part.
55
+ def merge_script_names(previous_script_name, new_script_name)
56
+ return new_script_name unless previous_script_name
57
+
58
+ resolved_parts = new_script_name.count("/")
59
+ previous_parts = previous_script_name.count("/")
60
+ context_parts = previous_parts - resolved_parts + 1
61
+
62
+ (previous_script_name.split("/").slice(0, context_parts).join("/")) + new_script_name
63
+ end
40
64
  end
41
65
  end
42
66
  end
@@ -1,84 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
1
5
  module ActionDispatch
2
6
  module Routing
3
- # In <tt>config/routes.rb</tt> you define URL-to-controller mappings, but the reverse
4
- # is also possible: an URL can be generated from one of your routing definitions.
5
- # URL generation functionality is centralized in this module.
6
- #
7
- # See ActionDispatch::Routing for general information about routing and routes.rb.
8
- #
9
- # <b>Tip:</b> If you need to generate URLs from your models or some other place,
10
- # then ActionController::UrlFor is what you're looking for. Read on for
11
- # an introduction. In general, this module should not be included on its own,
12
- # as it is usually included by url_helpers (as in Rails.application.routes.url_helpers).
13
- #
14
- # == URL generation from parameters
15
- #
16
- # As you may know, some functions, such as ActionController::Base#url_for
17
- # and ActionView::Helpers::UrlHelper#link_to, can generate URLs given a set
18
- # of parameters. For example, you've probably had the chance to write code
19
- # like this in one of your views:
20
- #
21
- # <%= link_to('Click here', controller: 'users',
22
- # action: 'new', message: 'Welcome!') %>
23
- # # => <a href="/users/new?message=Welcome%21">Click here</a>
24
- #
25
- # link_to, and all other functions that require URL generation functionality,
26
- # actually use ActionController::UrlFor under the hood. And in particular,
27
- # they use the ActionController::UrlFor#url_for method. One can generate
28
- # the same path as the above example by using the following code:
29
- #
30
- # include UrlFor
31
- # url_for(controller: 'users',
32
- # action: 'new',
33
- # message: 'Welcome!',
34
- # only_path: true)
35
- # # => "/users/new?message=Welcome%21"
36
- #
37
- # Notice the <tt>only_path: true</tt> part. This is because UrlFor has no
38
- # information about the website hostname that your Rails app is serving. So if you
39
- # want to include the hostname as well, then you must also pass the <tt>:host</tt>
40
- # argument:
41
- #
42
- # include UrlFor
43
- # url_for(controller: 'users',
44
- # action: 'new',
45
- # message: 'Welcome!',
46
- # host: 'www.example.com')
47
- # # => "http://www.example.com/users/new?message=Welcome%21"
48
- #
49
- # By default, all controllers and views have access to a special version of url_for,
50
- # that already knows what the current hostname is. So if you use url_for in your
51
- # controllers or your views, then you don't need to explicitly pass the <tt>:host</tt>
52
- # argument.
53
- #
54
- # For convenience reasons, mailers provide a shortcut for ActionController::UrlFor#url_for.
55
- # So within mailers, you only have to type 'url_for' instead of 'ActionController::UrlFor#url_for'
56
- # in full. However, mailers don't have hostname information, and that's why you'll still
57
- # have to specify the <tt>:host</tt> argument when generating URLs in mailers.
7
+ # # Action Dispatch Routing UrlFor
58
8
  #
9
+ # In `config/routes.rb` you define URL-to-controller mappings, but the reverse
10
+ # is also possible: a URL can be generated from one of your routing definitions.
11
+ # URL generation functionality is centralized in this module.
59
12
  #
60
- # == URL generation for named routes
13
+ # See ActionDispatch::Routing for general information about routing and
14
+ # `config/routes.rb`.
15
+ #
16
+ # **Tip:** If you need to generate URLs from your models or some other place,
17
+ # then ActionDispatch::Routing::UrlFor is what you're looking for. Read on for
18
+ # an introduction. In general, this module should not be included on its own, as
19
+ # it is usually included by `url_helpers` (as in
20
+ # `Rails.application.routes.url_helpers`).
21
+ #
22
+ # ## URL generation from parameters
23
+ #
24
+ # As you may know, some functions, such as `ActionController::Base#url_for` and
25
+ # ActionView::Helpers::UrlHelper#link_to, can generate URLs given a set of
26
+ # parameters. For example, you've probably had the chance to write code like
27
+ # this in one of your views:
28
+ #
29
+ # <%= link_to('Click here', controller: 'users',
30
+ # action: 'new', message: 'Welcome!') %>
31
+ # # => <a href="/users/new?message=Welcome%21">Click here</a>
32
+ #
33
+ # `link_to`, and all other functions that require URL generation functionality,
34
+ # actually use ActionDispatch::Routing::UrlFor under the hood. And in
35
+ # particular, they use the ActionDispatch::Routing::UrlFor#url_for method. One
36
+ # can generate the same path as the above example by using the following code:
37
+ #
38
+ # include ActionDispatch::Routing::UrlFor
39
+ # url_for(controller: 'users',
40
+ # action: 'new',
41
+ # message: 'Welcome!',
42
+ # only_path: true)
43
+ # # => "/users/new?message=Welcome%21"
44
+ #
45
+ # Notice the `only_path: true` part. This is because UrlFor has no information
46
+ # about the website hostname that your Rails app is serving. So if you want to
47
+ # include the hostname as well, then you must also pass the `:host` argument:
48
+ #
49
+ # include UrlFor
50
+ # url_for(controller: 'users',
51
+ # action: 'new',
52
+ # message: 'Welcome!',
53
+ # host: 'www.example.com')
54
+ # # => "http://www.example.com/users/new?message=Welcome%21"
55
+ #
56
+ # By default, all controllers and views have access to a special version of
57
+ # `url_for`, that already knows what the current hostname is. So if you use
58
+ # `url_for` in your controllers or your views, then you don't need to explicitly
59
+ # pass the `:host` argument.
60
+ #
61
+ # For convenience, mailers also include ActionDispatch::Routing::UrlFor. So
62
+ # within mailers, you can use url_for. However, mailers cannot access incoming
63
+ # web requests in order to derive hostname information, so you have to provide
64
+ # the `:host` option or set the default host using `default_url_options`. For
65
+ # more information on url_for in mailers see the ActionMailer::Base
66
+ # documentation.
67
+ #
68
+ # ## URL generation for named routes
61
69
  #
62
70
  # UrlFor also allows one to access methods that have been auto-generated from
63
71
  # named routes. For example, suppose that you have a 'users' resource in your
64
- # <tt>config/routes.rb</tt>:
72
+ # `config/routes.rb`:
65
73
  #
66
- # resources :users
74
+ # resources :users
67
75
  #
68
- # This generates, among other things, the method <tt>users_path</tt>. By default,
69
- # this method is accessible from your controllers, views and mailers. If you need
70
- # to access this auto-generated method from other places (such as a model), then
71
- # you can do that by including Rails.application.routes.url_helpers in your class:
76
+ # This generates, among other things, the method `users_path`. By default, this
77
+ # method is accessible from your controllers, views, and mailers. If you need to
78
+ # access this auto-generated method from other places (such as a model), then
79
+ # you can do that by including `Rails.application.routes.url_helpers` in your
80
+ # class:
72
81
  #
73
- # class User < ActiveRecord::Base
74
- # include Rails.application.routes.url_helpers
82
+ # class User < ActiveRecord::Base
83
+ # include Rails.application.routes.url_helpers
75
84
  #
76
- # def base_uri
77
- # user_path(self)
85
+ # def base_uri
86
+ # user_path(self)
87
+ # end
78
88
  # end
79
- # end
80
89
  #
81
- # User.find(1).base_uri # => "/users/1"
90
+ # User.find(1).base_uri # => "/users/1"
82
91
  #
83
92
  module UrlFor
84
93
  extend ActiveSupport::Concern
@@ -99,62 +108,85 @@ module ActionDispatch
99
108
  include(*_url_for_modules) if respond_to?(:_url_for_modules)
100
109
  end
101
110
 
102
- def initialize(*)
111
+ def initialize(...)
103
112
  @_routes = nil
104
113
  super
105
114
  end
106
115
 
107
- # Hook overridden in controller to add request information
108
- # with `default_url_options`. Application logic should not
109
- # go into url_options.
116
+ # Hook overridden in controller to add request information with
117
+ # `default_url_options`. Application logic should not go into url_options.
110
118
  def url_options
111
119
  default_url_options
112
120
  end
113
121
 
114
- # Generate a url based on the options provided, default_url_options and the
115
- # routes defined in routes.rb. The following options are supported:
122
+ # Generate a URL based on the options provided, `default_url_options`, and the
123
+ # routes defined in `config/routes.rb`. The following options are supported:
124
+ #
125
+ # * `:only_path` - If true, the relative URL is returned. Defaults to `false`.
126
+ # * `:protocol` - The protocol to connect to. Defaults to `"http"`.
127
+ # * `:host` - Specifies the host the link should be targeted at. If
128
+ # `:only_path` is false, this option must be provided either explicitly, or
129
+ # via `default_url_options`.
130
+ # * `:subdomain` - Specifies the subdomain of the link, using the `tld_length`
131
+ # to split the subdomain from the host. If false, removes all subdomains
132
+ # from the host part of the link.
133
+ # * `:domain` - Specifies the domain of the link, using the `tld_length` to
134
+ # split the domain from the host.
135
+ # * `:tld_length` - Number of labels the TLD id composed of, only used if
136
+ # `:subdomain` or `:domain` are supplied. Defaults to
137
+ # `ActionDispatch::Http::URL.tld_length`, which in turn defaults to 1.
138
+ # * `:port` - Optionally specify the port to connect to.
139
+ # * `:anchor` - An anchor name to be appended to the path.
140
+ # * `:params` - The query parameters to be appended to the path.
141
+ # * `:path_params` - The query parameters that will only be used for the named
142
+ # dynamic segments of path. If unused, they will be discarded.
143
+ # * `:trailing_slash` - If true, adds a trailing slash, as in
144
+ # `"/archive/2009/"`.
145
+ # * `:script_name` - Specifies application path relative to domain root. If
146
+ # provided, prepends application path.
147
+ #
148
+ #
149
+ # Any other key (`:controller`, `:action`, etc.) given to `url_for` is forwarded
150
+ # to the Routes module.
116
151
  #
117
- # * <tt>:only_path</tt> - If true, the relative url is returned. Defaults to +false+.
118
- # * <tt>:protocol</tt> - The protocol to connect to. Defaults to 'http'.
119
- # * <tt>:host</tt> - Specifies the host the link should be targeted at.
120
- # If <tt>:only_path</tt> is false, this option must be
121
- # provided either explicitly, or via +default_url_options+.
122
- # * <tt>:subdomain</tt> - Specifies the subdomain of the link, using the +tld_length+
123
- # to split the subdomain from the host.
124
- # If false, removes all subdomains from the host part of the link.
125
- # * <tt>:domain</tt> - Specifies the domain of the link, using the +tld_length+
126
- # to split the domain from the host.
127
- # * <tt>:tld_length</tt> - Number of labels the TLD id composed of, only used if
128
- # <tt>:subdomain</tt> or <tt>:domain</tt> are supplied. Defaults to
129
- # <tt>ActionDispatch::Http::URL.tld_length</tt>, which in turn defaults to 1.
130
- # * <tt>:port</tt> - Optionally specify the port to connect to.
131
- # * <tt>:anchor</tt> - An anchor name to be appended to the path.
132
- # * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in "/archive/2009/"
133
- # * <tt>:script_name</tt> - Specifies application path relative to domain root. If provided, prepends application path.
152
+ # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', port: '8080'
153
+ # # => 'http://somehost.org:8080/tasks/testing'
154
+ # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', anchor: 'ok', only_path: true
155
+ # # => '/tasks/testing#ok'
156
+ # url_for controller: 'tasks', action: 'testing', trailing_slash: true
157
+ # # => 'http://somehost.org/tasks/testing/'
158
+ # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', number: '33'
159
+ # # => 'http://somehost.org/tasks/testing?number=33'
160
+ # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', script_name: "/myapp"
161
+ # # => 'http://somehost.org/myapp/tasks/testing'
162
+ # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', script_name: "/myapp", only_path: true
163
+ # # => '/myapp/tasks/testing'
134
164
  #
135
- # Any other key (<tt>:controller</tt>, <tt>:action</tt>, etc.) given to
136
- # +url_for+ is forwarded to the Routes module.
165
+ # Missing routes keys may be filled in from the current request's parameters
166
+ # (e.g. `:controller`, `:action`, `:id`, and any other parameters that are
167
+ # placed in the path). Given that the current action has been reached through
168
+ # `GET /users/1`:
137
169
  #
138
- # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', port: '8080'
139
- # # => 'http://somehost.org:8080/tasks/testing'
140
- # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', anchor: 'ok', only_path: true
141
- # # => '/tasks/testing#ok'
142
- # url_for controller: 'tasks', action: 'testing', trailing_slash: true
143
- # # => 'http://somehost.org/tasks/testing/'
144
- # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', number: '33'
145
- # # => 'http://somehost.org/tasks/testing?number=33'
146
- # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', script_name: "/myapp"
147
- # # => 'http://somehost.org/myapp/tasks/testing'
148
- # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', script_name: "/myapp", only_path: true
149
- # # => '/myapp/tasks/testing'
170
+ # url_for(only_path: true) # => '/users/1'
171
+ # url_for(only_path: true, action: 'edit') # => '/users/1/edit'
172
+ # url_for(only_path: true, action: 'edit', id: 2) # => '/users/2/edit'
173
+ #
174
+ # Notice that no `:id` parameter was provided to the first `url_for` call and
175
+ # the helper used the one from the route's path. Any path parameter implicitly
176
+ # used by `url_for` can always be overwritten like shown on the last `url_for`
177
+ # calls.
150
178
  def url_for(options = nil)
179
+ full_url_for(options)
180
+ end
181
+
182
+ def full_url_for(options = nil) # :nodoc:
151
183
  case options
152
184
  when nil
153
185
  _routes.url_for(url_options.symbolize_keys)
154
- when Hash
186
+ when Hash, ActionController::Parameters
155
187
  route_name = options.delete :use_route
156
- _routes.url_for(options.symbolize_keys.reverse_merge!(url_options),
157
- route_name)
188
+ merged_url_options = options.to_h.symbolize_keys.reverse_merge!(url_options)
189
+ _routes.url_for(merged_url_options, route_name)
158
190
  when String
159
191
  options
160
192
  when Symbol
@@ -169,27 +201,43 @@ module ActionDispatch
169
201
  end
170
202
  end
171
203
 
172
- protected
173
-
174
- def optimize_routes_generation?
175
- _routes.optimize_routes_generation? && default_url_options.empty?
176
- end
177
-
178
- def _with_routes(routes)
179
- old_routes, @_routes = @_routes, routes
180
- yield
181
- ensure
182
- @_routes = old_routes
204
+ # Allows calling direct or regular named route.
205
+ #
206
+ # resources :buckets
207
+ #
208
+ # direct :recordable do |recording|
209
+ # route_for(:bucket, recording.bucket)
210
+ # end
211
+ #
212
+ # direct :threadable do |threadable|
213
+ # route_for(:recordable, threadable.parent)
214
+ # end
215
+ #
216
+ # This maintains the context of the original caller on whether to return a path
217
+ # or full URL, e.g:
218
+ #
219
+ # threadable_path(threadable) # => "/buckets/1"
220
+ # threadable_url(threadable) # => "http://example.com/buckets/1"
221
+ #
222
+ def route_for(name, *args)
223
+ public_send(:"#{name}_url", *args)
183
224
  end
184
225
 
185
- def _routes_context
186
- self
187
- end
226
+ protected
227
+ def optimize_routes_generation?
228
+ _routes.optimize_routes_generation? && default_url_options.empty?
229
+ end
188
230
 
189
231
  private
232
+ def _with_routes(routes) # :doc:
233
+ old_routes, @_routes = @_routes, routes
234
+ yield
235
+ ensure
236
+ @_routes = old_routes
237
+ end
190
238
 
191
- def _generate_paths_by_default
192
- true
239
+ def _routes_context # :doc:
240
+ self
193
241
  end
194
242
  end
195
243
  end