actionpack 3.2.22.5 → 5.2.4

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.
Files changed (271) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +279 -603
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +13 -297
  5. data/lib/abstract_controller/asset_paths.rb +4 -2
  6. data/lib/abstract_controller/base.rb +82 -52
  7. data/lib/abstract_controller/caching/fragments.rb +166 -0
  8. data/lib/abstract_controller/caching.rb +66 -0
  9. data/lib/abstract_controller/callbacks.rb +117 -103
  10. data/lib/abstract_controller/collector.rb +18 -7
  11. data/lib/abstract_controller/error.rb +6 -0
  12. data/lib/abstract_controller/helpers.rb +65 -38
  13. data/lib/abstract_controller/logger.rb +3 -2
  14. data/lib/abstract_controller/railties/routes_helpers.rb +5 -3
  15. data/lib/abstract_controller/rendering.rb +77 -129
  16. data/lib/abstract_controller/translation.rb +21 -3
  17. data/lib/abstract_controller/url_for.rb +9 -7
  18. data/lib/abstract_controller.rb +12 -13
  19. data/lib/action_controller/api/api_rendering.rb +16 -0
  20. data/lib/action_controller/api.rb +149 -0
  21. data/lib/action_controller/base.rb +81 -40
  22. data/lib/action_controller/caching.rb +22 -62
  23. data/lib/action_controller/form_builder.rb +50 -0
  24. data/lib/action_controller/log_subscriber.rb +30 -18
  25. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  26. data/lib/action_controller/metal/conditional_get.rb +190 -47
  27. data/lib/action_controller/metal/content_security_policy.rb +52 -0
  28. data/lib/action_controller/metal/cookies.rb +3 -3
  29. data/lib/action_controller/metal/data_streaming.rb +40 -65
  30. data/lib/action_controller/metal/etag_with_flash.rb +18 -0
  31. data/lib/action_controller/metal/etag_with_template_digest.rb +57 -0
  32. data/lib/action_controller/metal/exceptions.rb +19 -12
  33. data/lib/action_controller/metal/flash.rb +42 -9
  34. data/lib/action_controller/metal/force_ssl.rb +79 -19
  35. data/lib/action_controller/metal/head.rb +35 -10
  36. data/lib/action_controller/metal/helpers.rb +31 -21
  37. data/lib/action_controller/metal/http_authentication.rb +182 -134
  38. data/lib/action_controller/metal/implicit_render.rb +62 -8
  39. data/lib/action_controller/metal/instrumentation.rb +28 -26
  40. data/lib/action_controller/metal/live.rb +312 -0
  41. data/lib/action_controller/metal/mime_responds.rb +159 -163
  42. data/lib/action_controller/metal/parameter_encoding.rb +51 -0
  43. data/lib/action_controller/metal/params_wrapper.rb +146 -93
  44. data/lib/action_controller/metal/redirecting.rb +80 -56
  45. data/lib/action_controller/metal/renderers.rb +119 -47
  46. data/lib/action_controller/metal/rendering.rb +89 -32
  47. data/lib/action_controller/metal/request_forgery_protection.rb +373 -41
  48. data/lib/action_controller/metal/rescue.rb +9 -16
  49. data/lib/action_controller/metal/streaming.rb +39 -45
  50. data/lib/action_controller/metal/strong_parameters.rb +1086 -0
  51. data/lib/action_controller/metal/testing.rb +8 -29
  52. data/lib/action_controller/metal/url_for.rb +43 -32
  53. data/lib/action_controller/metal.rb +112 -106
  54. data/lib/action_controller/railtie.rb +56 -18
  55. data/lib/action_controller/railties/helpers.rb +24 -0
  56. data/lib/action_controller/renderer.rb +117 -0
  57. data/lib/action_controller/template_assertions.rb +11 -0
  58. data/lib/action_controller/test_case.rb +402 -347
  59. data/lib/action_controller.rb +31 -30
  60. data/lib/action_dispatch/http/cache.rb +133 -34
  61. data/lib/action_dispatch/http/content_security_policy.rb +272 -0
  62. data/lib/action_dispatch/http/filter_parameters.rb +40 -24
  63. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  64. data/lib/action_dispatch/http/headers.rb +117 -16
  65. data/lib/action_dispatch/http/mime_negotiation.rb +98 -33
  66. data/lib/action_dispatch/http/mime_type.rb +198 -146
  67. data/lib/action_dispatch/http/mime_types.rb +22 -7
  68. data/lib/action_dispatch/http/parameter_filter.rb +61 -49
  69. data/lib/action_dispatch/http/parameters.rb +94 -51
  70. data/lib/action_dispatch/http/rack_cache.rb +4 -3
  71. data/lib/action_dispatch/http/request.rb +262 -117
  72. data/lib/action_dispatch/http/response.rb +400 -86
  73. data/lib/action_dispatch/http/upload.rb +66 -29
  74. data/lib/action_dispatch/http/url.rb +232 -60
  75. data/lib/action_dispatch/journey/formatter.rb +189 -0
  76. data/lib/action_dispatch/journey/gtg/builder.rb +164 -0
  77. data/lib/action_dispatch/journey/gtg/simulator.rb +41 -0
  78. data/lib/action_dispatch/journey/gtg/transition_table.rb +158 -0
  79. data/lib/action_dispatch/journey/nfa/builder.rb +78 -0
  80. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  81. data/lib/action_dispatch/journey/nfa/simulator.rb +49 -0
  82. data/lib/action_dispatch/journey/nfa/transition_table.rb +120 -0
  83. data/lib/action_dispatch/journey/nodes/node.rb +140 -0
  84. data/lib/action_dispatch/journey/parser.rb +199 -0
  85. data/lib/action_dispatch/journey/parser.y +50 -0
  86. data/lib/action_dispatch/journey/parser_extras.rb +31 -0
  87. data/lib/action_dispatch/journey/path/pattern.rb +199 -0
  88. data/lib/action_dispatch/journey/route.rb +203 -0
  89. data/lib/action_dispatch/journey/router/utils.rb +102 -0
  90. data/lib/action_dispatch/journey/router.rb +156 -0
  91. data/lib/action_dispatch/journey/routes.rb +82 -0
  92. data/lib/action_dispatch/journey/scanner.rb +64 -0
  93. data/lib/action_dispatch/journey/visitors.rb +268 -0
  94. data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
  95. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  96. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  97. data/lib/action_dispatch/journey.rb +7 -0
  98. data/lib/action_dispatch/middleware/callbacks.rb +17 -13
  99. data/lib/action_dispatch/middleware/cookies.rb +494 -162
  100. data/lib/action_dispatch/middleware/debug_exceptions.rb +176 -53
  101. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  102. data/lib/action_dispatch/middleware/exception_wrapper.rb +103 -38
  103. data/lib/action_dispatch/middleware/executor.rb +21 -0
  104. data/lib/action_dispatch/middleware/flash.rb +128 -91
  105. data/lib/action_dispatch/middleware/public_exceptions.rb +43 -16
  106. data/lib/action_dispatch/middleware/reloader.rb +6 -83
  107. data/lib/action_dispatch/middleware/remote_ip.rb +151 -49
  108. data/lib/action_dispatch/middleware/request_id.rb +19 -15
  109. data/lib/action_dispatch/middleware/session/abstract_store.rb +38 -34
  110. data/lib/action_dispatch/middleware/session/cache_store.rb +14 -9
  111. data/lib/action_dispatch/middleware/session/cookie_store.rb +94 -44
  112. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -4
  113. data/lib/action_dispatch/middleware/show_exceptions.rb +36 -61
  114. data/lib/action_dispatch/middleware/ssl.rb +150 -0
  115. data/lib/action_dispatch/middleware/stack.rb +33 -41
  116. data/lib/action_dispatch/middleware/static.rb +92 -48
  117. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +22 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
  119. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +27 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  121. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
  122. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
  123. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +16 -0
  124. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
  125. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
  126. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
  127. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +134 -5
  128. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
  132. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
  136. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  137. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +200 -0
  138. data/lib/action_dispatch/railtie.rb +29 -8
  139. data/lib/action_dispatch/request/session.rb +234 -0
  140. data/lib/action_dispatch/request/utils.rb +78 -0
  141. data/lib/action_dispatch/routing/endpoint.rb +17 -0
  142. data/lib/action_dispatch/routing/inspector.rb +225 -0
  143. data/lib/action_dispatch/routing/mapper.rb +1329 -582
  144. data/lib/action_dispatch/routing/polymorphic_routes.rb +237 -94
  145. data/lib/action_dispatch/routing/redirection.rb +120 -50
  146. data/lib/action_dispatch/routing/route_set.rb +545 -322
  147. data/lib/action_dispatch/routing/routes_proxy.rb +37 -7
  148. data/lib/action_dispatch/routing/url_for.rb +103 -34
  149. data/lib/action_dispatch/routing.rb +66 -99
  150. data/lib/action_dispatch/system_test_case.rb +147 -0
  151. data/lib/action_dispatch/system_testing/browser.rb +49 -0
  152. data/lib/action_dispatch/system_testing/driver.rb +59 -0
  153. data/lib/action_dispatch/system_testing/server.rb +31 -0
  154. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
  155. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
  156. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
  157. data/lib/action_dispatch/testing/assertion_response.rb +47 -0
  158. data/lib/action_dispatch/testing/assertions/response.rb +53 -42
  159. data/lib/action_dispatch/testing/assertions/routing.rb +79 -74
  160. data/lib/action_dispatch/testing/assertions.rb +15 -9
  161. data/lib/action_dispatch/testing/integration.rb +361 -207
  162. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  163. data/lib/action_dispatch/testing/test_process.rb +28 -19
  164. data/lib/action_dispatch/testing/test_request.rb +30 -33
  165. data/lib/action_dispatch/testing/test_response.rb +35 -11
  166. data/lib/action_dispatch.rb +42 -32
  167. data/lib/action_pack/gem_version.rb +17 -0
  168. data/lib/action_pack/version.rb +7 -7
  169. data/lib/action_pack.rb +4 -2
  170. metadata +116 -175
  171. data/lib/abstract_controller/layouts.rb +0 -423
  172. data/lib/abstract_controller/view_paths.rb +0 -96
  173. data/lib/action_controller/caching/actions.rb +0 -185
  174. data/lib/action_controller/caching/fragments.rb +0 -127
  175. data/lib/action_controller/caching/pages.rb +0 -187
  176. data/lib/action_controller/caching/sweeping.rb +0 -97
  177. data/lib/action_controller/deprecated/integration_test.rb +0 -2
  178. data/lib/action_controller/deprecated/performance_test.rb +0 -1
  179. data/lib/action_controller/deprecated.rb +0 -3
  180. data/lib/action_controller/metal/compatibility.rb +0 -65
  181. data/lib/action_controller/metal/hide_actions.rb +0 -41
  182. data/lib/action_controller/metal/rack_delegation.rb +0 -26
  183. data/lib/action_controller/metal/responder.rb +0 -286
  184. data/lib/action_controller/metal/session_management.rb +0 -14
  185. data/lib/action_controller/middleware.rb +0 -39
  186. data/lib/action_controller/railties/paths.rb +0 -25
  187. data/lib/action_controller/record_identifier.rb +0 -85
  188. data/lib/action_controller/vendor/html-scanner/html/document.rb +0 -68
  189. data/lib/action_controller/vendor/html-scanner/html/node.rb +0 -532
  190. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +0 -177
  191. data/lib/action_controller/vendor/html-scanner/html/selector.rb +0 -830
  192. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +0 -107
  193. data/lib/action_controller/vendor/html-scanner/html/version.rb +0 -11
  194. data/lib/action_controller/vendor/html-scanner.rb +0 -20
  195. data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
  196. data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
  197. data/lib/action_dispatch/middleware/head.rb +0 -18
  198. data/lib/action_dispatch/middleware/params_parser.rb +0 -75
  199. data/lib/action_dispatch/middleware/rescue.rb +0 -26
  200. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +0 -31
  201. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -26
  202. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +0 -10
  203. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -2
  204. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +0 -15
  205. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -17
  206. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +0 -2
  207. data/lib/action_dispatch/testing/assertions/dom.rb +0 -37
  208. data/lib/action_dispatch/testing/assertions/selector.rb +0 -435
  209. data/lib/action_dispatch/testing/assertions/tag.rb +0 -138
  210. data/lib/action_dispatch/testing/performance_test.rb +0 -10
  211. data/lib/action_view/asset_paths.rb +0 -142
  212. data/lib/action_view/base.rb +0 -220
  213. data/lib/action_view/buffers.rb +0 -43
  214. data/lib/action_view/context.rb +0 -36
  215. data/lib/action_view/flows.rb +0 -79
  216. data/lib/action_view/helpers/active_model_helper.rb +0 -50
  217. data/lib/action_view/helpers/asset_paths.rb +0 -7
  218. data/lib/action_view/helpers/asset_tag_helper.rb +0 -457
  219. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
  220. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
  221. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
  222. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
  223. data/lib/action_view/helpers/atom_feed_helper.rb +0 -200
  224. data/lib/action_view/helpers/cache_helper.rb +0 -64
  225. data/lib/action_view/helpers/capture_helper.rb +0 -203
  226. data/lib/action_view/helpers/controller_helper.rb +0 -25
  227. data/lib/action_view/helpers/csrf_helper.rb +0 -32
  228. data/lib/action_view/helpers/date_helper.rb +0 -1062
  229. data/lib/action_view/helpers/debug_helper.rb +0 -40
  230. data/lib/action_view/helpers/form_helper.rb +0 -1486
  231. data/lib/action_view/helpers/form_options_helper.rb +0 -658
  232. data/lib/action_view/helpers/form_tag_helper.rb +0 -685
  233. data/lib/action_view/helpers/javascript_helper.rb +0 -110
  234. data/lib/action_view/helpers/number_helper.rb +0 -622
  235. data/lib/action_view/helpers/output_safety_helper.rb +0 -38
  236. data/lib/action_view/helpers/record_tag_helper.rb +0 -111
  237. data/lib/action_view/helpers/rendering_helper.rb +0 -92
  238. data/lib/action_view/helpers/sanitize_helper.rb +0 -259
  239. data/lib/action_view/helpers/tag_helper.rb +0 -167
  240. data/lib/action_view/helpers/text_helper.rb +0 -426
  241. data/lib/action_view/helpers/translation_helper.rb +0 -91
  242. data/lib/action_view/helpers/url_helper.rb +0 -693
  243. data/lib/action_view/helpers.rb +0 -60
  244. data/lib/action_view/locale/en.yml +0 -160
  245. data/lib/action_view/log_subscriber.rb +0 -28
  246. data/lib/action_view/lookup_context.rb +0 -258
  247. data/lib/action_view/path_set.rb +0 -101
  248. data/lib/action_view/railtie.rb +0 -55
  249. data/lib/action_view/renderer/abstract_renderer.rb +0 -41
  250. data/lib/action_view/renderer/partial_renderer.rb +0 -415
  251. data/lib/action_view/renderer/renderer.rb +0 -61
  252. data/lib/action_view/renderer/streaming_template_renderer.rb +0 -106
  253. data/lib/action_view/renderer/template_renderer.rb +0 -95
  254. data/lib/action_view/template/error.rb +0 -128
  255. data/lib/action_view/template/handlers/builder.rb +0 -26
  256. data/lib/action_view/template/handlers/erb.rb +0 -125
  257. data/lib/action_view/template/handlers.rb +0 -50
  258. data/lib/action_view/template/resolver.rb +0 -298
  259. data/lib/action_view/template/text.rb +0 -30
  260. data/lib/action_view/template.rb +0 -337
  261. data/lib/action_view/test_case.rb +0 -246
  262. data/lib/action_view/testing/resolvers.rb +0 -49
  263. data/lib/action_view.rb +0 -84
  264. data/lib/sprockets/assets.rake +0 -99
  265. data/lib/sprockets/bootstrap.rb +0 -37
  266. data/lib/sprockets/compressors.rb +0 -83
  267. data/lib/sprockets/helpers/isolated_helper.rb +0 -13
  268. data/lib/sprockets/helpers/rails_helper.rb +0 -182
  269. data/lib/sprockets/helpers.rb +0 -6
  270. data/lib/sprockets/railtie.rb +0 -62
  271. data/lib/sprockets/static_compiler.rb +0 -56
