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,104 +1,111 @@
1
- require 'action_controller/model_naming'
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
2
4
 
3
5
  module ActionDispatch
4
6
  module Routing
5
- # Polymorphic URL helpers are methods for smart resolution to a named route call when
6
- # given an Active Record model instance. They are to be used in combination with
7
- # ActionController::Resources.
7
+ # # Action Dispatch Routing PolymorphicRoutes
8
+ #
9
+ # Polymorphic URL helpers are methods for smart resolution to a named route call
10
+ # when given an Active Record model instance. They are to be used in combination
11
+ # with ActionController::Resources.
8
12
  #
9
- # These methods are useful when you want to generate correct URL or path to a RESTful
10
- # resource without having to know the exact type of the record in question.
13
+ # These methods are useful when you want to generate the correct URL or path to
14
+ # a RESTful resource without having to know the exact type of the record in
15
+ # question.
11
16
  #
12
- # Nested resources and/or namespaces are also supported, as illustrated in the example:
17
+ # Nested resources and/or namespaces are also supported, as illustrated in the
18
+ # example:
13
19
  #
14
- # polymorphic_url([:admin, @article, @comment])
20
+ # polymorphic_url([:admin, @article, @comment])
15
21
  #
16
22
  # results in:
17
23
  #
18
- # admin_article_comment_url(@article, @comment)
24
+ # admin_article_comment_url(@article, @comment)
25
+ #
26
+ # ## Usage within the framework
19
27
  #
20
- # == Usage within the framework
28
+ # Polymorphic URL helpers are used in a number of places throughout the Rails
29
+ # framework:
21
30
  #
22
- # Polymorphic URL helpers are used in a number of places throughout the \Rails framework:
31
+ # * `url_for`, so you can use it with a record as the argument, e.g.
32
+ # `url_for(@article)`;
33
+ # * ActionView::Helpers::FormHelper uses `polymorphic_path`, so you can write
34
+ # `form_for(@article)` without having to specify `:url` parameter for the
35
+ # form action;
36
+ # * `redirect_to` (which, in fact, uses `url_for`) so you can write
37
+ # `redirect_to(post)` in your controllers;
38
+ # * ActionView::Helpers::AtomFeedHelper, so you don't have to explicitly
39
+ # specify URLs for feed entries.
23
40
  #
24
- # * <tt>url_for</tt>, so you can use it with a record as the argument, e.g.
25
- # <tt>url_for(@article)</tt>;
26
- # * ActionView::Helpers::FormHelper uses <tt>polymorphic_path</tt>, so you can write
27
- # <tt>form_for(@article)</tt> without having to specify <tt>:url</tt> parameter for the form
28
- # action;
29
- # * <tt>redirect_to</tt> (which, in fact, uses <tt>url_for</tt>) so you can write
30
- # <tt>redirect_to(post)</tt> in your controllers;
31
- # * ActionView::Helpers::AtomFeedHelper, so you don't have to explicitly specify URLs
32
- # for feed entries.
33
41
  #
34
- # == Prefixed polymorphic helpers
42
+ # ## Prefixed polymorphic helpers
35
43
  #
36
- # In addition to <tt>polymorphic_url</tt> and <tt>polymorphic_path</tt> methods, a
37
- # number of prefixed helpers are available as a shorthand to <tt>action: "..."</tt>
38
- # in options. Those are:
44
+ # In addition to `polymorphic_url` and `polymorphic_path` methods, a number of
45
+ # prefixed helpers are available as a shorthand to `action: "..."` in options.
46
+ # Those are:
47
+ #
48
+ # * `edit_polymorphic_url`, `edit_polymorphic_path`
49
+ # * `new_polymorphic_url`, `new_polymorphic_path`
39
50
  #
40
- # * <tt>edit_polymorphic_url</tt>, <tt>edit_polymorphic_path</tt>
41
- # * <tt>new_polymorphic_url</tt>, <tt>new_polymorphic_path</tt>
42
51
  #
