actionpack 3.2.22.5 → 4.0.0.beta1

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 (265) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +641 -418
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -288
  5. data/lib/abstract_controller.rb +1 -8
  6. data/lib/abstract_controller/asset_paths.rb +2 -2
  7. data/lib/abstract_controller/base.rb +39 -37
  8. data/lib/abstract_controller/callbacks.rb +101 -82
  9. data/lib/abstract_controller/collector.rb +7 -3
  10. data/lib/abstract_controller/helpers.rb +23 -11
  11. data/lib/abstract_controller/layouts.rb +68 -73
  12. data/lib/abstract_controller/logger.rb +1 -2
  13. data/lib/abstract_controller/rendering.rb +22 -13
  14. data/lib/abstract_controller/translation.rb +16 -1
  15. data/lib/abstract_controller/url_for.rb +6 -6
  16. data/lib/abstract_controller/view_paths.rb +1 -1
  17. data/lib/action_controller.rb +15 -6
  18. data/lib/action_controller/base.rb +46 -22
  19. data/lib/action_controller/caching.rb +46 -33
  20. data/lib/action_controller/caching/fragments.rb +23 -53
  21. data/lib/action_controller/deprecated.rb +5 -1
  22. data/lib/action_controller/deprecated/integration_test.rb +3 -0
  23. data/lib/action_controller/log_subscriber.rb +11 -8
  24. data/lib/action_controller/metal.rb +16 -30
  25. data/lib/action_controller/metal/conditional_get.rb +76 -32
  26. data/lib/action_controller/metal/data_streaming.rb +20 -26
  27. data/lib/action_controller/metal/exceptions.rb +19 -6
  28. data/lib/action_controller/metal/flash.rb +24 -9
  29. data/lib/action_controller/metal/force_ssl.rb +32 -9
  30. data/lib/action_controller/metal/head.rb +25 -4
  31. data/lib/action_controller/metal/helpers.rb +6 -9
  32. data/lib/action_controller/metal/hide_actions.rb +1 -2
  33. data/lib/action_controller/metal/http_authentication.rb +105 -87
  34. data/lib/action_controller/metal/implicit_render.rb +1 -1
  35. data/lib/action_controller/metal/instrumentation.rb +2 -1
  36. data/lib/action_controller/metal/live.rb +141 -0
  37. data/lib/action_controller/metal/mime_responds.rb +161 -47
  38. data/lib/action_controller/metal/params_wrapper.rb +112 -74
  39. data/lib/action_controller/metal/rack_delegation.rb +9 -3
  40. data/lib/action_controller/metal/redirecting.rb +15 -20
  41. data/lib/action_controller/metal/renderers.rb +11 -9
  42. data/lib/action_controller/metal/rendering.rb +8 -0
  43. data/lib/action_controller/metal/request_forgery_protection.rb +112 -19
  44. data/lib/action_controller/metal/responder.rb +20 -19
  45. data/lib/action_controller/metal/streaming.rb +12 -18
  46. data/lib/action_controller/metal/strong_parameters.rb +516 -0
  47. data/lib/action_controller/metal/testing.rb +13 -18
  48. data/lib/action_controller/metal/url_for.rb +27 -25
  49. data/lib/action_controller/model_naming.rb +12 -0
  50. data/lib/action_controller/railtie.rb +33 -17
  51. data/lib/action_controller/railties/helpers.rb +22 -0
  52. data/lib/action_controller/record_identifier.rb +18 -72
  53. data/lib/action_controller/test_case.rb +215 -123
  54. data/lib/action_controller/vendor/html-scanner.rb +4 -19
  55. data/lib/action_dispatch.rb +27 -19
  56. data/lib/action_dispatch/http/cache.rb +63 -11
  57. data/lib/action_dispatch/http/filter_parameters.rb +18 -8
  58. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  59. data/lib/action_dispatch/http/headers.rb +27 -19
  60. data/lib/action_dispatch/http/mime_negotiation.rb +25 -2
  61. data/lib/action_dispatch/http/mime_type.rb +145 -113
  62. data/lib/action_dispatch/http/mime_types.rb +1 -1
  63. data/lib/action_dispatch/http/parameter_filter.rb +44 -46
  64. data/lib/action_dispatch/http/parameters.rb +12 -5
  65. data/lib/action_dispatch/http/rack_cache.rb +2 -3
  66. data/lib/action_dispatch/http/request.rb +49 -18
  67. data/lib/action_dispatch/http/response.rb +129 -35
  68. data/lib/action_dispatch/http/upload.rb +60 -17
  69. data/lib/action_dispatch/http/url.rb +53 -31
  70. data/lib/action_dispatch/journey.rb +5 -0
  71. data/lib/action_dispatch/journey/backwards.rb +5 -0
  72. data/lib/action_dispatch/journey/formatter.rb +146 -0
  73. data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
  74. data/lib/action_dispatch/journey/gtg/simulator.rb +44 -0
  75. data/lib/action_dispatch/journey/gtg/transition_table.rb +156 -0
  76. data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
  77. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  78. data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
  79. data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
  80. data/lib/action_dispatch/journey/nodes/node.rb +124 -0
  81. data/lib/action_dispatch/journey/parser.rb +206 -0
  82. data/lib/action_dispatch/journey/parser.y +47 -0
  83. data/lib/action_dispatch/journey/parser_extras.rb +23 -0
  84. data/lib/action_dispatch/journey/path/pattern.rb +196 -0
  85. data/lib/action_dispatch/journey/route.rb +116 -0
  86. data/lib/action_dispatch/journey/router.rb +164 -0
  87. data/lib/action_dispatch/journey/router/strexp.rb +24 -0
  88. data/lib/action_dispatch/journey/router/utils.rb +54 -0
  89. data/lib/action_dispatch/journey/routes.rb +75 -0
  90. data/lib/action_dispatch/journey/scanner.rb +61 -0
  91. data/lib/action_dispatch/journey/visitors.rb +189 -0
  92. data/lib/action_dispatch/journey/visualizer/fsm.css +34 -0
  93. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  94. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  95. data/lib/action_dispatch/middleware/callbacks.rb +9 -4
  96. data/lib/action_dispatch/middleware/cookies.rb +168 -57
  97. data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -17
  98. data/lib/action_dispatch/middleware/exception_wrapper.rb +27 -3
  99. data/lib/action_dispatch/middleware/flash.rb +58 -58
  100. data/lib/action_dispatch/middleware/params_parser.rb +14 -29
  101. data/lib/action_dispatch/middleware/public_exceptions.rb +31 -14
  102. data/lib/action_dispatch/middleware/reloader.rb +6 -6
  103. data/lib/action_dispatch/middleware/remote_ip.rb +145 -39
  104. data/lib/action_dispatch/middleware/request_id.rb +2 -6
  105. data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
  106. data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
  107. data/lib/action_dispatch/middleware/session/cookie_store.rb +81 -7
  108. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
  109. data/lib/action_dispatch/middleware/show_exceptions.rb +12 -45
  110. data/lib/action_dispatch/middleware/ssl.rb +70 -0
  111. data/lib/action_dispatch/middleware/stack.rb +6 -1
  112. data/lib/action_dispatch/middleware/static.rb +5 -24
  113. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +14 -11
  114. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +25 -0
  115. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
  116. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +15 -9
  117. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +121 -5
  118. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +7 -2
  119. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +30 -15
  120. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +39 -13
  121. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +6 -2
  122. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  123. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +144 -0
  124. data/lib/action_dispatch/railtie.rb +16 -6
  125. data/lib/action_dispatch/request/session.rb +181 -0
  126. data/lib/action_dispatch/routing.rb +41 -40
  127. data/lib/action_dispatch/routing/inspector.rb +240 -0
  128. data/lib/action_dispatch/routing/mapper.rb +501 -273
  129. data/lib/action_dispatch/routing/polymorphic_routes.rb +16 -20
  130. data/lib/action_dispatch/routing/redirection.rb +46 -29
  131. data/lib/action_dispatch/routing/route_set.rb +203 -164
  132. data/lib/action_dispatch/routing/routes_proxy.rb +2 -0
  133. data/lib/action_dispatch/routing/url_for.rb +48 -33
  134. data/lib/action_dispatch/testing/assertions/dom.rb +3 -13
  135. data/lib/action_dispatch/testing/assertions/response.rb +32 -40
  136. data/lib/action_dispatch/testing/assertions/routing.rb +40 -39
  137. data/lib/action_dispatch/testing/assertions/selector.rb +15 -20
  138. data/lib/action_dispatch/testing/assertions/tag.rb +20 -23
  139. data/lib/action_dispatch/testing/integration.rb +41 -22
  140. data/lib/action_dispatch/testing/test_process.rb +9 -6
  141. data/lib/action_dispatch/testing/test_request.rb +7 -3
  142. data/lib/action_pack.rb +1 -1
  143. data/lib/action_pack/version.rb +4 -4
  144. data/lib/action_view.rb +17 -8
  145. data/lib/action_view/base.rb +15 -34
  146. data/lib/action_view/buffers.rb +1 -1
  147. data/lib/action_view/context.rb +4 -4
  148. data/lib/action_view/dependency_tracker.rb +91 -0
  149. data/lib/action_view/digestor.rb +85 -0
  150. data/lib/action_view/flows.rb +1 -4
  151. data/lib/action_view/helpers.rb +2 -4
  152. data/lib/action_view/helpers/active_model_helper.rb +3 -4
  153. data/lib/action_view/helpers/asset_tag_helper.rb +211 -353
  154. data/lib/action_view/helpers/asset_url_helper.rb +354 -0
  155. data/lib/action_view/helpers/atom_feed_helper.rb +13 -10
  156. data/lib/action_view/helpers/cache_helper.rb +150 -18
  157. data/lib/action_view/helpers/capture_helper.rb +42 -29
  158. data/lib/action_view/helpers/csrf_helper.rb +0 -2
  159. data/lib/action_view/helpers/date_helper.rb +268 -247
  160. data/lib/action_view/helpers/debug_helper.rb +10 -11
  161. data/lib/action_view/helpers/form_helper.rb +904 -547
  162. data/lib/action_view/helpers/form_options_helper.rb +341 -166
  163. data/lib/action_view/helpers/form_tag_helper.rb +188 -88
  164. data/lib/action_view/helpers/javascript_helper.rb +23 -16
  165. data/lib/action_view/helpers/number_helper.rb +148 -354
  166. data/lib/action_view/helpers/output_safety_helper.rb +3 -3
  167. data/lib/action_view/helpers/record_tag_helper.rb +17 -22
  168. data/lib/action_view/helpers/rendering_helper.rb +2 -4
  169. data/lib/action_view/helpers/sanitize_helper.rb +3 -6
  170. data/lib/action_view/helpers/tag_helper.rb +43 -37
  171. data/lib/action_view/helpers/tags.rb +39 -0
  172. data/lib/action_view/helpers/tags/base.rb +148 -0
  173. data/lib/action_view/helpers/tags/check_box.rb +64 -0
  174. data/lib/action_view/helpers/tags/checkable.rb +16 -0
  175. data/lib/action_view/helpers/tags/collection_check_boxes.rb +43 -0
  176. data/lib/action_view/helpers/tags/collection_helpers.rb +83 -0
  177. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
  178. data/lib/action_view/helpers/tags/collection_select.rb +28 -0
  179. data/lib/action_view/helpers/tags/color_field.rb +25 -0
  180. data/lib/action_view/helpers/tags/date_field.rb +13 -0
  181. data/lib/action_view/helpers/tags/date_select.rb +72 -0
  182. data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
  183. data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
  184. data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
  185. data/lib/action_view/helpers/tags/email_field.rb +8 -0
  186. data/lib/action_view/helpers/tags/file_field.rb +8 -0
  187. data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
  188. data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
  189. data/lib/action_view/helpers/tags/label.rb +65 -0
  190. data/lib/action_view/helpers/tags/month_field.rb +13 -0
  191. data/lib/action_view/helpers/tags/number_field.rb +18 -0
  192. data/lib/action_view/helpers/tags/password_field.rb +12 -0
  193. data/lib/action_view/helpers/tags/radio_button.rb +31 -0
  194. data/lib/action_view/helpers/tags/range_field.rb +8 -0
  195. data/lib/action_view/helpers/tags/search_field.rb +24 -0
  196. data/lib/action_view/helpers/tags/select.rb +41 -0
  197. data/lib/action_view/helpers/tags/tel_field.rb +8 -0
  198. data/lib/action_view/helpers/tags/text_area.rb +18 -0
  199. data/lib/action_view/helpers/tags/text_field.rb +29 -0
  200. data/lib/action_view/helpers/tags/time_field.rb +13 -0
  201. data/lib/action_view/helpers/tags/time_select.rb +8 -0
  202. data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
  203. data/lib/action_view/helpers/tags/url_field.rb +8 -0
  204. data/lib/action_view/helpers/tags/week_field.rb +13 -0
  205. data/lib/action_view/helpers/text_helper.rb +126 -113
  206. data/lib/action_view/helpers/translation_helper.rb +32 -16
  207. data/lib/action_view/helpers/url_helper.rb +200 -271
  208. data/lib/action_view/locale/en.yml +1 -105
  209. data/lib/action_view/log_subscriber.rb +6 -4
  210. data/lib/action_view/lookup_context.rb +15 -39
  211. data/lib/action_view/model_naming.rb +12 -0
  212. data/lib/action_view/path_set.rb +9 -39
  213. data/lib/action_view/railtie.rb +6 -22
  214. data/lib/action_view/record_identifier.rb +84 -0
  215. data/lib/action_view/renderer/abstract_renderer.rb +10 -19
  216. data/lib/action_view/renderer/partial_renderer.rb +144 -81
  217. data/lib/action_view/renderer/renderer.rb +2 -19
  218. data/lib/action_view/renderer/streaming_template_renderer.rb +2 -5
  219. data/lib/action_view/renderer/template_renderer.rb +14 -13
  220. data/lib/action_view/routing_url_for.rb +107 -0
  221. data/lib/action_view/template.rb +22 -21
  222. data/lib/action_view/template/error.rb +22 -12
  223. data/lib/action_view/template/handlers.rb +12 -9
  224. data/lib/action_view/template/handlers/builder.rb +1 -1
  225. data/lib/action_view/template/handlers/erb.rb +11 -16
  226. data/lib/action_view/template/handlers/raw.rb +11 -0
  227. data/lib/action_view/template/resolver.rb +111 -83
  228. data/lib/action_view/template/text.rb +12 -8
  229. data/lib/action_view/template/types.rb +57 -0
  230. data/lib/action_view/test_case.rb +66 -43
  231. data/lib/action_view/testing/resolvers.rb +3 -2
  232. data/lib/action_view/vendor/html-scanner.rb +20 -0
  233. data/lib/{action_controller → action_view}/vendor/html-scanner/html/document.rb +0 -0
  234. data/lib/{action_controller → action_view}/vendor/html-scanner/html/node.rb +12 -12
  235. data/lib/{action_controller → action_view}/vendor/html-scanner/html/sanitizer.rb +18 -7
  236. data/lib/{action_controller → action_view}/vendor/html-scanner/html/selector.rb +1 -1
  237. data/lib/{action_controller → action_view}/vendor/html-scanner/html/tokenizer.rb +1 -1
  238. data/lib/{action_controller → action_view}/vendor/html-scanner/html/version.rb +0 -0
  239. metadata +135 -125
  240. data/lib/action_controller/caching/actions.rb +0 -185
  241. data/lib/action_controller/caching/pages.rb +0 -187
  242. data/lib/action_controller/caching/sweeping.rb +0 -97
  243. data/lib/action_controller/deprecated/performance_test.rb +0 -1
  244. data/lib/action_controller/metal/compatibility.rb +0 -65
  245. data/lib/action_controller/metal/session_management.rb +0 -14
  246. data/lib/action_controller/railties/paths.rb +0 -25
  247. data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
  248. data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
  249. data/lib/action_dispatch/middleware/head.rb +0 -18
  250. data/lib/action_dispatch/middleware/rescue.rb +0 -26
  251. data/lib/action_dispatch/testing/performance_test.rb +0 -10
  252. data/lib/action_view/asset_paths.rb +0 -142
  253. data/lib/action_view/helpers/asset_paths.rb +0 -7
  254. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
  255. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
  256. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
  257. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
  258. data/lib/sprockets/assets.rake +0 -99
  259. data/lib/sprockets/bootstrap.rb +0 -37
  260. data/lib/sprockets/compressors.rb +0 -83
  261. data/lib/sprockets/helpers.rb +0 -6
  262. data/lib/sprockets/helpers/isolated_helper.rb +0 -13
  263. data/lib/sprockets/helpers/rails_helper.rb +0 -182
  264. data/lib/sprockets/railtie.rb +0 -62
  265. data/lib/sprockets/static_compiler.rb +0 -56
