actionpack 2.1.2 → 2.2.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 (200) hide show
  1. data/CHANGELOG +223 -7
  2. data/README +6 -12
  3. data/Rakefile +11 -11
  4. data/lib/action_controller.rb +9 -9
  5. data/lib/action_controller/assertions/response_assertions.rb +29 -78
  6. data/lib/action_controller/assertions/routing_assertions.rb +33 -33
  7. data/lib/action_controller/assertions/selector_assertions.rb +9 -5
  8. data/lib/action_controller/base.rb +227 -161
  9. data/lib/action_controller/benchmarking.rb +37 -24
  10. data/lib/action_controller/caching/actions.rb +53 -21
  11. data/lib/action_controller/caching/fragments.rb +10 -36
  12. data/lib/action_controller/caching/sweeping.rb +3 -3
  13. data/lib/action_controller/cgi_ext/session.rb +2 -22
  14. data/lib/action_controller/cgi_process.rb +8 -46
  15. data/lib/action_controller/components.rb +4 -1
  16. data/lib/action_controller/cookies.rb +10 -0
  17. data/lib/action_controller/dispatcher.rb +49 -15
  18. data/lib/action_controller/filters.rb +48 -10
  19. data/lib/action_controller/headers.rb +16 -14
  20. data/lib/action_controller/helpers.rb +2 -2
  21. data/lib/action_controller/http_authentication.rb +1 -1
  22. data/lib/action_controller/integration.rb +57 -60
  23. data/lib/action_controller/layout.rb +27 -53
  24. data/lib/action_controller/mime_responds.rb +5 -1
  25. data/lib/action_controller/mime_type.rb +64 -42
  26. data/lib/action_controller/mime_types.rb +2 -1
  27. data/lib/action_controller/performance_test.rb +16 -0
  28. data/lib/action_controller/polymorphic_routes.rb +16 -9
  29. data/lib/action_controller/rack_process.rb +303 -0
  30. data/lib/action_controller/request.rb +205 -97
  31. data/lib/action_controller/request_forgery_protection.rb +2 -2
  32. data/lib/action_controller/request_profiler.rb +0 -0
  33. data/lib/action_controller/rescue.rb +20 -115
  34. data/lib/action_controller/resources.rb +186 -83
  35. data/lib/action_controller/response.rb +140 -26
  36. data/lib/action_controller/routing.rb +28 -30
  37. data/lib/action_controller/routing/builder.rb +45 -54
  38. data/lib/action_controller/routing/optimisations.rb +31 -21
  39. data/lib/action_controller/routing/recognition_optimisation.rb +33 -27
  40. data/lib/action_controller/routing/route.rb +162 -147
  41. data/lib/action_controller/routing/route_set.rb +8 -7
  42. data/lib/action_controller/routing/routing_ext.rb +4 -1
  43. data/lib/action_controller/routing/segments.rb +50 -21
  44. data/lib/action_controller/session/cookie_store.rb +3 -2
  45. data/lib/action_controller/session/drb_server.rb +7 -7
  46. data/lib/action_controller/session_management.rb +6 -2
  47. data/lib/action_controller/streaming.rb +15 -8
  48. data/lib/action_controller/templates/rescues/diagnostics.erb +2 -2
  49. data/lib/action_controller/templates/rescues/template_error.erb +2 -2
  50. data/lib/action_controller/test_case.rb +66 -2
  51. data/lib/action_controller/test_process.rb +71 -66
  52. data/lib/action_controller/translation.rb +13 -0
  53. data/lib/action_controller/url_rewriter.rb +90 -13
  54. data/lib/action_controller/vendor/html-scanner/html/node.rb +9 -2
  55. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +1 -1
  56. data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -2
  57. data/lib/action_controller/verification.rb +2 -2
  58. data/lib/action_pack/version.rb +1 -1
  59. data/lib/action_view.rb +19 -11
  60. data/lib/action_view/base.rb +184 -150
  61. data/lib/action_view/helpers.rb +38 -0
  62. data/lib/action_view/helpers/active_record_helper.rb +56 -27
  63. data/lib/action_view/helpers/asset_tag_helper.rb +356 -153
  64. data/lib/action_view/helpers/atom_feed_helper.rb +74 -19
  65. data/lib/action_view/helpers/benchmark_helper.rb +3 -3
  66. data/lib/action_view/helpers/cache_helper.rb +1 -2
  67. data/lib/action_view/helpers/capture_helper.rb +19 -44
  68. data/lib/action_view/helpers/date_helper.rb +486 -296
  69. data/lib/action_view/helpers/debug_helper.rb +20 -13
  70. data/lib/action_view/helpers/form_helper.rb +71 -30
  71. data/lib/action_view/helpers/form_options_helper.rb +15 -85
  72. data/lib/action_view/helpers/form_tag_helper.rb +61 -38
  73. data/lib/action_view/helpers/javascript_helper.rb +80 -89
  74. data/lib/action_view/helpers/number_helper.rb +179 -74
  75. data/lib/action_view/helpers/prototype_helper.rb +216 -201
  76. data/lib/action_view/helpers/record_tag_helper.rb +4 -5
  77. data/lib/action_view/helpers/sanitize_helper.rb +65 -33
  78. data/lib/action_view/helpers/scriptaculous_helper.rb +2 -2
  79. data/lib/action_view/helpers/tag_helper.rb +39 -22
  80. data/lib/action_view/helpers/text_helper.rb +212 -118
  81. data/lib/action_view/helpers/translation_helper.rb +21 -0
  82. data/lib/action_view/helpers/url_helper.rb +100 -58
  83. data/lib/action_view/inline_template.rb +13 -14
  84. data/lib/action_view/locale/en.yml +91 -0
  85. data/lib/action_view/partials.rb +100 -55
  86. data/lib/action_view/paths.rb +125 -0
  87. data/lib/action_view/renderable.rb +102 -0
  88. data/lib/action_view/renderable_partial.rb +48 -0
  89. data/lib/action_view/template.rb +90 -101
  90. data/lib/action_view/template_error.rb +11 -21
  91. data/lib/action_view/template_handler.rb +8 -28
  92. data/lib/action_view/template_handlers.rb +45 -0
  93. data/lib/action_view/template_handlers/builder.rb +5 -15
  94. data/lib/action_view/template_handlers/erb.rb +9 -6
  95. data/lib/action_view/template_handlers/rjs.rb +2 -17
  96. data/lib/action_view/test_case.rb +7 -4
  97. data/test/abstract_unit.rb +4 -1
  98. data/test/active_record_unit.rb +28 -30
  99. data/test/activerecord/render_partial_with_record_identification_test.rb +25 -12
  100. data/test/controller/action_pack_assertions_test.rb +8 -37
  101. data/test/controller/addresses_render_test.rb +0 -3
  102. data/test/controller/assert_select_test.rb +51 -24
  103. data/test/controller/base_test.rb +4 -4
  104. data/test/controller/caching_test.rb +136 -66
  105. data/test/controller/capture_test.rb +1 -21
  106. data/test/controller/cgi_test.rb +157 -10
  107. data/test/controller/components_test.rb +41 -25
  108. data/test/controller/content_type_test.rb +49 -17
  109. data/test/controller/cookie_test.rb +1 -1
  110. data/test/controller/deprecation/deprecated_base_methods_test.rb +0 -3
  111. data/test/controller/dispatcher_test.rb +9 -1
  112. data/test/controller/filter_params_test.rb +2 -2
  113. data/test/controller/filters_test.rb +13 -13
  114. data/test/controller/html-scanner/cdata_node_test.rb +15 -0
  115. data/test/controller/html-scanner/node_test.rb +21 -0
  116. data/test/controller/html-scanner/sanitizer_test.rb +14 -0
  117. data/test/controller/integration_test.rb +167 -6
  118. data/test/controller/layout_test.rb +11 -68
  119. data/test/controller/logging_test.rb +46 -0
  120. data/test/controller/mime_responds_test.rb +61 -59
  121. data/test/controller/mime_type_test.rb +6 -6
  122. data/test/controller/polymorphic_routes_test.rb +37 -2
  123. data/test/controller/rack_test.rb +323 -0
  124. data/test/controller/redirect_test.rb +72 -71
  125. data/test/controller/render_test.rb +1120 -108
  126. data/test/controller/request_forgery_protection_test.rb +66 -52
  127. data/test/controller/request_test.rb +103 -146
  128. data/test/controller/rescue_test.rb +20 -24
  129. data/test/controller/resources_test.rb +408 -25
  130. data/test/controller/routing_test.rb +1774 -1774
  131. data/test/controller/send_file_test.rb +0 -4
  132. data/test/controller/session/cookie_store_test.rb +53 -1
  133. data/test/controller/test_test.rb +15 -37
  134. data/test/controller/translation_test.rb +26 -0
  135. data/test/controller/url_rewriter_test.rb +27 -28
  136. data/test/controller/view_paths_test.rb +48 -47
  137. data/test/fixtures/_top_level_partial.html.erb +1 -0
  138. data/test/fixtures/_top_level_partial_only.erb +1 -0
  139. data/test/fixtures/developers/_developer.erb +1 -0
  140. data/test/fixtures/fun/games/_game.erb +1 -0
  141. data/test/fixtures/fun/serious/games/_game.erb +1 -0
  142. data/test/fixtures/functional_caching/formatted_fragment_cached.html.erb +3 -0
  143. data/test/fixtures/functional_caching/formatted_fragment_cached.js.rjs +6 -0
  144. data/test/fixtures/functional_caching/formatted_fragment_cached.xml.builder +5 -0
  145. data/test/fixtures/functional_caching/inline_fragment_cached.html.erb +2 -0
  146. data/test/fixtures/layouts/_column.html.erb +2 -0
  147. data/test/fixtures/projects/_project.erb +1 -0
  148. data/test/fixtures/public/javascripts/subdir/subdir.js +1 -0
  149. data/test/fixtures/public/stylesheets/subdir/subdir.css +1 -0
  150. data/test/fixtures/replies/_reply.erb +1 -0
  151. data/test/fixtures/test/_counter.html.erb +1 -0
  152. data/test/fixtures/test/_customer.erb +1 -1
  153. data/test/fixtures/test/_customer_with_var.erb +1 -0
  154. data/test/fixtures/test/_layout_for_block_with_args.html.erb +3 -0
  155. data/test/fixtures/test/_local_inspector.html.erb +1 -0
  156. data/test/fixtures/test/_partial_with_only_html_version.html.erb +1 -0
  157. data/test/fixtures/test/hello.builder +1 -1
  158. data/test/fixtures/test/hyphen-ated.erb +1 -0
  159. data/test/fixtures/test/implicit_content_type.atom.builder +2 -0
  160. data/test/fixtures/test/nested_layout.erb +3 -0
  161. data/test/fixtures/test/non_erb_block_content_for.builder +1 -1
  162. data/test/fixtures/test/sub_template_raise.html.erb +1 -0
  163. data/test/fixtures/test/template.erb +1 -0
  164. data/test/fixtures/test/using_layout_around_block_with_args.html.erb +1 -0
  165. data/test/template/active_record_helper_i18n_test.rb +46 -0
  166. data/test/template/active_record_helper_test.rb +24 -24
  167. data/test/template/asset_tag_helper_test.rb +161 -29
  168. data/test/template/atom_feed_helper_test.rb +114 -5
  169. data/test/template/compiled_templates_test.rb +59 -0
  170. data/test/template/date_helper_i18n_test.rb +113 -0
  171. data/test/template/date_helper_test.rb +403 -109
  172. data/test/template/form_helper_test.rb +213 -154
  173. data/test/template/form_options_helper_test.rb +249 -897
  174. data/test/template/form_tag_helper_test.rb +80 -32
  175. data/test/template/javascript_helper_test.rb +17 -18
  176. data/test/template/number_helper_i18n_test.rb +54 -0
  177. data/test/template/number_helper_test.rb +43 -13
  178. data/test/template/prototype_helper_test.rb +101 -84
  179. data/test/template/record_tag_helper_test.rb +24 -20
  180. data/test/template/render_test.rb +193 -0
  181. data/test/template/sanitize_helper_test.rb +3 -3
  182. data/test/template/tag_helper_test.rb +34 -14
  183. data/test/template/text_helper_test.rb +83 -9
  184. data/test/template/translation_helper_test.rb +28 -0
  185. data/test/template/url_helper_test.rb +55 -18
  186. metadata +57 -18
  187. data/lib/action_view/helpers/javascripts/controls.js +0 -963
  188. data/lib/action_view/helpers/javascripts/dragdrop.js +0 -972
  189. data/lib/action_view/helpers/javascripts/effects.js +0 -1120
  190. data/lib/action_view/helpers/javascripts/prototype.js +0 -4225
  191. data/lib/action_view/partial_template.rb +0 -70
  192. data/lib/action_view/template_finder.rb +0 -177
  193. data/lib/action_view/template_handlers/compilable.rb +0 -128
  194. data/test/controller/custom_handler_test.rb +0 -45
  195. data/test/controller/new_render_test.rb +0 -945
  196. data/test/fixtures/test/block_content_for.erb +0 -2
  197. data/test/fixtures/test/erb_content_for.erb +0 -2
  198. data/test/template/deprecated_erb_variable_test.rb +0 -9
  199. data/test/template/template_finder_test.rb +0 -73
  200. data/test/template/template_object_test.rb +0 -95