43
52
  # Example usage:
44
53
  #
45
- # edit_polymorphic_path(@post) # => "/posts/1/edit"
46
- # polymorphic_path(@post, format: :pdf) # => "/posts/1.pdf"
54
+ # edit_polymorphic_path(@post) # => "/posts/1/edit"
55
+ # polymorphic_path(@post, format: :pdf) # => "/posts/1.pdf"
47
56
  #
48
- # == Usage with mounted engines
57
+ # ## Usage with mounted engines
49
58
  #
50
59
  # If you are using a mounted engine and you need to use a polymorphic_url
51
60
  # pointing at the engine's routes, pass in the engine's route proxy as the first
52
61
  # argument to the method. For example:
53
62
  #
54
- # polymorphic_url([blog, @post]) # calls blog.post_path(@post)
55
- # form_for([blog, @post]) # => "/blog/posts/1"
63
+ # polymorphic_url([blog, @post]) # calls blog.post_path(@post)
64
+ # form_for([blog, @post]) # => "/blog/posts/1"
56
65
  #
57
66
  module PolymorphicRoutes
58
- include ActionController::ModelNaming
59
-
60
- # Constructs a call to a named RESTful route for the given record and returns the
61
- # resulting URL string. For example:
67
+ # Constructs a call to a named RESTful route for the given record and returns
68
+ # the resulting URL string. For example:
62
69
  #
63
- # # calls post_url(post)
64
- # polymorphic_url(post) # => "http://example.com/posts/1"
65
- # polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1"
66
- # polymorphic_url([:admin, blog, post]) # => "http://example.com/admin/blogs/1/posts/1"
67
- # polymorphic_url([user, :blog, post]) # => "http://example.com/users/1/blog/posts/1"
68
- # polymorphic_url(Comment) # => "http://example.com/comments"
70
+ # # calls post_url(post)
71
+ # polymorphic_url(post) # => "http://example.com/posts/1"
72
+ # polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1"
73
+ # polymorphic_url([:admin, blog, post]) # => "http://example.com/admin/blogs/1/posts/1"
74
+ # polymorphic_url([user, :blog, post]) # => "http://example.com/users/1/blog/posts/1"
75
+ # polymorphic_url(Comment) # => "http://example.com/comments"
69
76
  #
70
- # ==== Options
77
+ # #### Options
71
78
  #
72
- # * <tt>:action</tt> - Specifies the action prefix for the named route:
73
- # <tt>:new</tt> or <tt>:edit</tt>. Default is no prefix.
74
- # * <tt>:routing_type</tt> - Allowed values are <tt>:path</tt> or <tt>:url</tt>.
75
- # Default is <tt>:url</tt>.
79
+ # * `:action` - Specifies the action prefix for the named route: `:new` or
80
+ # `:edit`. Default is no prefix.
81
+ # * `:routing_type` - Allowed values are `:path` or `:url`. Default is `:url`.
76
82
  #
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
83
  #
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"
84
+ # Also includes all the options from `url_for`. These include such things as
85
+ # `:anchor` or `:trailing_slash`. Example usage is given below:
85
86
  #
86
- # For all of these options, see the documentation for <tt>url_for</tt>.
87
+ # polymorphic_url([blog, post], anchor: 'my_anchor')
88
+ # # => "http://example.com/blogs/1/posts/1#my_anchor"
89
+ # polymorphic_url([blog, post], anchor: 'my_anchor', script_name: "/my_app")
90
+ # # => "http://example.com/my_app/blogs/1/posts/1#my_anchor"
87
91
  #
88
- # ==== Functionality
92
+ # For all of these options, see the documentation for
93
+ # [url_for](rdoc-ref:ActionDispatch::Routing::UrlFor).
89
94
  #
90
- # # an Article record
91
- # polymorphic_url(record) # same as article_url(record)
95
+ # #### Functionality
92
96
  #
