actionpack 1.12.5 → 1.13.0

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 (179) hide show
  1. data/CHANGELOG +517 -15
  2. data/MIT-LICENSE +1 -1
  3. data/README +18 -20
  4. data/Rakefile +7 -4
  5. data/examples/address_book_controller.rb +3 -3
  6. data/examples/blog_controller.cgi +3 -3
  7. data/examples/debate_controller.cgi +5 -5
  8. data/lib/action_controller.rb +2 -2
  9. data/lib/action_controller/assertions.rb +73 -311
  10. data/lib/action_controller/{deprecated_assertions.rb → assertions/deprecated_assertions.rb} +32 -8
  11. data/lib/action_controller/assertions/dom_assertions.rb +25 -0
  12. data/lib/action_controller/assertions/model_assertions.rb +12 -0
  13. data/lib/action_controller/assertions/response_assertions.rb +140 -0
  14. data/lib/action_controller/assertions/routing_assertions.rb +82 -0
  15. data/lib/action_controller/assertions/selector_assertions.rb +571 -0
  16. data/lib/action_controller/assertions/tag_assertions.rb +117 -0
  17. data/lib/action_controller/base.rb +334 -163
  18. data/lib/action_controller/benchmarking.rb +3 -6
  19. data/lib/action_controller/caching.rb +83 -22
  20. data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -7
  21. data/lib/action_controller/cgi_ext/cgi_methods.rb +167 -173
  22. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +43 -22
  23. data/lib/action_controller/cgi_process.rb +50 -27
  24. data/lib/action_controller/components.rb +21 -25
  25. data/lib/action_controller/cookies.rb +10 -9
  26. data/lib/action_controller/{dependencies.rb → deprecated_dependencies.rb} +9 -27
  27. data/lib/action_controller/filters.rb +448 -225
  28. data/lib/action_controller/flash.rb +24 -20
  29. data/lib/action_controller/helpers.rb +2 -5
  30. data/lib/action_controller/integration.rb +40 -16
  31. data/lib/action_controller/layout.rb +11 -8
  32. data/lib/action_controller/macros/auto_complete.rb +3 -2
  33. data/lib/action_controller/macros/in_place_editing.rb +3 -2
  34. data/lib/action_controller/mime_responds.rb +41 -29
  35. data/lib/action_controller/mime_type.rb +68 -10
  36. data/lib/action_controller/pagination.rb +4 -3
  37. data/lib/action_controller/request.rb +22 -14
  38. data/lib/action_controller/rescue.rb +25 -22
  39. data/lib/action_controller/resources.rb +302 -0
  40. data/lib/action_controller/response.rb +20 -2
  41. data/lib/action_controller/response.rb.rej +17 -0
  42. data/lib/action_controller/routing.rb +1165 -567
  43. data/lib/action_controller/scaffolding.rb +30 -31
  44. data/lib/action_controller/session/active_record_store.rb +2 -0
  45. data/lib/action_controller/session/drb_store.rb +4 -0
  46. data/lib/action_controller/session/mem_cache_store.rb +4 -0
  47. data/lib/action_controller/session_management.rb +6 -9
  48. data/lib/action_controller/status_codes.rb +89 -0
  49. data/lib/action_controller/streaming.rb +6 -15
  50. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +5 -5
  51. data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -2
  52. data/lib/action_controller/templates/rescues/routing_error.rhtml +4 -4
  53. data/lib/action_controller/templates/rescues/template_error.rhtml +1 -1
  54. data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
  55. data/lib/action_controller/test_process.rb +52 -30
  56. data/lib/action_controller/url_rewriter.rb +63 -29
  57. data/lib/action_controller/vendor/html-scanner/html/document.rb +1 -0
  58. data/lib/action_controller/vendor/html-scanner/html/node.rb +3 -4
  59. data/lib/action_controller/vendor/html-scanner/html/selector.rb +822 -0
  60. data/lib/action_controller/verification.rb +22 -11
  61. data/lib/action_pack.rb +1 -1
  62. data/lib/action_pack/version.rb +2 -2
  63. data/lib/action_view.rb +1 -1
  64. data/lib/action_view/base.rb +46 -43
  65. data/lib/action_view/compiled_templates.rb +1 -1
  66. data/lib/action_view/helpers/active_record_helper.rb +54 -17
  67. data/lib/action_view/helpers/asset_tag_helper.rb +97 -46
  68. data/lib/action_view/helpers/capture_helper.rb +1 -1
  69. data/lib/action_view/helpers/date_helper.rb +258 -136
  70. data/lib/action_view/helpers/debug_helper.rb +1 -1
  71. data/lib/action_view/helpers/deprecated_helper.rb +34 -0
  72. data/lib/action_view/helpers/form_helper.rb +75 -35
  73. data/lib/action_view/helpers/form_options_helper.rb +7 -5
  74. data/lib/action_view/helpers/form_tag_helper.rb +44 -6
  75. data/lib/action_view/helpers/java_script_macros_helper.rb +59 -46
  76. data/lib/action_view/helpers/javascript_helper.rb +71 -10
  77. data/lib/action_view/helpers/javascripts/controls.js +41 -23
  78. data/lib/action_view/helpers/javascripts/dragdrop.js +105 -76
  79. data/lib/action_view/helpers/javascripts/effects.js +293 -163
  80. data/lib/action_view/helpers/javascripts/prototype.js +897 -389
  81. data/lib/action_view/helpers/javascripts/prototype.js.rej +561 -0
  82. data/lib/action_view/helpers/number_helper.rb +111 -65
  83. data/lib/action_view/helpers/prototype_helper.rb +84 -109
  84. data/lib/action_view/helpers/scriptaculous_helper.rb +5 -0
  85. data/lib/action_view/helpers/tag_helper.rb +69 -16
  86. data/lib/action_view/helpers/text_helper.rb +149 -112
  87. data/lib/action_view/helpers/url_helper.rb +200 -107
  88. data/lib/action_view/template_error.rb +66 -42
  89. data/test/abstract_unit.rb +4 -2
  90. data/test/active_record_unit.rb +84 -56
  91. data/test/activerecord/active_record_assertions_test.rb +26 -18
  92. data/test/activerecord/active_record_store_test.rb +4 -36
  93. data/test/activerecord/pagination_test.rb +1 -6
  94. data/test/controller/action_pack_assertions_test.rb +230 -113
  95. data/test/controller/addresses_render_test.rb +2 -6
  96. data/test/controller/assert_select_test.rb +576 -0
  97. data/test/controller/base_test.rb +73 -3
  98. data/test/controller/caching_test.rb +228 -0
  99. data/test/controller/capture_test.rb +12 -10
  100. data/test/controller/cgi_test.rb +89 -12
  101. data/test/controller/components_test.rb +24 -2
  102. data/test/controller/content_type_test.rb +139 -0
  103. data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
  104. data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
  105. data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
  106. data/test/controller/cookie_test.rb +33 -25
  107. data/test/controller/deprecated_instance_variables_test.rb +48 -0
  108. data/test/controller/deprecation/deprecated_base_methods_test.rb +60 -0
  109. data/test/controller/fake_controllers.rb +0 -1
  110. data/test/controller/filters_test.rb +301 -16
  111. data/test/controller/flash_test.rb +19 -2
  112. data/test/controller/helper_test.rb +2 -2
  113. data/test/controller/integration_test.rb +154 -0
  114. data/test/controller/layout_test.rb +115 -1
  115. data/test/controller/mime_responds_test.rb +94 -0
  116. data/test/controller/mime_type_test.rb +9 -0
  117. data/test/controller/new_render_test.rb +161 -11
  118. data/test/controller/raw_post_test.rb +52 -15
  119. data/test/controller/redirect_test.rb +27 -14
  120. data/test/controller/render_test.rb +76 -29
  121. data/test/controller/request_test.rb +55 -4
  122. data/test/controller/resources_test.rb +274 -0
  123. data/test/controller/routing_test.rb +1533 -824
  124. data/test/controller/selector_test.rb +628 -0
  125. data/test/controller/send_file_test.rb +9 -1
  126. data/test/controller/session_management_test.rb +51 -0
  127. data/test/controller/test_test.rb +113 -29
  128. data/test/controller/url_rewriter_test.rb +86 -17
  129. data/test/controller/verification_test.rb +19 -17
  130. data/test/controller/webservice_test.rb +0 -7
  131. data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
  132. data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
  133. data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
  134. data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
  135. data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +1 -0
  136. data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +1 -0
  137. data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +1 -0
  138. data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +1 -0
  139. data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +1 -0
  140. data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +1 -0
  141. data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +1 -0
  142. data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +1 -0
  143. data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +1 -0
  144. data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +1 -0
  145. data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +1 -0
  146. data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +1 -0
  147. data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +1 -0
  148. data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +1 -0
  149. data/test/fixtures/multipart/binary_file +0 -0
  150. data/test/fixtures/public/javascripts/application.js +1 -0
  151. data/test/fixtures/test/_hello.rxml +1 -0
  152. data/test/fixtures/test/hello_world_container.rxml +3 -0
  153. data/test/fixtures/topic.rb +2 -2
  154. data/test/template/active_record_helper_test.rb +83 -12
  155. data/test/template/asset_tag_helper_test.rb +75 -95
  156. data/test/template/compiled_templates_test.rb +1 -0
  157. data/test/template/date_helper_test.rb +873 -181
  158. data/test/template/deprecated_helper_test.rb +36 -0
  159. data/test/template/deprecated_instance_variables_test.rb +43 -0
  160. data/test/template/form_helper_test.rb +77 -1
  161. data/test/template/form_options_helper_test.rb +4 -0
  162. data/test/template/form_tag_helper_test.rb +66 -2
  163. data/test/template/java_script_macros_helper_test.rb +4 -1
  164. data/test/template/javascript_helper_test.rb +29 -0
  165. data/test/template/number_helper_test.rb +63 -27
  166. data/test/template/prototype_helper_test.rb +77 -34
  167. data/test/template/tag_helper_test.rb +34 -6
  168. data/test/template/text_helper_test.rb +69 -34
  169. data/test/template/url_helper_test.rb +168 -16
  170. data/test/testing_sandbox.rb +7 -22
  171. metadata +66 -20
  172. data/filler.txt +0 -50
  173. data/lib/action_controller/code_generation.rb +0 -235
  174. data/lib/action_controller/vendor/xml_simple.rb +0 -1019
  175. data/test/controller/caching_filestore.rb +0 -74
  176. data/test/fixtures/application_root/app/controllers/a_class_that_contains_a_controller/poorly_placed_controller.rb +0 -7
  177. data/test/fixtures/application_root/app/controllers/module_that_holds_controllers/nested_controller.rb +0 -3
  178. data/test/fixtures/application_root/app/models/a_class_that_contains_a_controller.rb +0 -7
  179. data/test/fixtures/dont_load.rb +0 -3