@@ -1,67 +1,9 @@
1
- require 'abstract_controller/collector'
2
- require 'active_support/core_ext/class/attribute'
3
- require 'active_support/core_ext/object/inclusion'
1
+ # frozen_string_literal: true
2
+
3
+ require "abstract_controller/collector"
4
4
 
5
5
  module ActionController #:nodoc:
6
6
  module MimeResponds
7
- extend ActiveSupport::Concern
8
-
9
- include ActionController::ImplicitRender
10
-
11
- included do
12
- class_attribute :responder, :mimes_for_respond_to
13
- self.responder = ActionController::Responder
14
- clear_respond_to
15
- end
16
-
17
- module ClassMethods
18
- # Defines mime types that are rendered by default when invoking
19
- # <tt>respond_with</tt>.
20
- #
21
- # Examples:
22
- #
23
- # respond_to :html, :xml, :json
24
- #
25
- # Specifies that all actions in the controller respond to requests
26
- # for <tt>:html</tt>, <tt>:xml</tt> and <tt>:json</tt>.
27
- #
28
- # To specify on per-action basis, use <tt>:only</tt> and
29
- # <tt>:except</tt> with an array of actions or a single action:
30
- #
31
- # respond_to :html
32
- # respond_to :xml, :json, :except => [ :edit ]
33
- #
34
- # This specifies that all actions respond to <tt>:html</tt>
35
- # and all actions except <tt>:edit</tt> respond to <tt>:xml</tt> and
36
- # <tt>:json</tt>.
37
- #
38
- # respond_to :json, :only => :create
39
- #
40
- # This specifies that the <tt>:create</tt> action and no other responds
41
- # to <tt>:json</tt>.
42
- def respond_to(*mimes)
43
- options = mimes.extract_options!
44
-
45
- only_actions = Array(options.delete(:only)).map(&:to_s)
46
- except_actions = Array(options.delete(:except)).map(&:to_s)
47
-
48
- new = mimes_for_respond_to.dup
49
- mimes.each do |mime|
50
- mime = mime.to_sym
51
- new[mime] = {}
52
- new[mime][:only] = only_actions unless only_actions.empty?
53
- new[mime][:except] = except_actions unless except_actions.empty?
54
- end
55
- self.mimes_for_respond_to = new.freeze
56
- end
57
-
58
- # Clear all mime types in <tt>respond_to</tt>.
59
- #
60
- def clear_respond_to
61
- self.mimes_for_respond_to = ActiveSupport::OrderedHash.new.freeze
62
- end
63
- end
64
-
65
7
  # Without web-service support, an action which collects the data for displaying a list of people