@@ -38,6 +38,7 @@ module ActionController #:nodoc:
38
38
  def self.included(base) #:nodoc:
39
39
  base.class_eval do
40
40
  include InstanceMethods
41
+ include ActiveSupport::Deprecation
41
42
  extend ClassMethods
42
43
  helper HelperMethods
43
44
 
@@ -64,7 +65,7 @@ module ActionController #:nodoc:
64
65
 
65
66
  module HelperMethods
66
67
  def render_component(options)
67
- @controller.send!(:render_component_as_string, options)
68
+ @controller.__send__(:render_component_as_string, options)
68
69
  end
69
70
  end
70
71
 
@@ -82,6 +83,7 @@ module ActionController #:nodoc:
82
83
  render_for_text(component_response(options, true).body, response.headers["Status"])
83
84
  end
84
85
  end
86
+ deprecate :render_component => "Please install render_component plugin from http://github.com/rails/render_component/tree/master"
85
87
 
86
88
  # Returns the component response as a string
87
89
  def render_component_as_string(options) #:doc:
@@ -95,6 +97,7 @@ module ActionController #:nodoc:
95
97
  end
96
98
  end
97
99
  end
100
+ deprecate :render_component_as_string => "Please install render_component plugin from http://github.com/rails/render_component/tree/master"
98
101
 
