actionpack 2.2.3 → 2.3.2

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 (264) hide show
  1. data/CHANGELOG +433 -375
  2. data/MIT-LICENSE +1 -1
  3. data/README +21 -75
  4. data/Rakefile +1 -1
  5. data/lib/action_controller.rb +80 -43
  6. data/lib/action_controller/assertions/model_assertions.rb +1 -0
  7. data/lib/action_controller/assertions/response_assertions.rb +43 -16
  8. data/lib/action_controller/assertions/routing_assertions.rb +1 -1
  9. data/lib/action_controller/assertions/selector_assertions.rb +17 -12
  10. data/lib/action_controller/assertions/tag_assertions.rb +1 -4
  11. data/lib/action_controller/base.rb +153 -82
  12. data/lib/action_controller/benchmarking.rb +9 -9
  13. data/lib/action_controller/caching.rb +9 -11
  14. data/lib/action_controller/caching/actions.rb +11 -18
  15. data/lib/action_controller/caching/fragments.rb +28 -20
  16. data/lib/action_controller/caching/pages.rb +13 -15
  17. data/lib/action_controller/caching/sweeping.rb +2 -2
  18. data/lib/action_controller/cgi_ext.rb +0 -1
  19. data/lib/action_controller/cgi_ext/cookie.rb +2 -0
  20. data/lib/action_controller/cgi_process.rb +54 -162
  21. data/lib/action_controller/cookies.rb +13 -25
  22. data/lib/action_controller/dispatcher.rb +43 -122
  23. data/lib/action_controller/failsafe.rb +52 -0
  24. data/lib/action_controller/flash.rb +38 -47
  25. data/lib/action_controller/helpers.rb +13 -9
  26. data/lib/action_controller/http_authentication.rb +203 -23
  27. data/lib/action_controller/integration.rb +126 -70
  28. data/lib/action_controller/layout.rb +36 -39
  29. data/lib/action_controller/middleware_stack.rb +119 -0
  30. data/lib/action_controller/middlewares.rb +13 -0
  31. data/lib/action_controller/mime_responds.rb +19 -4
  32. data/lib/action_controller/mime_type.rb +8 -0
  33. data/lib/action_controller/params_parser.rb +71 -0
  34. data/lib/action_controller/performance_test.rb +0 -1
  35. data/lib/action_controller/polymorphic_routes.rb +36 -30
  36. data/lib/action_controller/reloader.rb +14 -0
  37. data/lib/action_controller/request.rb +107 -499
  38. data/lib/action_controller/request_forgery_protection.rb +7 -39
  39. data/lib/action_controller/rescue.rb +55 -35
  40. data/lib/action_controller/resources.rb +34 -31
  41. data/lib/action_controller/response.rb +99 -57
  42. data/lib/action_controller/rewindable_input.rb +28 -0
  43. data/lib/action_controller/routing.rb +7 -7
  44. data/lib/action_controller/routing/builder.rb +4 -1
  45. data/lib/action_controller/routing/optimisations.rb +1 -1
  46. data/lib/action_controller/routing/recognition_optimisation.rb +1 -2
  47. data/lib/action_controller/routing/route.rb +15 -5
  48. data/lib/action_controller/routing/route_set.rb +82 -35
  49. data/lib/action_controller/routing/segments.rb +35 -0
  50. data/lib/action_controller/session/abstract_store.rb +181 -0
  51. data/lib/action_controller/session/cookie_store.rb +197 -175
  52. data/lib/action_controller/session/mem_cache_store.rb +36 -83
  53. data/lib/action_controller/session_management.rb +26 -134
  54. data/lib/action_controller/streaming.rb +24 -7
  55. data/lib/action_controller/templates/rescues/diagnostics.erb +2 -2
  56. data/lib/action_controller/templates/rescues/template_error.erb +2 -2
  57. data/lib/action_controller/test_case.rb +87 -30
  58. data/lib/action_controller/test_process.rb +145 -104
  59. data/lib/action_controller/uploaded_file.rb +44 -0
  60. data/lib/action_controller/url_rewriter.rb +3 -6
  61. data/lib/action_controller/vendor/html-scanner.rb +16 -0
  62. data/lib/action_controller/vendor/html-scanner/html/selector.rb +1 -1
  63. data/lib/action_controller/vendor/rack-1.0/rack.rb +89 -0
  64. data/lib/action_controller/vendor/rack-1.0/rack/adapter/camping.rb +22 -0
  65. data/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/handler.rb +37 -0
  66. data/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/request.rb +37 -0
  67. data/lib/action_controller/vendor/rack-1.0/rack/auth/basic.rb +58 -0
  68. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/md5.rb +124 -0
  69. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/nonce.rb +51 -0
  70. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/params.rb +55 -0
  71. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/request.rb +40 -0
  72. data/lib/action_controller/vendor/rack-1.0/rack/auth/openid.rb +480 -0
  73. data/lib/action_controller/vendor/rack-1.0/rack/builder.rb +63 -0
  74. data/lib/action_controller/vendor/rack-1.0/rack/cascade.rb +36 -0
  75. data/lib/action_controller/vendor/rack-1.0/rack/chunked.rb +49 -0
  76. data/lib/action_controller/vendor/rack-1.0/rack/commonlogger.rb +61 -0
  77. data/lib/action_controller/vendor/rack-1.0/rack/conditionalget.rb +45 -0
  78. data/lib/action_controller/vendor/rack-1.0/rack/content_length.rb +29 -0
  79. data/lib/action_controller/vendor/rack-1.0/rack/content_type.rb +23 -0
  80. data/lib/action_controller/vendor/rack-1.0/rack/deflater.rb +85 -0
  81. data/lib/action_controller/vendor/rack-1.0/rack/directory.rb +153 -0
  82. data/lib/action_controller/vendor/rack-1.0/rack/file.rb +88 -0
  83. data/lib/action_controller/vendor/rack-1.0/rack/handler.rb +48 -0
  84. data/lib/action_controller/vendor/rack-1.0/rack/handler/cgi.rb +61 -0
  85. data/lib/action_controller/vendor/rack-1.0/rack/handler/evented_mongrel.rb +8 -0
  86. data/lib/action_controller/vendor/rack-1.0/rack/handler/fastcgi.rb +89 -0
  87. data/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb +55 -0
  88. data/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb +84 -0
  89. data/lib/action_controller/vendor/rack-1.0/rack/handler/scgi.rb +59 -0
  90. data/lib/action_controller/vendor/rack-1.0/rack/handler/swiftiplied_mongrel.rb +8 -0
  91. data/lib/action_controller/vendor/rack-1.0/rack/handler/thin.rb +18 -0
  92. data/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb +67 -0
  93. data/lib/action_controller/vendor/rack-1.0/rack/head.rb +19 -0
  94. data/lib/action_controller/vendor/rack-1.0/rack/lint.rb +462 -0
  95. data/lib/action_controller/vendor/rack-1.0/rack/lobster.rb +65 -0
  96. data/lib/action_controller/vendor/rack-1.0/rack/lock.rb +16 -0
  97. data/lib/action_controller/vendor/rack-1.0/rack/methodoverride.rb +27 -0
  98. data/lib/action_controller/vendor/rack-1.0/rack/mime.rb +204 -0
  99. data/lib/action_controller/vendor/rack-1.0/rack/mock.rb +160 -0
  100. data/lib/action_controller/vendor/rack-1.0/rack/recursive.rb +57 -0
  101. data/lib/action_controller/vendor/rack-1.0/rack/reloader.rb +64 -0
  102. data/lib/action_controller/vendor/rack-1.0/rack/request.rb +241 -0
  103. data/lib/action_controller/vendor/rack-1.0/rack/response.rb +179 -0
  104. data/lib/action_controller/vendor/rack-1.0/rack/session/abstract/id.rb +142 -0
  105. data/lib/action_controller/vendor/rack-1.0/rack/session/cookie.rb +91 -0
  106. data/lib/action_controller/vendor/rack-1.0/rack/session/memcache.rb +109 -0
  107. data/lib/action_controller/vendor/rack-1.0/rack/session/pool.rb +100 -0
  108. data/lib/action_controller/vendor/rack-1.0/rack/showexceptions.rb +349 -0
  109. data/lib/action_controller/vendor/rack-1.0/rack/showstatus.rb +106 -0
  110. data/lib/action_controller/vendor/rack-1.0/rack/static.rb +38 -0
  111. data/lib/action_controller/vendor/rack-1.0/rack/urlmap.rb +55 -0
  112. data/lib/action_controller/vendor/rack-1.0/rack/utils.rb +392 -0
  113. data/lib/action_controller/verification.rb +1 -1
  114. data/lib/action_pack.rb +1 -1
  115. data/lib/action_pack/version.rb +2 -2
  116. data/lib/action_view.rb +22 -17
  117. data/lib/action_view/base.rb +53 -79
  118. data/lib/action_view/erb/util.rb +38 -0
  119. data/lib/action_view/helpers.rb +24 -5
  120. data/lib/action_view/helpers/active_record_helper.rb +2 -2
  121. data/lib/action_view/helpers/asset_tag_helper.rb +81 -50
  122. data/lib/action_view/helpers/atom_feed_helper.rb +1 -1
  123. data/lib/action_view/helpers/benchmark_helper.rb +26 -5
  124. data/lib/action_view/helpers/date_helper.rb +82 -7
  125. data/lib/action_view/helpers/form_helper.rb +295 -64
  126. data/lib/action_view/helpers/form_options_helper.rb +160 -18
  127. data/lib/action_view/helpers/form_tag_helper.rb +2 -2
  128. data/lib/action_view/helpers/number_helper.rb +31 -18
  129. data/lib/action_view/helpers/prototype_helper.rb +2 -12
  130. data/lib/action_view/helpers/sanitize_helper.rb +0 -10
  131. data/lib/action_view/helpers/scriptaculous_helper.rb +1 -0
  132. data/lib/action_view/helpers/tag_helper.rb +3 -4
  133. data/lib/action_view/helpers/text_helper.rb +99 -122
  134. data/lib/action_view/helpers/translation_helper.rb +19 -1
  135. data/lib/action_view/helpers/url_helper.rb +25 -2
  136. data/lib/action_view/inline_template.rb +1 -1
  137. data/lib/action_view/locale/en.yml +19 -1
  138. data/lib/action_view/partials.rb +46 -9
  139. data/lib/action_view/paths.rb +28 -84
  140. data/lib/action_view/reloadable_template.rb +117 -0
  141. data/lib/action_view/renderable.rb +28 -35
  142. data/lib/action_view/renderable_partial.rb +3 -4
  143. data/lib/action_view/template.rb +172 -31
  144. data/lib/action_view/template_error.rb +8 -9
  145. data/lib/action_view/template_handler.rb +1 -1
  146. data/lib/action_view/template_handlers.rb +9 -6
  147. data/lib/action_view/template_handlers/erb.rb +2 -39
  148. data/lib/action_view/template_handlers/rjs.rb +1 -0
  149. data/lib/action_view/test_case.rb +27 -1
  150. data/test/abstract_unit.rb +23 -17
  151. data/test/active_record_unit.rb +5 -4
  152. data/test/activerecord/active_record_store_test.rb +139 -106
  153. data/test/activerecord/render_partial_with_record_identification_test.rb +5 -21
  154. data/test/controller/action_pack_assertions_test.rb +25 -23
  155. data/test/controller/addresses_render_test.rb +3 -6
  156. data/test/controller/assert_select_test.rb +83 -70
  157. data/test/controller/base_test.rb +11 -13
  158. data/test/controller/benchmark_test.rb +3 -3
  159. data/test/controller/caching_test.rb +34 -24
  160. data/test/controller/capture_test.rb +3 -6
  161. data/test/controller/content_type_test.rb +3 -6
  162. data/test/controller/cookie_test.rb +31 -66
  163. data/test/controller/deprecation/deprecated_base_methods_test.rb +9 -11
  164. data/test/controller/dispatcher_test.rb +23 -28
  165. data/test/controller/fake_models.rb +8 -0
  166. data/test/controller/filters_test.rb +6 -2
  167. data/test/controller/flash_test.rb +2 -6
  168. data/test/controller/helper_test.rb +15 -1
  169. data/test/controller/html-scanner/document_test.rb +1 -1
  170. data/test/controller/html-scanner/sanitizer_test.rb +1 -1
  171. data/test/controller/http_basic_authentication_test.rb +88 -0
  172. data/test/controller/http_digest_authentication_test.rb +178 -0
  173. data/test/controller/integration_test.rb +56 -52
  174. data/test/controller/layout_test.rb +46 -44
  175. data/test/controller/middleware_stack_test.rb +90 -0
  176. data/test/controller/mime_responds_test.rb +7 -11
  177. data/test/controller/mime_type_test.rb +9 -0
  178. data/test/controller/polymorphic_routes_test.rb +235 -151
  179. data/test/controller/rack_test.rb +52 -81
  180. data/test/controller/redirect_test.rb +6 -14
  181. data/test/controller/render_test.rb +273 -60
  182. data/test/controller/request/json_params_parsing_test.rb +45 -0
  183. data/test/controller/request/multipart_params_parsing_test.rb +223 -0
  184. data/test/controller/request/query_string_parsing_test.rb +120 -0
  185. data/test/controller/request/url_encoded_params_parsing_test.rb +184 -0
  186. data/test/controller/request/xml_params_parsing_test.rb +88 -0
  187. data/test/controller/request_forgery_protection_test.rb +17 -98
  188. data/test/controller/request_test.rb +45 -530
  189. data/test/controller/rescue_test.rb +45 -22
  190. data/test/controller/resources_test.rb +112 -37
  191. data/test/controller/routing_test.rb +1442 -1384
  192. data/test/controller/selector_test.rb +3 -3
  193. data/test/controller/send_file_test.rb +30 -3
  194. data/test/controller/session/cookie_store_test.rb +169 -240
  195. data/test/controller/session/mem_cache_store_test.rb +94 -148
  196. data/test/controller/session/test_session_test.rb +58 -0
  197. data/test/controller/test_test.rb +32 -13
  198. data/test/controller/url_rewriter_test.rb +54 -4
  199. data/test/controller/verification_test.rb +1 -1
  200. data/test/controller/view_paths_test.rb +15 -15
  201. data/test/controller/webservice_test.rb +178 -147
  202. data/test/fixtures/alternate_helpers/foo_helper.rb +3 -0
  203. data/test/fixtures/layout_tests/alt/layouts/alt.rhtml +0 -0
  204. data/test/fixtures/layouts/default_html.html.erb +1 -0
  205. data/test/fixtures/layouts/xhr.html.erb +2 -0
  206. data/test/fixtures/multipart/empty +10 -0
  207. data/test/fixtures/multipart/hello.txt +1 -0
  208. data/test/fixtures/multipart/none +9 -0
  209. data/test/fixtures/public/500.da.html +1 -0
  210. data/test/fixtures/quiz/questions/_question.html.erb +1 -0
  211. data/test/fixtures/replies.yml +1 -1
  212. data/test/fixtures/test/_one.html.erb +1 -0
  213. data/test/fixtures/test/_two.html.erb +1 -0
  214. data/test/fixtures/test/dont_pick_me +1 -0
  215. data/test/fixtures/test/hello.builder +1 -1
  216. data/test/fixtures/test/hello_world.da.html.erb +1 -0
  217. data/test/fixtures/test/hello_world.erb~ +1 -0
  218. data/test/fixtures/test/hello_world.pt-BR.html.erb +1 -0
  219. data/test/fixtures/test/malformed/malformed.en.html.erb~ +1 -0
  220. data/test/fixtures/test/malformed/malformed.erb~ +1 -0
  221. data/test/fixtures/test/malformed/malformed.html.erb~ +1 -0
  222. data/test/fixtures/test/render_explicit_html_template.js.rjs +1 -0
  223. data/test/fixtures/test/render_implicit_html_template.js.rjs +1 -0
  224. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb +1 -0
  225. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb +1 -0
  226. data/test/fixtures/test/render_implicit_js_template_without_layout.js.erb +1 -0
  227. data/test/fixtures/test/utf8.html.erb +2 -0
  228. data/test/template/active_record_helper_i18n_test.rb +31 -33
  229. data/test/template/active_record_helper_test.rb +34 -0
  230. data/test/template/asset_tag_helper_test.rb +52 -14
  231. data/test/template/atom_feed_helper_test.rb +3 -5
  232. data/test/template/benchmark_helper_test.rb +50 -24
  233. data/test/template/compiled_templates_test.rb +177 -33
  234. data/test/template/date_helper_i18n_test.rb +88 -81
  235. data/test/template/date_helper_test.rb +427 -43
  236. data/test/template/form_helper_test.rb +243 -44
  237. data/test/template/form_options_helper_test.rb +631 -565
  238. data/test/template/form_tag_helper_test.rb +9 -2
  239. data/test/template/javascript_helper_test.rb +0 -5
  240. data/test/template/number_helper_i18n_test.rb +60 -48
  241. data/test/template/number_helper_test.rb +1 -0
  242. data/test/template/render_test.rb +117 -35
  243. data/test/template/test_test.rb +4 -6
  244. data/test/template/text_helper_test.rb +129 -50
  245. data/test/template/translation_helper_test.rb +23 -19
  246. data/test/template/url_helper_test.rb +35 -2
  247. data/test/view/test_case_test.rb +8 -0
  248. metadata +197 -23
  249. data/lib/action_controller/assertions.rb +0 -69
  250. data/lib/action_controller/caching/sql_cache.rb +0 -18
  251. data/lib/action_controller/cgi_ext/session.rb +0 -53
  252. data/lib/action_controller/components.rb +0 -169
  253. data/lib/action_controller/rack_process.rb +0 -297
  254. data/lib/action_controller/request_profiler.rb +0 -169
  255. data/lib/action_controller/session/active_record_store.rb +0 -340
  256. data/lib/action_controller/session/drb_server.rb +0 -32
  257. data/lib/action_controller/session/drb_store.rb +0 -35
  258. data/test/controller/cgi_test.rb +0 -269
  259. data/test/controller/components_test.rb +0 -156
  260. data/test/controller/http_authentication_test.rb +0 -54
  261. data/test/controller/integration_upload_test.rb +0 -43
  262. data/test/controller/session_fixation_test.rb +0 -89
  263. data/test/controller/session_management_test.rb +0 -178
  264. data/test/fixtures/test/hello_world.js +0 -1