66
8
  # might look something like this:
67
9
  #
@@ -69,6 +11,13 @@ module ActionController #:nodoc:
69
11
  # @people = Person.all
70
12
  # end
71
13
  #
14
+ # That action implicitly responds to all formats, but formats can also be whitelisted:
15
+ #
16
+ # def index
17
+ # @people = Person.all
18
+ # respond_to :html, :js
19
+ # end
20
+ #
72
21
  # Here's the same action, with web-service support baked in:
73
22
  #
74
23
  # def index
@@ -76,11 +25,12 @@ module ActionController #:nodoc:
76
25
  #
77
26
  # respond_to do |format|
78
27
  # format.html
79
- # format.xml { render :xml => @people.to_xml }
28
+ # format.js
29
+ # format.xml { render xml: @people }
80
30
  # end
81
31
  # end
82
32
  #
83
- # What that says is, "if the client wants HTML in response to this action, just respond as we
33
+ # What that says is, "if the client wants HTML or JS in response to this action, just respond as we
84
34
  # would have before, but if the client wants XML, return them the list of people in XML format."
85
35
  # (Rails determines the desired response format from the HTTP Accept header submitted by the client.)
86
36
  #
@@ -88,7 +38,7 @@ module ActionController #:nodoc:
88
38
  # (by name) if it does not already exist, without web-services, it might look like this:
89
39
  #
90
40
  # def create
91
- # @company = Company.find_or_create_by_name(params[:company][:name])
41
+ # @company = Company.find_or_create_by(name: params[:company][:name])
92
42
  # @person = @company.people.create(params[:person])
93
43
  #
94
44
  # redirect_to(person_list_url)
@@ -98,13 +48,13 @@ module ActionController #:nodoc:
98
48
  #
99
49
  # def create
100
50
  # company = params[:person].delete(:company)
101
- # @company = Company.find_or_create_by_name(company[:name])
51
+ # @company = Company.find_or_create_by(name: company[:name])
102
52
  # @person = @company.people.create(params[:person])
103
53
  #
104
54
  # respond_to do |format|
105
55
  # format.html { redirect_to(person_list_url) }
106
56
  # format.js
107
- # format.xml { render :xml => @person.to_xml(:include => @company) }
57
+ # format.xml { render xml: @person.to_xml(include: @company) }
108
58
  # end
109
59
  # end
110
60
  #
@@ -126,7 +76,7 @@ module ActionController #:nodoc:
126
76
  # Note, however, the extra bit at the top of that action:
127
77
  #
128
78
  # company = params[:person].delete(:company)
129
- # @company = Company.find_or_create_by_name(company[:name])
79
+ # @company = Company.find_or_create_by(name: company[:name])
130
80
  #