93
- # # a Comment record
94
- # polymorphic_url(record) # same as comment_url(record)
97
+ # # an Article record
98
+ # polymorphic_url(record) # same as article_url(record)
95
99
  #
96
- # # it recognizes new records and maps to the collection
97
- # record = Comment.new
98
- # polymorphic_url(record) # same as comments_url()
100
+ # # a Comment record
101
+ # polymorphic_url(record) # same as comment_url(record)
99
102
  #
100
- # # the class of a record will also map to the collection
101
- # polymorphic_url(Comment) # same as comments_url()
103
+ # # it recognizes new records and maps to the collection
104
+ # record = Comment.new
105
+ # polymorphic_url(record) # same as comments_url()
106
+ #
107
+ # # the class of a record will also map to the collection
108
+ # polymorphic_url(Comment) # same as comments_url()
102
109
  #
103
110
  def polymorphic_url(record_or_hash_or_array, options = {})
104
111
  if Hash === record_or_hash_or_array
@@ -107,6 +114,10 @@ module ActionDispatch
107
114
  return polymorphic_url record, options
108
115
  end
109
116
 
117
+ if mapping = polymorphic_mapping(record_or_hash_or_array)
118
+ return mapping.call(self, [record_or_hash_or_array, options], false)
119
+ end
120
+
110
121
  opts = options.dup
111
122
  action = opts.delete :action
112
123
  type = opts.delete(:routing_type) || :url
@@ -118,8 +129,7 @@ module ActionDispatch
118
129
  opts
119
130
  end
120
131
 
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>.
132
+ # Returns the path component of a URL for the given record.
123
133
  def polymorphic_path(record_or_hash_or_array, options = {})
124
134
  if Hash === record_or_hash_or_array
125
135
  options = record_or_hash_or_array.merge(options)
@@ -127,6 +137,10 @@ module ActionDispatch
127
137
  return polymorphic_path record, options
128
138
  end
129
139
 
140
+ if mapping = polymorphic_mapping(record_or_hash_or_array)
141
+ return mapping.call(self, [record_or_hash_or_array, options], true)
142
+ end
143
+
130
144
  opts = options.dup
131
145
  action = opts.delete :action
132
146
  type = :path
@@ -138,9 +152,9 @@ module ActionDispatch
138
152
  opts
139
153
  end
140
154
 
141
-
142
155
  %w(edit new).each do |action|
143
156
  module_eval <<-EOT, __FILE__, __LINE__ + 1
157
+ # frozen_string_literal: true
144
158
  def #{action}_polymorphic_url(record_or_hash, options = {})
145
159
  polymorphic_url_for_action("#{action}", record_or_hash, options)
146
160
  end
@@ -152,179 +166,198 @@ module ActionDispatch
152
166
  end
153
167
 
154
168
  private
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 }
169
+ def polymorphic_url_for_action(action, record_or_hash, options)
170
+ polymorphic_url(record_or_hash, options.merge(action: action))
170
171
  end
171
172
 
172
- def self.url; CACHE['url'.freeze][nil]; end
173
- def self.path; CACHE['path'.freeze][nil]; end
173
+ def polymorphic_path_for_action(action, record_or_hash, options)
174
+ polymorphic_path(record_or_hash, options.merge(action: action))
175
+ end
174
176
 
175
- def self.build(action, type)
176
- prefix = action ? "#{action}_" : ""
177
- suffix = type
178
- if action.to_s == 'new'
179
- HelperMethodBuilder.singular prefix, suffix
177
+ def polymorphic_mapping(record)
178
+ if record.respond_to?(:to_model)
179
+ _routes.polymorphic_mappings[record.to_model.model_name.name]
180
180
  else
181
- HelperMethodBuilder.plural prefix, suffix
181
+ _routes.polymorphic_mappings[record.class.name]
182
182
  end
183
183
  end
184
184
 
185
- def self.singular(prefix, suffix)
186
- new(->(name) { name.singular_route_key }, prefix, suffix)
187
- end
185
+ class HelperMethodBuilder # :nodoc:
186
+ CACHE = { path: {}, url: {} }
188
187
 