@@ -2,7 +2,7 @@ module ActionController
2
2
  module ImplicitRender
3
3
  def send_action(method, *args)
4
4
  ret = super
5
- default_render unless response_body
5
+ default_render unless performed?
6
6
  ret
7
7
  end
8
8
 
@@ -11,6 +11,7 @@ module ActionController
11
11
  extend ActiveSupport::Concern
12
12
 
13
13
  include AbstractController::Logger
14
+ include ActionController::RackDelegation
14
15
 
15
16
  attr_internal :view_runtime
16
17
 
@@ -59,7 +60,7 @@ module ActionController
59
60
  ActiveSupport::Notifications.instrument("redirect_to.action_controller") do |payload|
60
61
  result = super
61
62
  payload[:status] = response.status
62
- payload[:location] = response.location
63
+ payload[:location] = response.filtered_location
63
64
  result
64
65
  end
65
66
  end
@@ -0,0 +1,141 @@
1
+ require 'action_dispatch/http/response'
2
+ require 'delegate'
3
+
4
+ module ActionController
5
+ # Mix this module in to your controller, and all actions in that controller
6
+ # will be able to stream data to the client as it's written.
7
+ #
8
+ # class MyController < ActionController::Base
9
+ # include ActionController::Live
10
+ #
11
+ # def stream
12
+ # response.headers['Content-Type'] = 'text/event-stream'
13
+ # 100.times {
14
+ # response.stream.write "hello world\n"
15
+ # sleep 1
16
+ # }
17
+ # response.stream.close
18
+ # end
19
+ # end
20
+ #
21
+ # There are a few caveats with this use. You *cannot* write headers after the
22
+ # response has been committed (Response#committed? will return truthy).
23
+ # Calling +write+ or +close+ on the response stream will cause the response
24
+ # object to be committed. Make sure all headers are set before calling write
25
+ # or close on your stream.
26
+ #
27
+ # You *must* call close on your stream when you're finished, otherwise the
28
+ # socket may be left open forever.
29
+ #
30
+ # The final caveat is that your actions are executed in a separate thread than
31
+ # the main thread. Make sure your actions are thread safe, and this shouldn't
32
+ # be a problem (don't share state across threads, etc).
33
+ module Live
34
+ class Buffer < ActionDispatch::Response::Buffer #:nodoc:
35
+ def initialize(response)
36
+ super(response, SizedQueue.new(10))
37
+ end
38
+
39
+ def write(string)
40
+ unless @response.committed?
41
+ @response.headers["Cache-Control"] = "no-cache"
42
+ @response.headers.delete "Content-Length"
43
+ end
44
+
45
+ super
46
+ end
47
+
48
+ def each
49
+ while str = @buf.pop
50
+ yield str
51
+ end
52
+ end
53
+
54
+ def close
55
+ super
56
+ @buf.push nil
57
+ end
58
+ end
59
+
60
+ class Response < ActionDispatch::Response #:nodoc: all
61
+ class Header < DelegateClass(Hash)
62
+ def initialize(response, header)
63
+ @response = response
64
+ super(header)
65
+ end
66
+
67
+ def []=(k,v)
68
+ if @response.committed?
69
+ raise ActionDispatch::IllegalStateError, 'header already sent'
70
+ end
71
+
72
+ super
73
+ end
74
+
75
+ def merge(other)
76
+ self.class.new @response, __getobj__.merge(other)
77
+ end
78
+
79
+ def to_hash
80
+ __getobj__.dup
81
+ end
82
+ end
83
+
84
+ def commit!
85
+ headers.freeze
86
+ super
87
+ end
88
+
89
+ private
90
+
91
+ def build_buffer(response, body)
92
+ buf = Live::Buffer.new response
93
+ body.each { |part| buf.write part }
94
+ buf
95
+ end
96
+
97
+ def merge_default_headers(original, default)
98
+ Header.new self, super
99
+ end
100
+ end
101
+
102
+ def process(name)
103
+ t1 = Thread.current
104
+ locals = t1.keys.map { |key| [key, t1[key]] }
105
+
106
+ # This processes the action in a child thread. It lets us return the
107
+ # response code and headers back up the rack stack, and still process
108
+ # the body in parallel with sending data to the client
109
+ Thread.new {
110
+ t2 = Thread.current
111
+ t2.abort_on_exception = true
112
+
113
+ # Since we're processing the view in a different thread, copy the
114
+ # thread locals from the main thread to the child thread. :'(
115
+ locals.each { |k,v| t2[k] = v }
116
+
117
+ begin
118
+ super(name)
119
+ ensure
120
+ @_response.commit!
121
+ end
122
+ }
123
+
124
+ @_response.await_commit
125
+ end
126
+
127
+ def response_body=(body)
128
+ super
129
+ response.stream.close if response
130
+ end
131
+
132
+ def set_response!(request)
133
+ if request.env["HTTP_VERSION"] == "HTTP/1.0"
134
+ super
135
+ else
136
+ @_response = Live::Response.new
137
+ @_response.request = request
138
+ end
139
+ end
140
+ end
141
+ end
@@ -1,13 +1,10 @@
1
+ require 'active_support/core_ext/array/extract_options'
1
2
  require 'abstract_controller/collector'