@@ -41,7 +41,7 @@ module ActionController #:nodoc:
41
41
  # * <tt>:expires</tt> - The time at which this cookie expires, as a Time object.
42
42
  # * <tt>:secure</tt> - Whether this cookie is a only transmitted to HTTPS servers.
43
43
  # Default is +false+.
44
- # * <tt>:http_only</tt> - Whether this cookie is accessible via scripting or
44
+ # * <tt>:httponly</tt> - Whether this cookie is accessible via scripting or
45
45
  # only HTTP. Defaults to +false+.
46
46
  module Cookies
47
47
  def self.included(base)
@@ -64,43 +64,31 @@ module ActionController #:nodoc:
64
64
 
65
65
  # Returns the value of the cookie by +name+, or +nil+ if no such cookie exists.
66
66
  def [](name)
67
- cookie = @cookies[name.to_s]
68
- if cookie && cookie.respond_to?(:value)
69
- cookie.size > 1 ? cookie.value : cookie.value[0]
70
- end
67
+ super(name.to_s)
71
68
  end
72
69
 
73
70
  # Sets the cookie named +name+. The second argument may be the very cookie
74
71
  # value, or a hash of options as documented above.
75
- def []=(name, options)
72
+ def []=(key, options)
76
73
  if options.is_a?(Hash)