189
- def self.plural(prefix, suffix)
190
- new(->(name) { name.route_key }, prefix, suffix)
191
- end
188
+ def self.get(action, type)
189
+ type = type.to_sym
190
+ CACHE[type].fetch(action) { build action, type }
191
+ end
192
192
 
193
- def self.polymorphic_method(recipient, record_or_hash_or_array, action, type, options)
194
- builder = get action, type
193
+ def self.url; CACHE[:url][nil]; end
194
+ def self.path; CACHE[:path][nil]; end
195
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
196
+ def self.build(action, type)
197
+ prefix = action ? "#{action}_" : ""
198
+ suffix = type
199
+ if action.to_s == "new"
200
+ HelperMethodBuilder.singular prefix, suffix
201
+ else
202
+ HelperMethodBuilder.plural prefix, suffix
204
203
  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
204
  end
217
205
 
218
-
219
- if options.empty?
220
- recipient.send(method, *args)
221
- else
222
- recipient.send(method, *args, options)
206
+ def self.singular(prefix, suffix)
207
+ new(->(name) { name.singular_route_key }, prefix, suffix)
223
208
  end
224
- end
225
209
 
226
- attr_reader :suffix, :prefix
210
+ def self.plural(prefix, suffix)
211
+ new(->(name) { name.route_key }, prefix, suffix)
212
+ end
227
213
 
228
- def initialize(key_strategy, prefix, suffix)
229
- @key_strategy = key_strategy
230
- @prefix = prefix
231
- @suffix = suffix
232
- end
214
+ def self.polymorphic_method(recipient, record_or_hash_or_array, action, type, options)
215
+ builder = get action, type
216
+
217
+ case record_or_hash_or_array
218
+ when Array
219
+ record_or_hash_or_array = record_or_hash_or_array.compact
220
+ if record_or_hash_or_array.empty?
221
+ raise ArgumentError, "Nil location provided. Can't build URI."
222
+ end
223
+ if record_or_hash_or_array.first.is_a?(ActionDispatch::Routing::RoutesProxy)
224
+ recipient = record_or_hash_or_array.shift
225
+ end
226
+
227
+ method, args = builder.handle_list record_or_hash_or_array
228
+ when String, Symbol
229
+ method, args = builder.handle_string record_or_hash_or_array
230
+ when Class
231
+ method, args = builder.handle_class record_or_hash_or_array
233
232
 
234
- def handle_string(record)
235
- [get_method_for_string(record), []]
236
- end
233
+ when nil
234
+ raise ArgumentError, "Nil location provided. Can't build URI."
235
+ else
236
+ method, args = builder.handle_model record_or_hash_or_array
237
+ end
237
238
 
238
- def handle_string_call(target, str)
239
- target.send get_method_for_string str
240
- end
239
+ if options.empty?
240
+ recipient.public_send(method, *args)
241
+ else
242
+ recipient.public_send(method, *args, options)
243
+ end
244
+ end
241
245
 
242
- def handle_class(klass)
243
- [get_method_for_class(klass), []]
244
- end
246
+ attr_reader :suffix, :prefix
245
247
 
246
- def handle_class_call(target, klass)
247
- target.send get_method_for_class klass
248
- end
248
+ def initialize(key_strategy, prefix, suffix)
249
+ @key_strategy = key_strategy
250
+ @prefix = prefix
251
+ @suffix = suffix
252
+ end
249
253
 
250
- def handle_model(record)
251
- args = []
254
+ def handle_string(record)
255
+ [get_method_for_string(record), []]
256
+ end
252
257
 
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
258
+ def handle_string_call(target, str)
259
+ target.public_send get_method_for_string str
260
+ end
260
261
 
261
- named_route = prefix + "#{name}_#{suffix}"
262
+ def handle_class(klass)
263
+ [get_method_for_class(klass), []]
264
+ end
262
265
 