2
- require 'active_support/core_ext/class/attribute'
3
- require 'active_support/core_ext/object/inclusion'
4
3
 
5
4
  module ActionController #:nodoc:
6
5
  module MimeResponds
7
6
  extend ActiveSupport::Concern
8
7
 
9
- include ActionController::ImplicitRender
10
-
11
8
  included do
12
9
  class_attribute :responder, :mimes_for_respond_to
13
10
  self.responder = ActionController::Responder
@@ -18,8 +15,6 @@ module ActionController #:nodoc:
18
15
  # Defines mime types that are rendered by default when invoking
19
16
  # <tt>respond_with</tt>.
20
17
  #
21
- # Examples:
22
- #
23
18
  # respond_to :html, :xml, :json
24
19
  #
25
20
  # Specifies that all actions in the controller respond to requests
@@ -29,13 +24,13 @@ module ActionController #:nodoc:
29
24
  # <tt>:except</tt> with an array of actions or a single action:
30
25
  #
31
26
  # respond_to :html
32
- # respond_to :xml, :json, :except => [ :edit ]
27
+ # respond_to :xml, :json, except: [ :edit ]
33
28
  #
34
29
  # This specifies that all actions respond to <tt>:html</tt>
35
30
  # and all actions except <tt>:edit</tt> respond to <tt>:xml</tt> and