@@ -1,27 +1,48 @@
1
1
  class CGI #:nodoc:
2
- # Add @request.env['RAW_POST_DATA'] for the vegans.
3
2
  module QueryExtension
4
3
  # Initialize the data from the query.
5
4
  #
6
5
  # Handles multipart forms (in particular, forms that involve file uploads).
7
6
  # Reads query parameters in the @params field, and cookies into @cookies.
8
- def initialize_query()
7
+ def initialize_query
9
8
  @cookies = CGI::Cookie::parse(env_table['HTTP_COOKIE'] || env_table['COOKIE'])
10
9
 
11
- #fix some strange request environments
10
+ # Fix some strange request environments.
12
11
  if method = env_table['REQUEST_METHOD']
13
12
  method = method.to_s.downcase.intern
14
13
  else
15
14
  method = :get
16
15
  end
17
16
 
18
- if method == :post && (boundary = multipart_form_boundary)
19
- @multipart = true
20
- @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
21
- else
22
- @multipart = false
23
- @params = CGI::parse(read_query_params(method) || "")
17
+ # POST assumes missing Content-Type is application/x-www-form-urlencoded.
18
+ content_type = env_table['CONTENT_TYPE']
19
+ if content_type.blank? && method == :post
20
+ content_type = 'application/x-www-form-urlencoded'
24
21
  end