99
102
  def flash_with_components(refresh = false) #:nodoc:
100
103
  if !defined?(@_flash) || refresh
@@ -22,6 +22,16 @@ module ActionController #:nodoc:
22
22
  #
23
23
  # cookies.delete :user_name
24
24
  #
25
+ # Please note that if you specify a :domain when setting a cookie, you must also specify the domain when deleting the cookie:
26
+ #
27
+ # cookies[:key] = {
28
+ # :value => 'a yummy cookie',
29
+ # :expires => 1.year.from_now,
30
+ # :domain => 'domain.com'
31
+ # }
32
+ #
33
+ # cookies.delete(:key, :domain => 'domain.com')
34
+ #
25
35
  # The option symbols for setting cookies are:
26
36
  #
27
37
  # * <tt>:value</tt> - The cookie's value or list of values (as an array).
@@ -22,11 +22,15 @@ module ActionController
22
22
  end
23
23
 
24
24
  if defined?(ActiveRecord)
25
- before_dispatch { ActiveRecord::Base.verify_active_connections! }
25
+ after_dispatch :checkin_connections
26
26
  to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers }
27
27
  end
28
28
 
29
- after_dispatch :flush_logger if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:flush)
29
+ after_dispatch :flush_logger if Base.logger && Base.logger.respond_to?(:flush)
30
+
31
+ to_prepare do
32
+ I18n.reload!
33
+ end
30
34
  end