36
31
  # <tt>:json</tt>.
37
32
  #
38
- # respond_to :json, :only => :create
33
+ # respond_to :json, only: :create
39
34
  #
40
35
  # This specifies that the <tt>:create</tt> action and no other responds
41
36
  # to <tt>:json</tt>.
@@ -58,7 +53,7 @@ module ActionController #:nodoc:
58
53
  # Clear all mime types in <tt>respond_to</tt>.
59
54
  #
60
55
  def clear_respond_to
61
- self.mimes_for_respond_to = ActiveSupport::OrderedHash.new.freeze
56
+ self.mimes_for_respond_to = Hash.new.freeze
62
57
  end
63
58
  end
64
59
 
@@ -76,7 +71,7 @@ module ActionController #:nodoc:
76
71
  #
77
72
  # respond_to do |format|
78
73
  # format.html
79
- # format.xml { render :xml => @people.to_xml }
74
+ # format.xml { render xml: @people }
80
75
  # end
81
76
  # end
82
77
  #
@@ -88,7 +83,7 @@ module ActionController #:nodoc:
88
83
  # (by name) if it does not already exist, without web-services, it might look like this:
89
84
  #
90
85
  # def create
91
- # @company = Company.find_or_create_by_name(params[:company][:name])
86
+ # @company = Company.find_or_create_by(name: params[:company][:name])
92
87
  # @person = @company.people.create(params[:person])