131
81
  # This is because the incoming XML document (if a web-service request is in process) can only contain a
132
82
  # single root-node. So, we have to rearrange things so that the request looks like this (url-encoded):
@@ -151,11 +101,11 @@ module ActionController #:nodoc:
151
101
  # and accept Rails' defaults, life will be much easier.
152
102
  #
153
103
  # If you need to use a MIME type which isn't supported by default, you can register your own handlers in
154
- # config/initializers/mime_types.rb as follows.
104
+ # +config/initializers/mime_types.rb+ as follows.
155
105
  #
156
106
  # Mime::Type.register "image/jpg", :jpg
157
107
  #
158
- # Respond to also allows you to specify a common block for different formats by using any:
108
+ # Respond to also allows you to specify a common block for different formats by using +any+:
159
109
  #
160
110
  # def index
161
111
  # @people = Person.all
@@ -168,126 +118,125 @@ module ActionController #:nodoc:
168
118
  #
169
119
  # In the example above, if the format is xml, it will render:
170
120
  #
171
- # render :xml => @people
121
+ # render xml: @people
172
122
  #
173
123
  # Or if the format is json:
174
124
  #
175
- # render :json => @people
125
+ # render json: @people
126
+ #
127
+ # Formats can have different variants.
128
+ #
129
+ # The request variant is a specialization of the request format, like <tt>:tablet</tt>,
130
+ # <tt>:phone</tt>, or <tt>:desktop</tt>.
176
131
  #