31
35
 
32
36
  # Backward-compatible class method takes CGI-specific args. Deprecated
@@ -38,7 +42,7 @@ module ActionController
38
42
  # Add a preparation callback. Preparation callbacks are run before every
39
43
  # request in development mode, and before the first request in production
40
44
  # mode.
41
- #
45
+ #
42
46
  # An optional identifier may be supplied for the callback. If provided,
43
47
  # to_prepare may be called again with the same identifier to replace the
44
48
  # existing callback. Passing an identifier is a suggested practice if the
@@ -46,7 +50,7 @@ module ActionController
46
50
  def to_prepare(identifier = nil, &block)
47
51
  @prepare_dispatch_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new
48
52
  callback = ActiveSupport::Callbacks::Callback.new(:prepare_dispatch, block, :identifier => identifier)
49
- @prepare_dispatch_callbacks | callback
53
+ @prepare_dispatch_callbacks.replace_or_append!(callback)
50
54
  end
51
55
 
52
56
  # If the block raises, send status code as a last-ditch response.
@@ -96,19 +100,27 @@ module ActionController
96
100
  include ActiveSupport::Callbacks
97
101
  define_callbacks :prepare_dispatch, :before_dispatch, :after_dispatch
98
102
 
99
- def initialize(output, request = nil, response = nil)
103
+ def initialize(output = $stdout, request = nil, response = nil)
100
104
  @output, @request, @response = output, request, response
101
105
  end
102
106
 
107
+ def dispatch_unlocked
108
+ begin
109
+ run_callbacks :before_dispatch
110
+ handle_request
111
+ rescue Exception => exception
112
+ failsafe_rescue exception
113
+ ensure
114
+ run_callbacks :after_dispatch, :enumerator => :reverse_each
115
+ end
116
+ end
117
+
103
118
  def dispatch
104
- @@guard.synchronize do
105
- begin
106
- run_callbacks :before_dispatch
107
- handle_request
108
- rescue Exception => exception
109
- failsafe_rescue exception
110
- ensure
111
- run_callbacks :after_dispatch, :enumerator => :reverse_each
119
+ if ActionController::Base.allow_concurrency
120
+ dispatch_unlocked
121
+ else
122
+ @@guard.synchronize do
123
+ dispatch_unlocked
112
124
  end