22
+
23
+ # Force content length to zero if missing.
24
+ content_length = env_table['CONTENT_LENGTH'].to_i
25
+
26
+ # Set multipart to false by default.
27
+ @multipart = false
28
+
29
+ # POST and PUT may have params in entity body. If content type is
30
+ # missing for POST, assume urlencoded. If content type is missing
31
+ # for PUT, don't assume anything and don't parse the parameters:
32
+ # it's likely binary data.
33
+ #
34
+ # The other HTTP methods have their params in the query string.
35
+ if method == :post || method == :put
36
+ if boundary = extract_multipart_form_boundary(content_type)
37
+ @multipart = true
38
+ @params = read_multipart(boundary, content_length)
39
+ elsif content_type.blank? || content_type !~ %r{application/x-www-form-urlencoded}i
40
+ read_params(method, content_length)
41
+ @params = {}
42
+ end
43
+ end
44
+
45
+ @params ||= CGI.parse(read_params(method, content_length))
25
46
  end
26
47
 
27
48
  private
@@ -29,16 +50,16 @@ class CGI #:nodoc:
29
50
  MULTIPART_FORM_BOUNDARY_RE = %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n #"
30
51
  end
31
52
 
32
- def multipart_form_boundary
33
- MULTIPART_FORM_BOUNDARY_RE.match(env_table['CONTENT_TYPE']).to_a.pop
53
+ def extract_multipart_form_boundary(content_type)
54
+ MULTIPART_FORM_BOUNDARY_RE.match(content_type).to_a.pop
34
55
  end