93
88
  #
94
89
  # redirect_to(person_list_url)
@@ -98,13 +93,13 @@ module ActionController #:nodoc:
98
93
  #
99
94
  # def create
100
95
  # company = params[:person].delete(:company)
101
- # @company = Company.find_or_create_by_name(company[:name])
96
+ # @company = Company.find_or_create_by(name: company[:name])
102
97
  # @person = @company.people.create(params[:person])
103
98
  #
104
99
  # respond_to do |format|
105
100
  # format.html { redirect_to(person_list_url) }
106
101
  # format.js
107
- # format.xml { render :xml => @person.to_xml(:include => @company) }
102
+ # format.xml { render xml: @person.to_xml(include: @company) }
108
103
  # end
109
104
  # end
110
105
  #
@@ -126,7 +121,7 @@ module ActionController #:nodoc:
126
121
  # Note, however, the extra bit at the top of that action:
127
122
  #
128
123
  # company = params[:person].delete(:company)
129
- # @company = Company.find_or_create_by_name(company[:name])
124
+ # @company = Company.find_or_create_by(name: company[:name])
130
125
  #
131
126
  # This is because the incoming XML document (if a web-service request is in process) can only contain a
132
127
  # single root-node. So, we have to rearrange things so that the request looks like this (url-encoded):