177
- # Since this is a common pattern, you can use the class method respond_to
178
- # with the respond_with method to have the same results:
132
+ # We often want to render different html/json/xml templates for phones,
133
+ # tablets, and desktop browsers. Variants make it easy.
179
134
  #
180
- # class PeopleController < ApplicationController
181
- # respond_to :html, :xml, :json
135
+ # You can set the variant in a +before_action+:
182
136
  #
183
- # def index
184
- # @people = Person.all
185
- # respond_with(@people)
137
+ # request.variant = :tablet if request.user_agent =~ /iPad/
138
+ #
139
+ # Respond to variants in the action just like you respond to formats:
140
+ #
141
+ # respond_to do |format|
142
+ # format.html do |variant|
143
+ # variant.tablet # renders app/views/projects/show.html+tablet.erb
144
+ # variant.phone { extra_setup; render ... }
145
+ # variant.none { special_setup } # executed only if there is no variant set
186
146
  # end
187
147
  # end
188
148
  #
189
- # Be sure to check respond_with and respond_to documentation for more examples.
149
+ # Provide separate templates for each format and variant:
190
150
  #
191
- def respond_to(*mimes, &block)
192
- raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
193
-
194
- if collector = retrieve_collector_from_mimes(mimes, &block)
195
- response = collector.response
196
- response ? response.call : default_render({})
197
- end
198
- end
199
-
200
- # respond_with wraps a resource around a responder for default representation.
201
- # First it invokes respond_to, if a response cannot be found (ie. no block
202
- # for the request was given and template was not available), it instantiates
203
- # an ActionController::Responder with the controller and resource.
151
+ # app/views/projects/show.html.erb
152
+ # app/views/projects/show.html+tablet.erb
153
+ # app/views/projects/show.html+phone.erb
204
154
  #
205
- # ==== Example
155
+ # When you're not sharing any code within the format, you can simplify defining variants
156
+ # using the inline syntax:
206
157
  #
207
- # def index
208
- # @users = User.all
209
- # respond_with(@users)
158
+ # respond_to do |format|
159
+ # format.js { render "trash" }
160
+ # format.html.phone { redirect_to progress_path }
161
+ # format.html.none { render "trash" }
210
162
  # end
211
163
  #
212
- # It also accepts a block to be given. It's used to overwrite a default
213
- # response:
164
+ # Variants also support common +any+/+all+ block that formats have.
214
165
  #
215
- # def create
216
- # @user = User.new(params[:user])
217
- # flash[:notice] = "User was successfully created." if @user.save
166
+ # It works for both inline:
167
+ #
168
+ # respond_to do |format|
169
+ # format.html.any { render html: "any" }
170
+ # format.html.phone { render html: "phone" }
171
+ # end
218
172
  #