77
- options = options.inject({}) { |options, pair| options[pair.first.to_s] = pair.last; options }
78
- options["name"] = name.to_s
74
+ options.symbolize_keys!
79
75
  else
80
- options = { "name" => name.to_s, "value" => options }
76
+ options = { :value => options }
81
77
  end
82
78
 
83
- set_cookie(options)
79
+ options[:path] = "/" unless options.has_key?(:path)
80
+ super(key.to_s, options[:value])
81
+ @controller.response.set_cookie(key, options)
84
82
  end
85
83
 
86
84
  # Removes the cookie on the client machine by setting the value to an empty string
87
85
  # and setting its expiration date into the past. Like <tt>[]=</tt>, you can pass in
88
86
  # an options hash to delete cookies with extra data such as a <tt>:path</tt>.
89
- def delete(name, options = {})
90
- options.stringify_keys!
91
- set_cookie(options.merge("name" => name.to_s, "value" => "", "expires" => Time.at(0)))
87
+ def delete(key, options = {})
88
+ options.symbolize_keys!
89
+ options[:path] = "/" unless options.has_key?(:path)
90
+ super(key.to_s)
91
+ @controller.response.delete_cookie(key, options)
92
92
  end
93
-
94
- private
95
- # Builds a CGI::Cookie object and adds the cookie to the response headers.
96
- #
97
- # The path of the cookie defaults to "/" if there's none in +options+, and
98
- # everything is passed to the CGI::Cookie constructor.
99
- def set_cookie(options) #:doc:
100
- options["path"] = "/" unless options["path"]
101
- cookie = CGI::Cookie.new(options)
102
- @controller.logger.info "Cookie set: #{cookie}" unless @controller.logger.nil?
103
- @controller.response.headers["cookie"] << cookie
104
- end
105
93
  end