@@ -168,11 +163,11 @@ module ActionController #:nodoc:
168
163
  #
169
164
  # In the example above, if the format is xml, it will render:
170
165
  #
171
- # render :xml => @people
166
+ # render xml: @people
172
167
  #
173
168
  # Or if the format is json:
174
169
  #
175
- # render :json => @people
170
+ # render json: @people
176
171
  #
177
172
  # Since this is a common pattern, you can use the class method respond_to
178
173
  # with the respond_with method to have the same results:
@@ -186,31 +181,117 @@ module ActionController #:nodoc:
186
181
  # end
187
182
  # end
188
183
  #
189
- # Be sure to check respond_with and respond_to documentation for more examples.
190
- #
184
+ # Be sure to check the documentation of +respond_with+ and
185
+ # <tt>ActionController::MimeResponds.respond_to</tt> for more examples.
191
186
  def respond_to(*mimes, &block)
192
187
  raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
193
188
 
194
189
  if collector = retrieve_collector_from_mimes(mimes, &block)
195
190
  response = collector.response
196
- response ? response.call : default_render({})
191
+ response ? response.call : render({})
197
192
  end
198
193
  end
199
194
 
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.
195
+ # For a given controller action, respond_with generates an appropriate
196
+ # response based on the mime-type requested by the client.
204
197
  #
205
- # ==== Example
198
+ # If the method is called with just a resource, as in this example -
206
199
  #