35
56
 
36
57
  if defined? MOD_RUBY
37
- def read_params_from_query
58
+ def read_query
38
59
  Apache::request.args || ''
39
60
  end
40
61
  else
41
- def read_params_from_query
62
+ def read_query
42
63
  # fixes CGI querystring parsing for lighttpd
43
64
  env_qs = env_table['QUERY_STRING']
44
65
  if env_qs.blank? && !(uri = env_table['REQUEST_URI']).blank?
@@ -49,25 +70,25 @@ class CGI #:nodoc:
49
70
  end
50
71
  end
51
72
 
52
- def read_params_from_post
73
+ def read_body(content_length)
53
74
  stdinput.binmode if stdinput.respond_to?(:binmode)
54
- content = stdinput.read(Integer(env_table['CONTENT_LENGTH'])) || ''
55
- # fix for Safari Ajax postings that always append \000
75
+ content = stdinput.read(content_length) || ''
76
+ # Fix for Safari Ajax postings that always append \000
56
77
  content.chop! if content[-1] == 0
57
- content.gsub! /&_=$/, ''
78
+ content.gsub!(/&_=$/, '')
58
79
  env_table['RAW_POST_DATA'] = content.freeze
59
80
  end
60
81
 
61
- def read_query_params(method)
82
+ def read_params(method, content_length)
62
83
  case method
63
84
  when :get
64
- read_params_from_query
85
+ read_query
65
86
  when :post, :put
66
- read_params_from_post
87
+ read_body(content_length)
67
88
  when :cmd
68
89
  read_from_cmdline
69
- else # when :head, :delete, :options
70
- read_params_from_query
90
+ else # :head, :delete, :options, :trace, :connect
91
+ read_query
71
92
  end
72
93
  end
73
94
  end # module QueryExtension
@@ -8,13 +8,13 @@ module ActionController #:nodoc:
8
8
  # sessions (large performance increase if sessions are not needed). The <tt>session_options</tt> are the same as for CGI::Session:
9
9
  #
10
10
  # * <tt>:database_manager</tt> - standard options are CGI::Session::FileStore, CGI::Session::MemoryStore, and CGI::Session::PStore
11
- # (default). Additionally, there is CGI::Session::DRbStore and CGI::Session::ActiveRecordStore. Read more about these in
11
+ # (default). Additionally, there is CGI::Session::DRbStore and CGI::Session::ActiveRecordStore. Read more about these in
12
12
  # lib/action_controller/session.
13
13
  # * <tt>:session_key</tt> - the parameter name used for the session id. Defaults to '_session_id'.
14
14
  # * <tt>:session_id</tt> - the session id to use. If not provided, then it is retrieved from the +session_key+ parameter
15
15
  # of the request, or automatically generated for a new session.
16
16
  # * <tt>:new_session</tt> - if true, force creation of a new session. If not set, a new session is only created if none currently
17
- # exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set,
17
+ # exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set,
18
18
  # an ArgumentError is raised.
19
19
  # * <tt>:session_expires</tt> - the time the current session expires, as a +Time+ object. If not set, the session will continue