106
94
  end
@@ -2,29 +2,17 @@ module ActionController
2
2
  # Dispatches requests to the appropriate controller and takes care of
3
3
  # reloading the app after each request when Dependencies.load? is true.
4
4
  class Dispatcher
5
- @@guard = Mutex.new
6
-
7
5
  class << self
8
6
  def define_dispatcher_callbacks(cache_classes)
9
7
  unless cache_classes
10
- # Development mode callbacks
11
- before_dispatch :reload_application
12
- after_dispatch :cleanup_application
8
+ unless self.middleware.include?(Reloader)
9
+ self.middleware.insert_after(Failsafe, Reloader)
10
+ end
13
11
 
14
12
  ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
15
13
  end
16
14
 
17
- # Common callbacks
18
- to_prepare :load_application_controller do
19
- begin
20
- require_dependency 'application' unless defined?(::ApplicationController)
21
- rescue LoadError => error
22
- raise unless error.message =~ /application\.rb/
23
- end
24
- end
25
-
26
15
  if defined?(ActiveRecord)
27
- after_dispatch :checkin_connections
28
16
  to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers }
29
17
  end
30
18
 
@@ -35,8 +23,7 @@ module ActionController
35
23
  end
36
24
  end
37
25
 
38
- # Backward-compatible class method takes CGI-specific args. Deprecated
39
- # in favor of Dispatcher.new(output, request, response).dispatch.
26
+ # DEPRECATE: Remove CGI support
40
27
  def dispatch(cgi = nil, session_options = CgiRequest::DEFAULT_SESSION_OPTIONS, output = $stdout)