207
- # def index
208
- # @users = User.all
209
- # respond_with(@users)
200
+ # class PeopleController < ApplicationController
201
+ # respond_to :html, :xml, :json
202
+ #
203
+ # def index
204
+ # @people = Person.all
205
+ # respond_with @people
206
+ # end
207
+ # end
208
+ #
209
+ # then the mime-type of the response is typically selected based on the
210
+ # request's Accept header and the set of available formats declared
211
+ # by previous calls to the controller's class method +respond_to+. Alternatively
212
+ # the mime-type can be selected by explicitly setting <tt>request.format</tt> in
213
+ # the controller.
214
+ #
215
+ # If an acceptable format is not identified, the application returns a
216
+ # '406 - not acceptable' status. Otherwise, the default response is to render
217
+ # a template named after the current action and the selected format,
218
+ # e.g. <tt>index.html.erb</tt>. If no template is available, the behavior
219
+ # depends on the selected format:
220
+ #
221
+ # * for an html response - if the request method is +get+, an exception
222
+ # is raised but for other requests such as +post+ the response
223
+ # depends on whether the resource has any validation errors (i.e.
224
+ # assuming that an attempt has been made to save the resource,
225
+ # e.g. by a +create+ action) -
226
+ # 1. If there are no errors, i.e. the resource
227
+ # was saved successfully, the response +redirect+'s to the resource
228
+ # i.e. its +show+ action.
229
+ # 2. If there are validation errors, the response
230
+ # renders a default action, which is <tt>:new</tt> for a
231
+ # +post+ request or <tt>:edit</tt> for +patch+ or +put+.
232
+ # Thus an example like this -
233
+ #
234
+ # respond_to :html, :xml
235
+ #
236
+ # def create
237
+ # @user = User.new(params[:user])
238
+ # flash[:notice] = 'User was successfully created.' if @user.save
239
+ # respond_with(@user)
240
+ # end
241
+ #
242
+ # is equivalent, in the absence of <tt>create.html.erb</tt>, to -
243
+ #
244
+ # def create
245
+ # @user = User.new(params[:user])
246
+ # respond_to do |format|
247
+ # if @user.save
248
+ # flash[:notice] = 'User was successfully created.'
249
+ # format.html { redirect_to(@user) }
250
+ # format.xml { render xml: @user }
251
+ # else
252
+ # format.html { render action: "new" }
253
+ # format.xml { render xml: @user }
254
+ # end
255
+ # end
256
+ # end
257
+ #
258
+ # * for a javascript request - if the template isn't found, an exception is
259
+ # raised.
260
+ # * for other requests - i.e. data formats such as xml, json, csv etc, if
261
+ # the resource passed to +respond_with+ responds to <code>to_<format></code>,
262
+ # the method attempts to render the resource in the requested format
263
+ # directly, e.g. for an xml request, the response is equivalent to calling
264
+ # <code>render xml: resource</code>.
265
+ #
266
+ # === Nested resources
267
+ #
268
+ # As outlined above, the +resources+ argument passed to +respond_with+
269
+ # can play two roles. It can be used to generate the redirect url
270
+ # for successful html requests (e.g. for +create+ actions when
271
+ # no template exists), while for formats other than html and javascript
272
+ # it is the object that gets rendered, by being converted directly to the
273
+ # required format (again assuming no template exists).
274
+ #
275
+ # For redirecting successful html requests, +respond_with+ also supports
276
+ # the use of nested resources, which are supplied in the same way as
277
+ # in <code>form_for</code> and <code>polymorphic_url</code>. For example -
278
+ #
279
+ # def create
280
+ # @project = Project.find(params[:project_id])
281
+ # @task = @project.comments.build(params[:task])
282
+ # flash[:notice] = 'Task was successfully created.' if @task.save
283
+ # respond_with(@project, @task)
210
284
  # end
211
285
  #
212
- # It also accepts a block to be given. It's used to overwrite a default
213
- # response:
286
+ # This would cause +respond_with+ to redirect to <code>project_task_url</code>
287
+ # instead of <code>task_url</code>. For request formats other than html or
288
+ # javascript, if multiple resources are passed in this way, it is the last
289
+ # one specified that is rendered.
290
+ #
291
+ # === Customizing response behavior
292
+ #
293
+ # Like +respond_to+, +respond_with+ may also be called with a block that
294
+ # can be used to overwrite any of the default responses, e.g. -
214
295
  #
215
296
  # def create
216
297
  # @user = User.new(params[:user])
@@ -221,16 +302,26 @@ module ActionController #:nodoc:
221
302
  # end
222
303
  # end