263
- [named_route, args]
264
- end
266
+ def handle_class_call(target, klass)
267
+ target.public_send get_method_for_class klass
268
+ end
265
269
 
266
- def handle_model_call(target, model)
267
- method, args = handle_model model
268
- target.send(method, *args)
269
- end
270
+ def handle_model(record)
271
+ args = []
270
272
 
271
- def handle_list(list)
272
- record_list = list.dup
273
- record = record_list.pop
273
+ model = record.to_model
274
+ named_route = if model.persisted?
275
+ args << model
276
+ get_method_for_string model.model_name.singular_route_key
277
+ else
278
+ get_method_for_class model
279
+ end
274
280
 
275
- args = []
281
+ [named_route, args]
282
+ end
276
283
 
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
284
+ def handle_model_call(target, record)
285
+ if mapping = polymorphic_mapping(target, record)
286
+ mapping.call(target, [record], suffix == "path")
284
287
  else
285
- args << parent.to_model
286
- parent.to_model.model_name.singular_route_key
288
+ method, args = handle_model(record)
289
+ target.public_send(method, *args)
287
290
  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
296
- else
297
- model = record.to_model
298
- if model.persisted?
299
- args << model
300
- model.model_name.singular_route_key
291
+ end
292
+
293
+ def handle_list(list)
294
+ record_list = list.dup
295
+ record = record_list.pop
296
+
297
+ args = []
298
+
299
+ route = record_list.map do |parent|
300
+ case parent
301
+ when Symbol
302
+ parent.to_s
303
+ when String
304
+ raise(ArgumentError, "Please use symbols for polymorphic route arguments.")
305
+ when Class
306
+ args << parent
307
+ parent.model_name.singular_route_key
308
+ else
309
+ args << parent.to_model
310
+ parent.to_model.model_name.singular_route_key
311
+ end
312
+ end
313
+
314
+ route <<
315
+ case record
316
+ when Symbol
317
+ record.to_s
318
+ when String
319
+ raise(ArgumentError, "Please use symbols for polymorphic route arguments.")
320
+ when Class
321
+ @key_strategy.call record.model_name
301
322
  else
302
- @key_strategy.call model.model_name
323
+ model = record.to_model
324
+ if model.persisted?
325
+ args << model
326
+ model.model_name.singular_route_key
327
+ else
328
+ @key_strategy.call model.model_name
329
+ end
303
330
  end
304
- end
305
331
 
306
- route << suffix
332
+ route << suffix
307
333
 
308
- named_route = prefix + route.join("_")
309
- [named_route, args]
310
- end
334
+ named_route = prefix + route.join("_")
335
+ [named_route, args]
336
+ end
311
337
 
312
- private
338
+ private
339
+ def polymorphic_mapping(target, record)
340
+ if record.respond_to?(:to_model)
341
+ target._routes.polymorphic_mappings[record.to_model.model_name.name]
342
+ else
343
+ target._routes.polymorphic_mappings[record.class.name]
344
+ end
345
+ end
313
346
 
314
- def get_method_for_class(klass)
315
- name = @key_strategy.call klass.model_name
316
- prefix + "#{name}_#{suffix}"
317
- end
347
+ def get_method_for_class(klass)
348
+ name = @key_strategy.call klass.model_name
349
+ get_method_for_string name
350
+ end
318
351
 
319
- def get_method_for_string(str)
320
- prefix + "#{str}_#{suffix}"
321
- end
352
+ def get_method_for_string(str)
353
+ "#{prefix}#{str}_#{suffix}"
354
+ end
322
355
 
323
- [nil, 'new', 'edit'].each do |action|
324
- CACHE['url'][action] = build action, 'url'
325
- CACHE['path'][action] = build action, 'path'
356
+ [nil, "new", "edit"].each do |action|
357
+ CACHE[:url][action] = build action, "url"
358
+ CACHE[:path][action] = build action, "path"
359
+ end
326
360
  end
327
- end
328
361
  end
329
362
  end
330
363
  end