41
28
  new(output).dispatch_cgi(cgi, session_options)
42
29
  end
@@ -55,143 +42,77 @@ module ActionController
55
42
  @prepare_dispatch_callbacks.replace_or_append!(callback)
56
43
  end
57
44
 
58
- # If the block raises, send status code as a last-ditch response.
59
- def failsafe_response(fallback_output, status, originating_exception = nil)
60
- yield
61
- rescue Exception => exception
62
- begin
63
- log_failsafe_exception(status, originating_exception || exception)
64
- body = failsafe_response_body(status)
65
- fallback_output.write "Status: #{status}\r\nContent-Type: text/html\r\n\r\n#{body}"
66
- nil
67
- rescue Exception => failsafe_error # Logger or IO errors
68
- $stderr.puts "Error during failsafe response: #{failsafe_error}"
69
- $stderr.puts "(originally #{originating_exception})" if originating_exception
45
+ def run_prepare_callbacks
46
+ if defined?(Rails) && Rails.logger
47
+ logger = Rails.logger
48
+ else
49
+ logger = Logger.new($stderr)
70
50
  end
51
+
52
+ new(logger).send :run_callbacks, :prepare_dispatch
71
53
  end
72
54
 
73
- private
74
- def failsafe_response_body(status)
75
- error_path = "#{error_file_path}/#{status.to_s[0..3]}.html"
55
+ def reload_application
56
+ # Run prepare callbacks before every request in development mode
57
+ run_prepare_callbacks
76
58
 