113
125
  end
114
126
  end
@@ -123,12 +135,19 @@ module ActionController
123
135
  failsafe_rescue exception
124
136
  end
125
137
 
138
+ def call(env)
139
+ @request = RackRequest.new(env)
140
+ @response = RackResponse.new(@request)
141
+ dispatch
142
+ end
143
+
126
144
  def reload_application
127
145
  # Run prepare callbacks before every request in development mode
128
146
  run_callbacks :prepare_dispatch
129
147
 
130
148
  Routing::Routes.reload
131
- ActionView::TemplateFinder.reload! unless ActionView::Base.cache_template_loading
149
+ ActionController::Base.view_paths.reload!
150
+ ActionView::Helpers::AssetTagHelper::AssetTag::Cache.clear
132
151
  end
133
152
 
134
153
  # Cleanup the application by clearing out loaded classes so they can
@@ -140,7 +159,22 @@ module ActionController
140
159
  end
141
160
 
142
161
  def flush_logger
143
- RAILS_DEFAULT_LOGGER.flush
162
+ Base.logger.flush
163
+ end
164
+
165
+ def mark_as_test_request!
166
+ @test_request = true
167
+ self
168
+ end
169
+
170
+ def test_request?
171
+ @test_request
172
+ end
173
+
174
+ def checkin_connections
175
+ # Don't return connection (and peform implicit rollback) if this request is a part of integration test
176
+ return if test_request?
177
+ ActiveRecord::Base.clear_active_connections!
144
178
  end
145
179
 
146
180
  protected
@@ -94,7 +94,7 @@ module ActionController #:nodoc:
94
94
  map! do |filter|
95
95
  if filters.include?(filter)
96
96
  new_filter = filter.dup
97
- new_filter.options.merge!(options)
97
+ new_filter.update_options!(options)
98
98
  new_filter
99
99
  else
100
100
  filter
@@ -104,16 +104,34 @@ module ActionController #:nodoc:
104
104
  end
105
105
 
106
106
  class Filter < ActiveSupport::Callbacks::Callback #:nodoc:
107
+ def initialize(kind, method, options = {})
108
+ super
109
+ update_options! options
110
+ end
111
+
112
+ # override these to return true in appropriate subclass
107
113
  def before?
108
- self.class == BeforeFilter
114
+ false
109
115
  end
110
116
 
111
117
  def after?
112
- self.class == AfterFilter
118
+ false
113
119
  end
114
120
 
115
121
  def around?
116
- self.class == AroundFilter
122
+ false
123
+ end
124
+
125
+ # Make sets of strings from :only/:except options
126
+ def update_options!(other)
127
+ if other
128
+ convert_only_and_except_options_to_sets_of_strings(other)
129
+ if other[:skip]
130
+ convert_only_and_except_options_to_sets_of_strings(other[:skip])
131
+ end
132
+ end
133
+
134
+ options.update(other)
117
135
  end
118
136
 
119
137
  private
@@ -127,9 +145,9 @@ module ActionController #:nodoc:
127
145
 
128
146
  def included_in_action?(controller, options)
129
147
  if options[:only]
130
- Array(options[:only]).map(&:to_s).include?(controller.action_name)
148
+ options[:only].include?(controller.action_name)
131
149
  elsif options[:except]
132
- !Array(options[:except]).map(&:to_s).include?(controller.action_name)
150
+ !options[:except].include?(controller.action_name)
133
151
  else
134
152
  true
135
153
  end
@@ -138,6 +156,14 @@ module ActionController #:nodoc:
138
156
  def should_run_callback?(controller)
139
157
  should_not_skip?(controller) && included_in_action?(controller, options) && super
140
158
  end
159
+
160
+ def convert_only_and_except_options_to_sets_of_strings(opts)
161
+ [:only, :except].each do |key|
162
+ if values = opts[key]
163
+ opts[key] = Array(values).map(&:to_s).to_set
164
+ end
165
+ end
166
+ end
141
167
  end
142
168
 
143
169
  class AroundFilter < Filter #:nodoc:
@@ -145,6 +171,10 @@ module ActionController #:nodoc:
145
171
  :around
146
172
  end
147
173
 
174
+ def around?
175
+ true
176
+ end
177
+
148
178
  def call(controller, &block)
149
179
  if should_run_callback?(controller)
150
180
  method = filter_responds_to_before_and_after? ? around_proc : self.method