219
- # respond_with(@user) do |format|
220
- # format.html { render }
173
+ # and block syntax:
174
+ #
175
+ # respond_to do |format|
176
+ # format.html do |variant|
177
+ # variant.any(:tablet, :phablet){ render html: "any" }
178
+ # variant.phone { render html: "phone" }
221
179
  # end
222
180
  # end
223
181
  #
224
- # All options given to respond_with are sent to the underlying responder,
225
- # except for the option :responder itself. Since the responder interface
226
- # is quite simple (it just needs to respond to call), you can even give
227
- # a proc to it.
182
+ # You can also set an array of variants:
228
183
  #
229
- # In order to use respond_with, first you need to declare the formats your
230
- # controller responds to in the class level with a call to <tt>respond_to</tt>.
184
+ # request.variant = [:tablet, :phone]
231
185
  #
232
- def respond_with(*resources, &block)
233
- raise "In order to use respond_with, first you need to declare the formats your " <<
234
- "controller responds to in the class level" if self.class.mimes_for_respond_to.empty?
235
-
236
- if collector = retrieve_collector_from_mimes(&block)
237
- options = resources.size == 1 ? {} : resources.extract_options!
238
- options[:default_response] = collector.response
239
- (options.delete(:responder) || self.class.responder).call(self, resources, options)
240
- end
241
- end
242
-
243
- protected
244
-
245
- # Collect mimes declared in the class method respond_to valid for the
246
- # current action.
186
+ # This will work similarly to formats and MIME types negotiation. If there
187
+ # is no +:tablet+ variant declared, the +:phone+ variant will be used:
247
188
  #
248
- def collect_mimes_from_class_level #:nodoc:
249
- action = action_name.to_s
250
-
251
- self.class.mimes_for_respond_to.keys.select do |mime|
252
- config = self.class.mimes_for_respond_to[mime]
253
-
254
- if config[:except]
255
- !action.in?(config[:except])
256
- elsif config[:only]
257
- action.in?(config[:only])
258
- else
259
- true
260
- end
261
- end
262
- end
189
+ # respond_to do |format|
190
+ # format.html.none
191
+ # format.html.phone # this gets rendered
192
+ # end
193
+ def respond_to(*mimes)
194
+ raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
263
195
 
264
- # Collects mimes and return the response for the negotiated format. Returns
265
- # nil if :not_acceptable was sent to the client.
266
- #
267
- def retrieve_collector_from_mimes(mimes=nil, &block) #:nodoc:
268
- mimes ||= collect_mimes_from_class_level
269
- collector = Collector.new(mimes)
270
- block.call(collector) if block_given?
271
- format = collector.negotiate_format(request)
196
+ collector = Collector.new(mimes, request.variant)
197
+ yield collector if block_given?
272
198
 
273
- if format
274
- self.content_type ||= format.to_s
275
- lookup_context.formats = [format.to_sym]
276
- lookup_context.rendered_format = lookup_context.formats.first
277
- collector
199
+ if format = collector.negotiate_format(request)
200
+ _process_format(format)
201
+ _set_rendered_content_type format
202
+ response = collector.response
203
+ response.call if response
278
204
  else
279
- head :not_acceptable
280
- nil
205
+ raise ActionController::UnknownFormat
281
206
  end
282
207
  end
283
208
 
284
- class Collector #:nodoc:
209
+ # A container for responses available from the current controller for
210
+ # requests for different mime-types sent to a particular action.
211
+ #
212
+ # The public controller methods +respond_to+ may be called with a block
213
+ # that is used to define responses to different mime-types, e.g.
214
+ # for +respond_to+ :
215
+ #
216
+ # respond_to do |format|
217
+ # format.html
218
+ # format.xml { render xml: @people }
219
+ # end
220
+ #
221
+ # In this usage, the argument passed to the block (+format+ above) is an
222
+ # instance of the ActionController::MimeResponds::Collector class. This
223
+ # object serves as a container in which available responses can be stored by
224
+ # calling any of the dynamically generated, mime-type-specific methods such
225
+ # as +html+, +xml+ etc on the Collector. Each response is represented by a
226
+ # corresponding block if present.
227
+ #
228
+ # A subsequent call to #negotiate_format(request) will enable the Collector
229
+ # to determine which specific mime-type it should respond with for the current
230
+ # request, with this response then being accessible by calling #response.
231
+ class Collector
285
232
  include AbstractController::Collector