77
- if File.exist?(error_path)
78
- File.read(error_path)
79
- else
80
- "<html><body><h1>#{status}</h1></body></html>"
81
- end
82
- end
83
-
84
- def log_failsafe_exception(status, exception)
85
- message = "/!\\ FAILSAFE /!\\ #{Time.now}\n Status: #{status}\n"
86
- message << " #{exception}\n #{exception.backtrace.join("\n ")}" if exception
87
- failsafe_logger.fatal message
88
- end
59
+ Routing::Routes.reload
60
+ end
89
61
 
90
- def failsafe_logger
91
- if defined?(::RAILS_DEFAULT_LOGGER) && !::RAILS_DEFAULT_LOGGER.nil?
92
- ::RAILS_DEFAULT_LOGGER
93
- else
94
- Logger.new($stderr)
95
- end
96
- end
62
+ def cleanup_application
63
+ # Cleanup the application before processing the current request.
64
+ ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
65
+ ActiveSupport::Dependencies.clear
66
+ ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
67
+ end
97
68
  end
98
69
 
99
- cattr_accessor :error_file_path
100
- self.error_file_path = Rails.public_path if defined?(Rails.public_path)
70
+ cattr_accessor :middleware
71
+ self.middleware = MiddlewareStack.new do |middleware|
72
+ middlewares = File.join(File.dirname(__FILE__), "middlewares.rb")
73
+ middleware.instance_eval(File.read(middlewares))
74
+ end
101
75
 
102
76
  include ActiveSupport::Callbacks
103
77
  define_callbacks :prepare_dispatch, :before_dispatch, :after_dispatch
104
78
 
79
+ # DEPRECATE: Remove arguments, since they are only used by CGI
105
80
  def initialize(output = $stdout, request = nil, response = nil)
106
- @output, @request, @response = output, request, response
81
+ @output = output
82
+ @app = @@middleware.build(lambda { |env| self.dup._call(env) })
107
83
  end
108
84
 
109
- def dispatch_unlocked
85
+ def dispatch
110
86
  begin
111
87
  run_callbacks :before_dispatch
112
- handle_request
88
+ Routing::Routes.call(@env)
113
89
  rescue Exception => exception
114
- failsafe_rescue exception
90
+ if controller ||= (::ApplicationController rescue Base)
91
+ controller.call_with_exception(@env, exception).to_a
92
+ else
93
+ raise exception
94
+ end
115
95
  ensure
116
96
  run_callbacks :after_dispatch, :enumerator => :reverse_each
117
97
  end
118
98
  end
119
99
 
120
- def dispatch
121
- if ActionController::Base.allow_concurrency
122
- dispatch_unlocked
123
- else
124
- @@guard.synchronize do
125
- dispatch_unlocked
126
- end
127
- end
128
- end
129
-
100
+ # DEPRECATE: Remove CGI support
130
101
  def dispatch_cgi(cgi, session_options)
131
- if cgi ||= self.class.failsafe_response(@output, '400 Bad Request') { CGI.new }
132
- @request = CgiRequest.new(cgi, session_options)
133
- @response = CgiResponse.new(cgi)
134
- dispatch
135
- end
136
- rescue Exception => exception
137
- failsafe_rescue exception
102
+ CGIHandler.dispatch_cgi(self, cgi, @output)
138
103
  end
139
104
 
140
105
  def call(env)
141
- @request = RackRequest.new(env)
142
- @response = RackResponse.new(@request)
143
- dispatch
144
- end
145
-
146
- def reload_application
147
- # Run prepare callbacks before every request in development mode
148
- run_callbacks :prepare_dispatch
149
-
150
- Routing::Routes.reload
151
- ActionController::Base.view_paths.reload!
106
+ @app.call(env)
152
107
  end
153
108
 
154
- # Cleanup the application by clearing out loaded classes so they can
155
- # be reloaded on the next request without restarting the server.
156
- def cleanup_application
157
- ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
158
- ActiveSupport::Dependencies.clear
159
- ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
109
+ def _call(env)
110
+ @env = env
111
+ dispatch
160
112
  end