@@ -169,8 +199,8 @@ module ActionController #:nodoc:
169
199
  Proc.new do |controller, action|
170
200
  method.before(controller)
171
201
 
172
- if controller.send!(:performed?)
173
- controller.send!(:halt_filter_chain, method, :rendered_or_redirected)
202
+ if controller.__send__(:performed?)
203
+ controller.__send__(:halt_filter_chain, method, :rendered_or_redirected)
174
204
  else
175
205
  begin
176
206
  action.call
@@ -187,10 +217,14 @@ module ActionController #:nodoc:
187
217
  :before
188
218
  end
189
219
 
220
+ def before?
221
+ true
222
+ end
223
+
190
224
  def call(controller, &block)
191
225
  super
192
- if controller.send!(:performed?)
193
- controller.send!(:halt_filter_chain, method, :rendered_or_redirected)
226
+ if controller.__send__(:performed?)
227
+ controller.__send__(:halt_filter_chain, method, :rendered_or_redirected)
194
228
  end
195
229
  end
196
230
  end
@@ -199,6 +233,10 @@ module ActionController #:nodoc:
199
233
  def type
200
234
  :after
201
235
  end
236
+
237
+ def after?
238
+ true
239
+ end
202
240
  end
203
241
 
204
242
  # Filters enable controllers to run shared pre- and post-processing code for its actions. These filters can be used to do
@@ -1,31 +1,33 @@
1
+ require 'active_support/memoizable'
2
+
1
3
  module ActionController
2
4
  module Http
3
5
  class Headers < ::Hash
4
-
5
- def initialize(constructor = {})
6
- if constructor.is_a?(Hash)
6
+ extend ActiveSupport::Memoizable
7
+
8
+ def initialize(*args)
9
+ if args.size == 1 && args[0].is_a?(Hash)
7
10
  super()
8
- update(constructor)
11
+ update(args[0])
9
12
  else
10
- super(constructor)
13
+ super
11
14
  end
12
15
  end
13
-
16
+
14
17
  def [](header_name)
15
18
  if include?(header_name)
16
- super
19
+ super
17
20
  else
18
- super(normalize_header(header_name))
21
+ super(env_name(header_name))
19
22
  end
20
23
  end
21
-
22
-
24
+
23
25
  private
24
- # Takes an HTTP header name and returns it in the
25
- # format
26
- def normalize_header(header_name)
26
+ # Converts a HTTP header name to an environment variable name.
27
+ def env_name(header_name)
27
28
  "HTTP_#{header_name.upcase.gsub(/-/, '_')}"
28
29
  end
30
+ memoize :env_name
29
31
  end
30
32
  end
31
- end
33
+ end
@@ -204,8 +204,8 @@ module ActionController #:nodoc:
204
204
 
205
205
  begin
206
206
  child.master_helper_module = Module.new
207
- child.master_helper_module.send! :include, master_helper_module
208
- child.send! :default_helper_module!
207
+ child.master_helper_module.__send__ :include, master_helper_module
208
+ child.__send__ :default_helper_module!
209
209
  rescue MissingSourceFile => e
210
210
  raise unless e.is_missing?("helpers/#{child.controller_path}_helper")
211
211
  end
@@ -117,7 +117,7 @@ module ActionController
117
117
 
118
118
  def authentication_request(controller, realm)
119
119
  controller.headers["WWW-Authenticate"] = %(Basic realm="#{realm.gsub(/"/, "")}")
120
- controller.send! :render, :text => "HTTP Basic: Access denied.\n", :status => :unauthorized
120
+ controller.__send__ :render, :text => "HTTP Basic: Access denied.\n", :status => :unauthorized
121
121
  end
122
122
  end
123
123
  end
@@ -1,9 +1,10 @@
1
- require 'stringio'
2
- require 'uri'
3
-
1
+ require 'active_support/test_case'
4
2
  require 'action_controller/dispatcher'
5
3
  require 'action_controller/test_process'
6
4
 
5
+ require 'stringio'
6
+ require 'uri'
7
+
7
8
  module ActionController
8
9
  module Integration #:nodoc:
9
10
  # An integration Session instance represents a set of requests and responses
@@ -100,7 +101,7 @@ module ActionController
100
101
  @https = flag
101
102
  end
102
103
 
103
- # Return +true+ if the session is mimicing a secure HTTPS request.
104
+ # Return +true+ if the session is mimicking a secure HTTPS request.
104
105
  #
105
106
  # if session.https?
106
107
  # ...
@@ -164,11 +165,19 @@ module ActionController
164
165
  status/100 == 3
165
166
  end
166
167
 