20
20
  # indefinitely.
@@ -22,10 +22,10 @@ module ActionController #:nodoc:
22
22
  # server.
23
23
  # * <tt>:session_secure</tt> - if +true+, this session will only work over HTTPS.
24
24
  # * <tt>:session_path</tt> - the path for which this session applies. Defaults to the directory of the CGI script.
25
- def self.process_cgi(cgi = CGI.new, session_options = {})
25
+ def self.process_cgi(cgi = CGI.new, session_options = {})
26
26
  new.process_cgi(cgi, session_options)
27
27
  end
28
-
28
+
29
29
  def process_cgi(cgi, session_options = {}) #:nodoc:
30
30
  process(CgiRequest.new(cgi, session_options), CgiResponse.new(cgi)).out
31
31
  end
@@ -51,7 +51,7 @@ module ActionController #:nodoc:
51
51
  if (qs = @cgi.query_string) && !qs.empty?
52
52
  qs
53
53
  elsif uri = @env['REQUEST_URI']
54
- parts = uri.split('?')
54
+ parts = uri.split('?')
55
55
  parts.shift
56
56
  parts.join('?')
57
57
  else
@@ -60,7 +60,8 @@ module ActionController #:nodoc:
60
60
  end
61
61
 
62
62
  def query_parameters
63
- (qs = self.query_string).empty? ? {} : CGIMethods.parse_query_parameters(qs)
63
+ @query_parameters ||=
64
+ (qs = self.query_string).empty? ? {} : CGIMethods.parse_query_parameters(qs)
64
65
  end
65
66
 
66
67
  def request_parameters
@@ -71,7 +72,7 @@ module ActionController #:nodoc:
71
72
  CGIMethods.parse_request_parameters(@cgi.params)
72
73
  end
73
74
  end
74
-
75
+
75
76
  def cookies
76
77
  @cgi.cookies.freeze
77
78
  end
@@ -101,15 +102,26 @@ module ActionController #:nodoc:
101
102
  end
102
103
 
103
104
  def session
104
- unless @session
105
+ unless defined?(@session)
105
106
  if @session_options == false
106
107
  @session = Hash.new
107
108
  else
108
109
  stale_session_check! do
109
- if session_options_with_string_keys['new_session'] == true
110
- @session = new_session
111
- else
112
- @session = CGI::Session.new(@cgi, session_options_with_string_keys)
110
+ case value = session_options_with_string_keys['new_session']
111
+ when true
112
+ @session = new_session
113
+ when false
114
+ begin
115
+ @session = CGI::Session.new(@cgi, session_options_with_string_keys)
116
+ # CGI::Session raises ArgumentError if 'new_session' == false
117
+ # and no session cookie or query param is present.
118
+ rescue ArgumentError
119
+ @session = Hash.new
120
+ end
121
+ when nil
122
+ @session = CGI::Session.new(@cgi, session_options_with_string_keys)
123
+ else
124
+ raise ArgumentError, "Invalid new_session option: #{value}"
113
125
  end
114
126
  @session['__valid_session']
115
127
  end
@@ -119,7 +131,7 @@ module ActionController #:nodoc:
119
131
  end
120
132
 
121
133
  def reset_session
122
- @session.delete if CGI::Session === @session
134
+ @session.delete if defined?(@session) && @session.is_a?(CGI::Session)
123
135
  @session = new_session
124
136
  end
125
137
 
@@ -141,11 +153,11 @@ module ActionController #:nodoc:
141
153
  def stale_session_check!
142
154
  yield
143
155
  rescue ArgumentError => argument_error
144
- if argument_error.message =~ %r{undefined class/module (\w+)}
156
+ if argument_error.message =~ %r{undefined class/module ([\w:]+)}
145
157
  begin
146
158
  Module.const_missing($1)
147
159
  rescue LoadError, NameError => const_error
148
- raise ActionController::SessionRestoreError, <<end_msg
160
+ raise ActionController::SessionRestoreError, <<-end_msg
149
161
  Session contains objects whose class definition isn\'t available.
150
162
  Remember to require the classes for all objects kept in the session.