161
113
 
162
114
  def flush_logger
163
115
  Base.logger.flush
164
116
  end
165
-
166
- def mark_as_test_request!
167
- @test_request = true
168
- self
169
- end
170
-
171
- def test_request?
172
- @test_request
173
- end
174
-
175
- def checkin_connections
176
- # Don't return connection (and peform implicit rollback) if this request is a part of integration test
177
- return if test_request?
178
- ActiveRecord::Base.clear_active_connections!
179
- end
180
-
181
- protected
182
- def handle_request
183
- @controller = Routing::Routes.recognize(@request)
184
- @controller.process(@request, @response).out(@output)
185
- end
186
-
187
- def failsafe_rescue(exception)
188
- self.class.failsafe_response(@output, '500 Internal Server Error', exception) do
189
- if @controller ||= defined?(::ApplicationController) ? ::ApplicationController : Base
190
- @controller.process_with_exception(@request, @response, exception).out(@output)
191
- else
192
- raise exception
193
- end
194
- end
195
- end
196
117
  end
197
118
  end
@@ -0,0 +1,52 @@
1
+ module ActionController
2
+ class Failsafe
3
+ cattr_accessor :error_file_path
4
+ self.error_file_path = Rails.public_path if defined?(Rails.public_path)
5
+
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ @app.call(env)
12
+ rescue Exception => exception
13
+ # Reraise exception in test environment
14
+ if env["rack.test"]
15
+ raise exception
16
+ else
17
+ failsafe_response(exception)
18
+ end
19
+ end
20
+
21
+ private
22
+ def failsafe_response(exception)
23
+ log_failsafe_exception(exception)
24
+ [500, {'Content-Type' => 'text/html'}, failsafe_response_body]
25
+ rescue Exception => failsafe_error # Logger or IO errors
26
+ $stderr.puts "Error during failsafe response: #{failsafe_error}"
27
+ end
28
+
29
+ def failsafe_response_body
30
+ error_path = "#{self.class.error_file_path}/500.html"
31
+ if File.exist?(error_path)
32
+ File.read(error_path)
33
+ else
34
+ "<html><body><h1>500 Internal Server Error</h1></body></html>"
35
+ end
36
+ end
37
+
38
+ def log_failsafe_exception(exception)
39
+ message = "/!\\ FAILSAFE /!\\ #{Time.now}\n Status: 500 Internal Server Error\n"
40
+ message << " #{exception}\n #{exception.backtrace.join("\n ")}" if exception
41
+ failsafe_logger.fatal(message)
42
+ end
43
+
44
+ def failsafe_logger
45
+ if defined?(Rails) && Rails.logger
46
+ Rails.logger
47
+ else
48
+ Logger.new($stderr)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -4,20 +4,22 @@ module ActionController #:nodoc:
4
4
  # action that sets <tt>flash[:notice] = "Successfully created"</tt> before redirecting to a display action that can
5
5
  # then expose the flash to its template. Actually, that exposure is automatically done. Example:
6
6
  #
7
- # class WeblogController < ActionController::Base
7
+ # class PostsController < ActionController::Base
8
8
  # def create
9
9
  # # save post
10
10
  # flash[:notice] = "Successfully created post"
11
- # redirect_to :action => "display", :params => { :id => post.id }
11
+ # redirect_to posts_path(@post)
12
12
  # end
13
13
  #
14
- # def display
14
+ # def show
15
15
  # # doesn't need to assign the flash notice to the template, that's done automatically
16
16
  # end
17
17
  # end
18
18
  #
19
- # display.erb
20
- # <% if flash[:notice] %><div class="notice"><%= flash[:notice] %></div><% end %>
19
+ # show.html.erb
20
+ # <% if flash[:notice] %>
21
+ # <div class="notice"><%= flash[:notice] %></div>
22
+ # <% end %>
21
23
  #
22
24
  # This example just places a string in the flash, but you can put any object in there. And of course, you can put as
23
25
  # many as you like at a time too. Just remember: They'll be gone by the time the next action has been performed.
@@ -27,55 +29,54 @@ module ActionController #:nodoc:
27
29
  def self.included(base)
28
30
  base.class_eval do
29
31
  include InstanceMethods
30
- alias_method_chain :assign_shortcuts, :flash
31
- alias_method_chain :reset_session, :flash
32
+ alias_method_chain :perform_action, :flash
33
+ alias_method_chain :reset_session, :flash
32
34
  end
33
35
  end
34
-
35
-
36
+
36
37
  class FlashNow #:nodoc:
37
38
  def initialize(flash)
38
39
  @flash = flash
39
40
  end
40
-
41
+
41
42
  def []=(k, v)
42
43
  @flash[k] = v
43
44
  @flash.discard(k)
44
45
  v
45
46
  end