167
- # Performs a GET request with the given parameters. The parameters may
168
- # be +nil+, a Hash, or a string that is appropriately encoded
169
- # (<tt>application/x-www-form-urlencoded</tt> or <tt>multipart/form-data</tt>).
170
- # The headers should be a hash. The keys will automatically be upcased, with the
171
- # prefix 'HTTP_' added if needed.
168
+ # Performs a GET request with the given parameters.
169
+ #
170
+ # - +path+: The URI (as a String) on which you want to perform a GET request.
171
+ # - +parameters+: The HTTP parameters that you want to pass. This may be +nil+,
172
+ # a Hash, or a String that is appropriately encoded
173
+ # (<tt>application/x-www-form-urlencoded</tt> or <tt>multipart/form-data</tt>).
174
+ # - +headers+: Additional HTTP headers to pass, as a Hash. The keys will
175
+ # automatically be upcased, with the prefix 'HTTP_' added if needed.
176
+ #
177
+ # This method returns an AbstractResponse object, which one can use to inspect
178
+ # the details of the response. Furthermore, if this method was called from an
179
+ # ActionController::IntegrationTest object, then that object's <tt>@response</tt>
180
+ # instance variable will point to the same response object.
172
181
  #
173
182
  # You can also perform POST, PUT, DELETE, and HEAD requests with +post+,
174
183
  # +put+, +delete+, and +head+.
@@ -219,21 +228,6 @@ module ActionController
219
228
  end
220
229
 
221
230
  private
222
- class StubCGI < CGI #:nodoc:
223
- attr_accessor :stdinput, :stdoutput, :env_table
224
-
225
- def initialize(env, stdinput = nil)
226
- self.env_table = env
227
- self.stdoutput = StringIO.new
228
-
229
- super
230
-
231
- stdinput.set_encoding(Encoding::BINARY) if stdinput.respond_to?(:set_encoding)
232
- stdinput.force_encoding(Encoding::BINARY) if stdinput.respond_to?(:force_encoding)
233
- @stdinput = stdinput.is_a?(IO) ? stdinput : StringIO.new(stdinput || '')
234
- end
235
- end
236
-
237
231
  # Tailors the session based on the given URI, setting the HTTPS value
238
232
  # and the hostname.
239
233
  def interpret_uri(path)
@@ -281,9 +275,8 @@ module ActionController
281
275
 
282
276
  ActionController::Base.clear_last_instantiation!
283
277
 
284
- cgi = StubCGI.new(env, data)
285
- ActionController::Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, cgi.stdoutput)
286
- @result = cgi.stdoutput.string
278
+ env['rack.input'] = data.is_a?(IO) ? data : StringIO.new(data || '')
279
+ @status, @headers, result_body = ActionController::Dispatcher.new.mark_as_test_request!.call(env)
287
280
  @request_count += 1
288
281
 
289
282
  @controller = ActionController::Base.last_instantiation
@@ -297,32 +290,34 @@ module ActionController
297
290
 
298
291
  @html_document = nil
299
292
 
300
- parse_result
301
- return status
302
- rescue MultiPartNeededException
303
- boundary = "----------XnJLe9ZIbbGUYtzPQJ16u1"
304
- status = process(method, path, multipart_body(parameters, boundary), (headers || {}).merge({"CONTENT_TYPE" => "multipart/form-data; boundary=#{boundary}"}))
305
- return status
306
- end
293
+ # Inject status back in for backwords compatibility with CGI
294
+ @headers['Status'] = @status
307
295
 
308
- # Parses the result of the response and extracts the various values,
309
- # like cookies, status, headers, etc.
310
- def parse_result
311
- response_headers, result_body = @result.split(/\r\n\r\n/, 2)
296
+ @status, @status_message = @status.split(/ /)
297
+ @status = @status.to_i
312
298
 
313
- @headers = Hash.new { |h,k| h[k] = [] }
314
- response_headers.to_s.each_line do |line|
315
- key, value = line.strip.split(/:\s*/, 2)
316
- @headers[key.downcase] << value
299
+ cgi_headers = Hash.new { |h,k| h[k] = [] }
300
+ @headers.each do |key, value|
301
+ cgi_headers[key.downcase] << value
317
302
  end
303
+ cgi_headers['set-cookie'] = cgi_headers['set-cookie'].first
304
+ @headers = cgi_headers
318
305
 
319
- (@headers['set-cookie'] || [] ).each do |string|
320
- name, value = string.match(/^([^=]*)=([^;]*);/)[1,2]
306
+ @response.headers['cookie'] ||= []
307
+ (@headers['set-cookie'] || []).each do |cookie|
308
+ name, value = cookie.match(/^([^=]*)=([^;]*);/)[1,2]
321
309
  @cookies[name] = value