286
- attr_accessor :order, :format
233
+ attr_accessor :format
287
234
 
288
- def initialize(mimes)
289
- @order, @responses = [], {}
290
- mimes.each { |mime| send(mime) }
235
+ def initialize(mimes, variant = nil)
236
+ @responses = {}
237
+ @variant = variant
238
+
239
+ mimes.each { |mime| @responses[Mime[mime]] = nil }
291
240
  end
292
241
 
293
242
  def any(*args, &block)
@@ -301,16 +250,63 @@ module ActionController #:nodoc:
301
250
 
302
251
  def custom(mime_type, &block)
303
252
  mime_type = Mime::Type.lookup(mime_type.to_s) unless mime_type.is_a?(Mime::Type)
304
- @order << mime_type
305
- @responses[mime_type] ||= block
253
+ @responses[mime_type] ||= if block_given?
254
+ block
255
+ else
256
+ VariantCollector.new(@variant)
257
+ end
306
258
  end
307
259
 
308
260
  def response
309
- @responses[format] || @responses[Mime::ALL]
261
+ response = @responses.fetch(format, @responses[Mime::ALL])
262
+ if response.is_a?(VariantCollector) # `format.html.phone` - variant inline syntax
263
+ response.variant
264
+ elsif response.nil? || response.arity == 0 # `format.html` - just a format, call its block
265
+ response
266
+ else # `format.html{ |variant| variant.phone }` - variant block syntax
267
+ variant_collector = VariantCollector.new(@variant)
268
+ response.call(variant_collector) # call format block with variants collector
269
+ variant_collector.variant
270
+ end
310
271
  end
311
272
 
312
273
  def negotiate_format(request)
313
- @format = request.negotiate_mime(order)
274
+ @format = request.negotiate_mime(@responses.keys)
275
+ end
276
+
277
+ class VariantCollector #:nodoc:
278
+ def initialize(variant = nil)
279
+ @variant = variant
280
+ @variants = {}
281
+ end
282
+
283
+ def any(*args, &block)
284
+ if block_given?
285
+ if args.any? && args.none? { |a| a == @variant }
286
+ args.each { |v| @variants[v] = block }
287
+ else
288
+ @variants[:any] = block
289
+ end
290
+ end
291
+ end
292
+ alias :all :any
293
+
294
+ def method_missing(name, *args, &block)
295
+ @variants[name] = block if block_given?
296
+ end
297
+
298
+ def variant
299
+ if @variant.empty?
300
+ @variants[:none] || @variants[:any]
301
+ else
302
+ @variants[variant_key]
303
+ end
304
+ end
305
+
306
+ private
307
+ def variant_key
308
+ @variant.find { |variant| @variants.key?(variant) } || :any
309
+ end
314
310
  end
315
311
  end
316
312
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionController
4
+ # Specify binary encoding for parameters for a given action.
5
+ module ParameterEncoding
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ def inherited(klass) # :nodoc:
10
+ super
11
+ klass.setup_param_encode
12
+ end
13
+
14
+ def setup_param_encode # :nodoc:
15
+ @_parameter_encodings = {}
16
+ end
17
+
18
+ def binary_params_for?(action) # :nodoc:
19
+ @_parameter_encodings[action.to_s]
20
+ end
21
+
22
+ # Specify that a given action's parameters should all be encoded as
23
+ # ASCII-8BIT (it "skips" the encoding default of UTF-8).
24
+ #
25
+ # For example, a controller would use it like this:
26
+ #
27
+ # class RepositoryController < ActionController::Base
28
+ # skip_parameter_encoding :show
29
+ #
30
+ # def show
31
+ # @repo = Repository.find_by_filesystem_path params[:file_path]
32
+ #
33
+ # # `repo_name` is guaranteed to be UTF-8, but was ASCII-8BIT, so
34
+ # # tag it as such
35
+ # @repo_name = params[:repo_name].force_encoding 'UTF-8'
36
+ # end
37
+ #
38
+ # def index
39
+ # @repositories = Repository.all
40
+ # end
41
+ # end
42
+ #
43
+ # The show action in the above controller would have all parameter values
44
+ # encoded as ASCII-8BIT. This is useful in the case where an application
45
+ # must handle data but encoding of the data is unknown, like file system data.
46
+ def skip_parameter_encoding(action)
47
+ @_parameter_encodings[action.to_s] = true
48
+ end
49
+ end
50
+ end
51
+ end