46
-
47
+
47
48
  def [](k)
48
49
  @flash[k]
49
50
  end
50
51
  end
51
-
52
+
52
53
  class FlashHash < Hash
53
54
  def initialize #:nodoc:
54
55
  super
55
56
  @used = {}
56
57
  end
57
-
58
+
58
59
  def []=(k, v) #:nodoc:
59
60
  keep(k)
60
61
  super
61
62
  end
62
-
63
+
63
64
  def update(h) #:nodoc:
64
65
  h.keys.each { |k| keep(k) }
65
66
  super
66
67
  end
67
-
68
+
68
69
  alias :merge! :update
69
-
70
+
70
71
  def replace(h) #:nodoc:
71
72
  @used = {}
72
73
  super
73
74
  end
74
-
75
+
75
76
  # Sets a flash that will not be available to the next action, only to the current.
76
77
  #
77
78
  # flash.now[:message] = "Hello current action"
78
- #
79
+ #
79
80
  # This method enables you to use the flash as a central messaging system in your app.
80
81
  # When you need to pass an object to the next action, you use the standard flash assign (<tt>[]=</tt>).
81
82
  # When you need to pass an object to the current action, you use <tt>now</tt>, and your object will
@@ -85,7 +86,7 @@ module ActionController #:nodoc:
85
86
  def now
86
87
  FlashNow.new(self)
87
88
  end
88
-
89
+
89
90
  # Keeps either the entire current flash or a specific flash entry available for the next action:
90
91
  #
91
92
  # flash.keep # keeps the entire flash
@@ -93,7 +94,7 @@ module ActionController #:nodoc:
93
94
  def keep(k = nil)
94
95
  use(k, false)
95
96
  end
96
-
97
+
97
98
  # Marks the entire flash or a single flash entry to be discarded by the end of the current action:
98
99
  #
99
100
  # flash.discard # discard the entire flash at the end of the current action
@@ -101,12 +102,12 @@ module ActionController #:nodoc:
101
102
  def discard(k = nil)
102
103
  use(k)
103
104
  end
104
-
105
+
105
106
  # Mark for removal entries that were kept, and delete unkept ones.
106
107
  #
107
108
  # This method is called automatically by filters, so you generally don't need to care about it.
108
109
  def sweep #:nodoc:
109
- keys.each do |k|
110
+ keys.each do |k|
110
111
  unless @used[k]
111
112
  use(k)
112
113
  else
@@ -118,7 +119,7 @@ module ActionController #:nodoc:
118
119
  # clean up after keys that could have been left over by calling reject! or shift on the flash
119
120
  (@used.keys - keys).each{ |k| @used.delete(k) }
120
121
  end
121
-
122
+
122
123
  private
123
124
  # Used internally by the <tt>keep</tt> and <tt>discard</tt> methods
124
125
  # use() # marks the entire flash as used
@@ -136,37 +137,27 @@ module ActionController #:nodoc:
136
137
 
137
138
  module InstanceMethods #:nodoc:
138
139
  protected
140
+ def perform_action_with_flash
141
+ perform_action_without_flash
142
+ remove_instance_variable(:@_flash) if defined? @_flash
143
+ end
144
+
139
145
  def reset_session_with_flash
140
146
  reset_session_without_flash
141
- remove_instance_variable(:@_flash)
142
- flash(:refresh)
147
+ remove_instance_variable(:@_flash) if defined? @_flash
143
148
  end
144
-
145
- # Access the contents of the flash. Use <tt>flash["notice"]</tt> to read a notice you put there or
146
- # <tt>flash["notice"] = "hello"</tt> to put a new one.
147
- # Note that if sessions are disabled only flash.now will work.
148
- def flash(refresh = false) #:doc:
149
- if !defined?(@_flash) || refresh
150
- @_flash =
151
- if session.is_a?(Hash)
152
- # don't put flash in session if disabled
153
- FlashHash.new
154
- else
155
- # otherwise, session is a CGI::Session or a TestSession
156
- # so make sure it gets retrieved from/saved to session storage after request processing
157
- session["flash"] ||= FlashHash.new
158
- end
149
+
150
+ # Access the contents of the flash. Use <tt>flash["notice"]</tt> to
151
+ # read a notice you put there or <tt>flash["notice"] = "hello"</tt>
152
+ # to put a new one.
153
+ def flash #:doc:
154
+ unless defined? @_flash
155
+ @_flash = session["flash"] ||= FlashHash.new
156
+ @_flash.sweep
159
157
  end
160
158
 
161
159
  @_flash
162
160
  end
163
-
164
- private
165
- def assign_shortcuts_with_flash(request, response) #:nodoc:
166
- assign_shortcuts_without_flash(request, response)
167
- flash(:refresh)
168
- flash.sweep if @_session && !component_request?
169
- end
170
161
  end
171
162
  end
172
163
  end