310
+
311
+ # Fake CGI cookie header
312
+ # DEPRECATE: Use response.headers["Set-Cookie"] instead
313
+ @response.headers['cookie'] << CGI::Cookie::new("name" => name, "value" => value)
322
314
  end
323
315
 
324
- @status, @status_message = @headers["status"].first.to_s.split(/ /)
325
- @status = @status.to_i
316
+ return status
317
+ rescue MultiPartNeededException
318
+ boundary = "----------XnJLe9ZIbbGUYtzPQJ16u1"
319
+ status = process(method, path, multipart_body(parameters, boundary), (headers || {}).merge({"CONTENT_TYPE" => "multipart/form-data; boundary=#{boundary}"}))
320
+ return status
326
321
  end
327
322
 
328
323
  # Encode the cookies hash in a format suitable for passing to a
@@ -335,13 +330,15 @@ module ActionController
335
330
 
336
331
  # Get a temporary URL writer object
337
332
  def generic_url_rewriter
338
- cgi = StubCGI.new('REQUEST_METHOD' => "GET",
339
- 'QUERY_STRING' => "",
340
- "REQUEST_URI" => "/",
341
- "HTTP_HOST" => host,
342
- "SERVER_PORT" => https? ? "443" : "80",
343
- "HTTPS" => https? ? "on" : "off")
344
- ActionController::UrlRewriter.new(ActionController::CgiRequest.new(cgi), {})
333
+ env = {
334
+ 'REQUEST_METHOD' => "GET",
335
+ 'QUERY_STRING' => "",
336
+ "REQUEST_URI" => "/",
337
+ "HTTP_HOST" => host,
338
+ "SERVER_PORT" => https? ? "443" : "80",
339
+ "HTTPS" => https? ? "on" : "off"
340
+ }
341
+ ActionController::UrlRewriter.new(ActionController::RackRequest.new(env), {})
345
342
  end
346
343
 
347
344
  def name_with_prefix(prefix, name)
@@ -442,12 +439,12 @@ EOF
442
439
  end
443
440
 
444
441
  %w(get post put head delete cookies assigns
445
- xml_http_request get_via_redirect post_via_redirect).each do |method|
442
+ xml_http_request xhr get_via_redirect post_via_redirect).each do |method|
446
443
  define_method(method) do |*args|
447
444
  reset! unless @integration_session
448
445
  # reset the html_document variable, but only for new get/post calls
449
446
  @html_document = nil unless %w(cookies assigns).include?(method)
450
- returning @integration_session.send!(method, *args) do
447
+ returning @integration_session.__send__(method, *args) do
451
448
  copy_session_variables!
452
449
  end
453
450
  end
@@ -472,12 +469,12 @@ EOF
472
469
  self.class.fixture_table_names.each do |table_name|
473
470
  name = table_name.tr(".", "_")
474
471
  next unless respond_to?(name)
475
- extras.send!(:define_method, name) { |*args| delegate.send(name, *args) }
472
+ extras.__send__(:define_method, name) { |*args| delegate.send(name, *args) }
476
473
  end
477
474
  end
478
475
 
479
476
  # delegate add_assertion to the test case
480
- extras.send!(:define_method, :add_assertion) { test_result.add_assertion }
477
+ extras.__send__(:define_method, :add_assertion) { test_result.add_assertion }
481
478
  session.extend(extras)
482
479
  session.delegate = self
483
480
  session.test_result = @_result
@@ -491,14 +488,14 @@ EOF
491
488
  def copy_session_variables! #:nodoc:
492
489
  return unless @integration_session
493
490
  %w(controller response request).each do |var|
494
- instance_variable_set("@#{var}", @integration_session.send!(var))
491
+ instance_variable_set("@#{var}", @integration_session.__send__(var))
495
492
  end
496
493
  end
497
494
 
498
495
  # Delegate unhandled messages to the current session instance.
499
496
  def method_missing(sym, *args, &block)
500
497
  reset! unless @integration_session
501
- returning @integration_session.send!(sym, *args, &block) do
498
+ returning @integration_session.__send__(sym, *args, &block) do
502
499
  copy_session_variables!
503
500
  end
504
501
  end
@@ -580,7 +577,7 @@ EOF
580
577
  # end
581
578
  # end
582
579
  # end
583
- class IntegrationTest < Test::Unit::TestCase
580
+ class IntegrationTest < ActiveSupport::TestCase
584
581
  include Integration::Runner
585
582
 
586
583
  # Work around a bug in test/unit caused by the default test being named