223
304
  #
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.
228
- #
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>.
231
- #
305
+ # The argument passed to the block is an ActionController::MimeResponds::Collector
306
+ # object which stores the responses for the formats defined within the
307
+ # block. Note that formats with responses defined explicitly in this way
308
+ # do not have to first be declared using the class method +respond_to+.
309
+ #
310
+ # Also, a hash passed to +respond_with+ immediately after the specified
311
+ # resource(s) is interpreted as a set of options relevant to all
312
+ # formats. Any option accepted by +render+ can be used, e.g.
313
+ # respond_with @people, status: 200
314
+ # However, note that these options are ignored after an unsuccessful attempt
315
+ # to save a resource, e.g. when automatically rendering <tt>:new</tt>
316
+ # after a post request.
317
+ #
318
+ # Two additional options are relevant specifically to +respond_with+ -
319
+ # 1. <tt>:location</tt> - overwrites the default redirect location used after
320
+ # a successful html +post+ request.
321
+ # 2. <tt>:action</tt> - overwrites the default render action used after an
322
+ # unsuccessful html +post+ request.
232
323
  def respond_with(*resources, &block)
233
- raise "In order to use respond_with, first you need to declare the formats your " <<
324
+ raise "In order to use respond_with, first you need to declare the formats your " \
234
325
  "controller responds to in the class level" if self.class.mimes_for_respond_to.empty?
235
326
 
236
327
  if collector = retrieve_collector_from_mimes(&block)
@@ -244,7 +335,6 @@ module ActionController #:nodoc:
244
335
 
245
336
  # Collect mimes declared in the class method respond_to valid for the
246
337
  # current action.
247
- #
248
338
  def collect_mimes_from_class_level #:nodoc:
249
339
  action = action_name.to_s
250
340
 
@@ -252,18 +342,21 @@ module ActionController #:nodoc:
252
342
  config = self.class.mimes_for_respond_to[mime]
253
343
 
254
344
  if config[:except]
255
- !action.in?(config[:except])
345
+ !config[:except].include?(action)
256
346
  elsif config[:only]
257
- action.in?(config[:only])
347
+ config[:only].include?(action)
258
348
  else
259
349
  true
260
350
  end
261
351
  end
262
352
  end
263
353
 
264
- # Collects mimes and return the response for the negotiated format. Returns
265
- # nil if :not_acceptable was sent to the client.
354
+ # Returns a Collector object containing the appropriate mime-type response
355
+ # for the current request, based on the available responses defined by a block.
356
+ # In typical usage this is the block passed to +respond_with+ or +respond_to+.
266
357
  #
358
+ # Sends :not_acceptable to the client and returns nil if no suitable format
359
+ # is available.
267
360
  def retrieve_collector_from_mimes(mimes=nil, &block) #:nodoc:
268
361
  mimes ||= collect_mimes_from_class_level
269
362
  collector = Collector.new(mimes)
@@ -276,12 +369,33 @@ module ActionController #:nodoc:
276
369
  lookup_context.rendered_format = lookup_context.formats.first
277
370
  collector
278
371
  else
279
- head :not_acceptable
280
- nil
372
+ raise ActionController::UnknownFormat
281
373
  end
282
374
  end
283
375
 
284
- class Collector #:nodoc:
376
+ # A container for responses available from the current controller for
377
+ # requests for different mime-types sent to a particular action.
378
+ #
379
+ # The public controller methods +respond_with+ and +respond_to+ may be called
380
+ # with a block that is used to define responses to different mime-types, e.g.
381
+ # for +respond_to+ :
382
+ #
383
+ # respond_to do |format|
384
+ # format.html
385
+ # format.xml { render xml: @people }
386
+ # end
387
+ #
388
+ # In this usage, the argument passed to the block (+format+ above) is an
389
+ # instance of the ActionController::MimeResponds::Collector class. This
390
+ # object serves as a container in which available responses can be stored by
391
+ # calling any of the dynamically generated, mime-type-specific methods such
392
+ # as +html+, +xml+ etc on the Collector. Each response is represented by a
393
+ # corresponding block if present.
394
+ #
395
+ # A subsequent call to #negotiate_format(request) will enable the Collector
396
+ # to determine which specific mime-type it should respond with for the current
397
+ # request, with this response then being accessible by calling #response.
398
+ class Collector
285
399
  include AbstractController::Collector
286
400
  attr_accessor :order, :format
287
401
 
@@ -306,7 +420,7 @@ module ActionController #:nodoc:
306
420
  end
307
421
 
308
422
  def response
309
- @responses[format] || @responses[Mime::ALL]
423
+ @responses.fetch(format, @responses[Mime::ALL])
310
424
  end
311
425
 
312
426
  def negotiate_format(request)