151
163
  (Original exception: #{const_error.message} [#{const_error.class}])
@@ -159,7 +171,7 @@ end_msg
159
171
  end
160
172
 
161
173
  def session_options_with_string_keys
162
- @session_options_with_string_keys ||= DEFAULT_SESSION_OPTIONS.merge(@session_options).inject({}) { |options, (k,v)| options[k.to_s] = v; options }
174
+ @session_options_with_string_keys ||= DEFAULT_SESSION_OPTIONS.merge(@session_options).stringify_keys
163
175
  end
164
176
  end
165
177
 
@@ -170,38 +182,49 @@ end_msg
170
182
  end
171
183
 
172
184
  def out(output = $stdout)
173
- convert_content_type!(@headers)
185
+ convert_content_type!
186
+ set_content_length!
187
+
174
188
  output.binmode if output.respond_to?(:binmode)
175
189
  output.sync = false if output.respond_to?(:sync=)
176
-
190
+
177
191
  begin
178
192
  output.write(@cgi.header(@headers))
179
193
 
180
194
  if @cgi.send(:env_table)['REQUEST_METHOD'] == 'HEAD'
181
195
  return
182
196
  elsif @body.respond_to?(:call)
197
+ # Flush the output now in case the @body Proc uses
198
+ # #syswrite.
199
+ output.flush if output.respond_to?(:flush)
183
200
  @body.call(self, output)
184
201
  else
185
202
  output.write(@body)
186
203
  end
187
204
 
188
205
  output.flush if output.respond_to?(:flush)
189
- rescue Errno::EPIPE => e
190
- # lost connection to the FCGI process -- ignore the output, then
206
+ rescue Errno::EPIPE, Errno::ECONNRESET
207
+ # lost connection to parent process, ignore output
191
208
  end
192
209
  end
193
210
 
194
211
  private
195
- def convert_content_type!(headers)
196
- if header = headers.delete("Content-Type")
197
- headers["type"] = header
212
+ def convert_content_type!
213
+ if content_type = @headers.delete("Content-Type")
214
+ @headers["type"] = content_type
198
215
  end
199
- if header = headers.delete("Content-type")
200
- headers["type"] = header
216
+ if content_type = @headers.delete("Content-type")
217
+ @headers["type"] = content_type
201
218
  end
202
- if header = headers.delete("content-type")
203
- headers["type"] = header
219
+ if content_type = @headers.delete("content-type")
220
+ @headers["type"] = content_type
204
221
  end
205
222
  end
223
+
224
+ # Don't set the Content-Length for block-based bodies as that would mean reading it all into memory. Not nice
225
+ # for, say, a 2GB streaming file.
226
+ def set_content_length!
227
+ @headers["Content-Length"] = @body.size unless @body.respond_to?(:call)
228
+ end
206
229
  end
207
230
  end
@@ -50,14 +50,9 @@ module ActionController #:nodoc:
50
50
  base.send :attr_accessor, :parent_controller
51
51
 
52
52
  base.class_eval do
53
- alias_method :process_cleanup_without_components, :process_cleanup
54
- alias_method :process_cleanup, :process_cleanup_with_components
55
-
56
- alias_method :set_session_options_without_components, :set_session_options
57
- alias_method :set_session_options, :set_session_options_with_components
58
-
59
- alias_method :flash_without_components, :flash
60
- alias_method :flash, :flash_with_components
53
+ alias_method_chain :process_cleanup, :components
54
+ alias_method_chain :set_session_options, :components
55
+ alias_method_chain :flash, :components
61
56
 
62
57
  alias_method :component_request?, :parent_controller
63
58
  end
@@ -80,11 +75,13 @@ module ActionController #:nodoc:
80
75
  # will also use /code/weblog/components as template root
81
76
  # and find templates in /code/weblog/components/admin/parties/users/
82
77
  def uses_component_template_root
83
- path_of_calling_controller = File.dirname(caller[0].split(/:\d+:/).first)
84
- path_of_controller_root = path_of_calling_controller.sub(/#{controller_path.split("/")[0..-2]}$/, "") # " (for ruby-mode)
78
+ path_of_calling_controller = File.dirname(caller[1].split(/:\d+:/, 2).first)
79
+ path_of_controller_root = path_of_calling_controller.sub(/#{Regexp.escape(File.dirname(controller_path))}$/, "")
85
80
 
86
81
  self.template_root = path_of_controller_root
87
82
  end
83
+
84
+ deprecate :uses_component_template_root => 'Components are deprecated and will be removed in Rails 2.0.'
88
85
  end
89
86
 
90
87
  module InstanceMethods
@@ -116,27 +113,26 @@ module ActionController #:nodoc:
116
113
  end
117
114
 
118
115
  def flash_with_components(refresh = false) #:nodoc:
119
- if @flash.nil? || refresh
120
- @flash =
121
- if @parent_controller
116
+ if !defined?(@_flash) || refresh
117
+ @_flash =
118
+ if defined?(@parent_controller)
122
119
  @parent_controller.flash
123
120
  else
124
121
  flash_without_components
125
122
  end
126
123
  end
127
-
128
- @flash
124
+ @_flash
129
125
  end
130
126
 
131
127
  private
132
128
  def component_response(options, reuse_response)
133
129
  klass = component_class(options)
134
130
  request = request_for_component(klass.controller_name, options)
135
- response = reuse_response ? @response : @response.dup
131
+ new_response = reuse_response ? response : response.dup
136
132
 
137
- klass.process_with_components(request, response, self)
133
+ klass.process_with_components(request, new_response, self)
138
134
  end
139
-
135
+
140
136
  # determine the controller class for the component request
141
137
  def component_class(options)
142
138
  if controller = options[:controller]
@@ -145,22 +141,22 @@ module ActionController #:nodoc:
145
141
  self.class
146
142
  end
147
143
  end
148
-
144
+
149
145
  # Create a new request object based on the current request.
150
146
  # The new request inherits the session from the current request,
151
147
  # bypassing any session options set for the component controller's class
152
148
  def request_for_component(controller_name, options)
153
- request = @request.dup
154
- request.session = @request.session
155
-
156
- request.instance_variable_set(
149
+ new_request = request.dup
150
+ new_request.session = request.session
151
+
152
+ new_request.instance_variable_set(
157
153
  :@parameters,
158
154
  (options[:params] || {}).with_indifferent_access.update(
159
155
  "controller" => controller_name, "action" => options[:action], "id" => options[:id]
160
156
  )
161
157
  )
162
-
163
- request
158
+
159
+ new_request
164
160
  end
165
161
 
166
162
  def component_logging(options)
@@ -4,13 +4,14 @@ module ActionController #:nodoc:
4
4
  # itself back -- just the value it holds). Examples for writing:
5
5
  #
6
6
  # cookies[:user_name] = "david" # => Will set a simple session cookie
7
- # cookies[:login] = { :value => "XJ-122", :expires => Time.now + 360} # => Will set a cookie that expires in 1 hour
8
- #
7
+ # cookies[:login] = { :value => "XJ-122", :expires => 1.hour.from_now }
8
+ # # => Will set a cookie that expires in 1 hour
9
+ #
9
10
  # Examples for reading:
10
11
  #
11
12
  # cookies[:user_name] # => "david"
12
13
  # cookies.size # => 2
13
- #
14
+ #
14
15
  # Example for deleting:
15
16
  #
16
17
  # cookies.delete :user_name
@@ -32,13 +33,13 @@ module ActionController #:nodoc:
32
33
 
33
34
  # Deprecated cookie writer method
34
35
  def cookie(*options)
35
- @response.headers["cookie"] << CGI::Cookie.new(*options)
36
+ response.headers['cookie'] << CGI::Cookie.new(*options)
36
37
  end
37
38
  end
38
-
39
+
39
40
  class CookieJar < Hash #:nodoc:
40
41
  def initialize(controller)
41
- @controller, @cookies = controller, controller.instance_variable_get("@cookies")
42
+ @controller, @cookies = controller, controller.request.cookies
42
43
  super()
43
44
  update(@cookies)
44
45
  end
@@ -48,7 +49,7 @@ module ActionController #:nodoc:
48
49
  def [](name)
49
50
  @cookies[name.to_s].value.first if @cookies[name.to_s] && @cookies[name.to_s].respond_to?(:value)
50
51
  end
51
-
52
+
52
53
  def []=(name, options)
53
54
  if options.is_a?(Hash)
54
55
  options = options.inject({}) { |options, pair| options[pair.first.to_s] = pair.last; options }
@@ -56,10 +57,10 @@ module ActionController #:nodoc:
56
57
  else
57
58
  options = { "name" => name.to_s, "value" => options }
58
59
  end
59
-
60
+
60
61
  set_cookie(options)
61
62
  end
62
-
63
+
63
64
  # Removes the cookie on the client machine by setting the value to an empty string
64
65
  # and setting its expiration date into the past
65
66
  def delete(name)
@@ -1,33 +1,10 @@
1
1
  module ActionController #:nodoc:
2
2
  module Dependencies #:nodoc:
3
- def self.append_features(base)
4
- super
3
+ def self.included(base)
5
4
  base.extend(ClassMethods)
6
5
  end
7
6
 
8
- # Dependencies control what classes are needed for the controller to run its course. This is an alternative to doing explicit
9
- # +require+ statements that bring a number of benefits. It's more succinct, communicates what type of dependency we're talking about,
10
- # can trigger special behavior (as in the case of +observer+), and enables Rails to be clever about reloading in cached environments
11
- # like FCGI. Example:
12
- #
13
- # class ApplicationController < ActionController::Base
14
- # model :account, :company, :person, :project, :category
15
- # helper :access_control
16
- # service :notifications, :billings
17
- # observer :project_change_observer
18
- # end
19
- #
20
- # Please note that a controller like ApplicationController will automatically attempt to require_dependency on a model of its
21
- # singuralized name and a helper of its name. If nothing is found, no error is raised. This is especially useful for concrete
22
- # controllers like PostController:
23
- #
24
- # class PostController < ApplicationController
25
- # # model :post (already required)
26
- # # helper :post (already required)
27
- # end
28
- #
29
- # Also note, that if the models follow the pattern of just 1 class per file in the form of MyClass => my_class.rb, then these
30
- # classes don't have to be required as Active Support will auto-require them.
7
+ # Deprecated module. The responsibility of loading dependencies belong with Active Support now.
31
8
  module ClassMethods #:nodoc:
32
9
  # Specifies a variable number of models that this controller depends on. Models are normally Active Record classes or a similar
33
10
  # backend for modelling entity classes.
@@ -35,6 +12,7 @@ module ActionController #:nodoc:
35
12
  require_dependencies(:model, models)
36
13
  depend_on(:model, models)
37
14
  end
15
+ deprecate :model
38
16
 
39
17
  # Specifies a variable number of services that this controller depends on. Services are normally singletons or factories, like
40
18
  # Action Mailer service or a Payment Gateway service.
@@ -42,6 +20,7 @@ module ActionController #:nodoc:
42
20
  require_dependencies(:service, services)
43
21
  depend_on(:service, services)
44
22
  end
23
+ deprecate :service
45
24
 
46
25
  # Specifies a variable number of observers that are to govern when this controller is handling actions. The observers will
47
26
  # automatically have .instance called on them to make them active on assignment.
@@ -50,16 +29,19 @@ module ActionController #:nodoc:
50
29
  depend_on(:observer, observers)
51
30
  instantiate_observers(observers)
52
31
  end
32
+ deprecate :observer
53
33
 
54
34
  # Returns an array of symbols that specify the dependencies on a given layer. For the example at the top, calling
55
35
  # <tt>ApplicationController.dependencies_on(:model)</tt> would return <tt>[:account, :company, :person, :project, :category]</tt>
56
36
  def dependencies_on(layer)
57
37
  read_inheritable_attribute("#{layer}_dependencies")
58
38
  end
59
-
39
+ deprecate :dependencies_on
40
+
60
41
  def depend_on(layer, dependencies) #:nodoc:
61
42
  write_inheritable_array("#{layer}_dependencies", dependencies)
62
43
  end
44
+ deprecate :depend_on
63
45
 
64
46
  private
65
47
  def instantiate_observers(observers)
@@ -72,7 +54,7 @@ module ActionController #:nodoc:
72
54
  require_dependency(dependency.to_s)
73
55
  rescue LoadError => e
74
56
  raise LoadError.new("Missing #{layer} #{dependency}.rb").copy_blame!(e)
75
- rescue Object => exception
57
+ rescue Exception => exception # error from loaded file
76
58
  exception.blame_file! "=> #{layer} #{dependency}.rb"
77
59
  raise
78
60
  end