Skip to content
Browse files

Merge commit 'rails/master'

  • Loading branch information...
2 parents 19d2ff8 + db892ea commit b0bd4f45fa9180793e3c35590c8a887ddfe43553 @miloops miloops committed
Showing with 1,775 additions and 6,327 deletions.
  1. +6 −5 actionmailer/lib/action_mailer/base.rb
  2. +2 −2 actionmailer/test/mail_service_test.rb
  3. +23 −21 actionpack/lib/action_controller/base/base.rb
  4. +1 −1 actionpack/lib/action_controller/base/mime_responds.rb
  5. +5 −4 actionpack/lib/action_controller/base/render.rb
  6. +1 −1 actionpack/lib/action_controller/caching/actions.rb
  7. +0 −1 actionpack/lib/action_controller/dispatch/middlewares.rb
  8. +22 −10 actionpack/lib/action_controller/testing/assertions/response.rb
  9. +30 −158 actionpack/lib/action_controller/testing/integration.rb
  10. +22 −162 actionpack/lib/action_controller/testing/process.rb
  11. +7 −8 actionpack/lib/action_dispatch.rb
  12. +10 −14 actionpack/lib/action_dispatch/http/request.rb
  13. +97 −8 actionpack/lib/action_dispatch/http/response.rb
  14. +3 −3 actionpack/lib/action_dispatch/middleware/failsafe.rb
  15. +0 −19 actionpack/lib/action_dispatch/middleware/rewindable_input.rb
  16. +26 −4 actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
  17. +4 −3 actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
  18. +114 −0 actionpack/lib/action_dispatch/test/mock.rb
  19. +33 −0 actionpack/lib/action_dispatch/test/uploaded_file.rb
  20. +0 −89 actionpack/lib/action_dispatch/vendor/rack-1.0/rack.rb
  21. +0 −22 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/adapter/camping.rb
  22. +0 −37 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/abstract/handler.rb
  23. +0 −37 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/abstract/request.rb
  24. +0 −58 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/basic.rb
  25. +0 −124 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/md5.rb
  26. +0 −51 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/nonce.rb
  27. +0 −55 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/params.rb
  28. +0 −40 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/request.rb
  29. +0 −480 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/openid.rb
  30. +0 −63 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/builder.rb
  31. +0 −36 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/cascade.rb
  32. +0 −49 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/chunked.rb
  33. +0 −61 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/commonlogger.rb
  34. +0 −45 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/conditionalget.rb
  35. +0 −29 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/content_length.rb
  36. +0 −23 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/content_type.rb
  37. +0 −85 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/deflater.rb
  38. +0 −153 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/directory.rb
  39. +0 −88 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/file.rb
  40. +0 −48 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler.rb
  41. +0 −61 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/cgi.rb
  42. +0 −8 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/evented_mongrel.rb
  43. +0 −89 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/fastcgi.rb
  44. +0 −55 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/lsws.rb
  45. +0 −84 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/mongrel.rb
  46. +0 −59 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/scgi.rb
  47. +0 −8 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/swiftiplied_mongrel.rb
  48. +0 −18 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/thin.rb
  49. +0 −67 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/handler/webrick.rb
  50. +0 −19 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/head.rb
  51. +0 −462 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lint.rb
  52. +0 −65 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lobster.rb
  53. +0 −16 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/lock.rb
  54. +0 −27 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/methodoverride.rb
  55. +0 −204 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/mime.rb
  56. +0 −160 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/mock.rb
  57. +0 −57 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/recursive.rb
  58. +0 −64 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/reloader.rb
  59. +0 −241 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/request.rb
  60. +0 −179 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/response.rb
  61. +0 −142 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/abstract/id.rb
  62. +0 −91 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/cookie.rb
  63. +0 −109 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/memcache.rb
  64. +0 −100 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/session/pool.rb
  65. +0 −349 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/showexceptions.rb
  66. +0 −106 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/showstatus.rb
  67. +0 −38 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/static.rb
  68. +0 −55 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/urlmap.rb
  69. +0 −392 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/utils.rb
  70. +4 −2 actionpack/lib/action_view/base.rb
  71. +9 −11 actionpack/lib/action_view/helpers/prototype_helper.rb
  72. +6 −6 actionpack/lib/action_view/paths.rb
  73. +7 −6 actionpack/lib/action_view/render/rendering.rb
  74. +2 −2 actionpack/lib/action_view/template/error.rb
  75. +1 −1 actionpack/lib/action_view/template/handlers.rb
  76. +45 −23 actionpack/lib/action_view/template/path.rb
  77. +54 −162 actionpack/lib/action_view/template/template.rb
  78. +7 −5 actionpack/lib/action_view/test_case.rb
  79. +1 −1 actionpack/test/abstract_controller/abstract_controller_test.rb
  80. +1 −0 actionpack/test/activerecord/active_record_store_test.rb
  81. +12 −10 actionpack/test/controller/action_pack_assertions_test.rb
  82. +1 −1 actionpack/test/controller/dispatcher_test.rb
  83. +107 −70 actionpack/test/controller/filters_test.rb
  84. +24 −24 actionpack/test/controller/flash_test.rb
  85. +1 −1 actionpack/test/controller/helper_test.rb
  86. +0 −2 actionpack/test/controller/http_digest_authentication_test.rb
  87. +2 −2 actionpack/test/controller/integration_test.rb
  88. +18 −16 actionpack/test/controller/layout_test.rb
  89. +4 −3 actionpack/test/controller/render_test.rb
  90. +12 −11 actionpack/test/controller/request/test_request_test.rb
  91. +0 −6 actionpack/test/controller/test_test.rb
  92. +29 −20 actionpack/test/controller/view_paths_test.rb
  93. +0 −90 actionpack/test/dispatch/rack_test.rb
  94. +1 −63 actionpack/test/dispatch/request/multipart_params_parsing_test.rb
  95. +0 −38 actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb
  96. +130 −0 actionpack/test/dispatch/response_test.rb
  97. +1 −2 actionpack/test/dispatch/session/cookie_store_test.rb
  98. +8 −16 actionpack/test/dispatch/session/test_session_test.rb
  99. 0 actionpack/test/fixtures/layouts/{standard.erb → standard.html.erb}
  100. +1 −0 actionpack/test/fixtures/test/render_file_with_locals_and_default.erb
  101. +1 −1 actionpack/test/template/body_parts_test.rb
  102. +5 −31 actionpack/test/template/compiled_templates_test.rb
  103. +9 −9 actionpack/test/template/output_buffer_test.rb
  104. +3 −11 actionpack/test/template/render_test.rb
  105. +9 −5 activerecord/lib/active_record/autosave_association.rb
  106. +4 −4 activerecord/lib/active_record/serialization.rb
  107. +6 −3 activerecord/lib/active_record/serializers/json_serializer.rb
  108. +22 −0 activerecord/test/cases/autosave_association_test.rb
  109. +1 −1 activerecord/test/cases/calculations_test.rb
  110. +5 −3 activeresource/lib/active_resource/base.rb
  111. +3 −1 activesupport/lib/active_support/core_ext/module/delegation.rb
  112. +1 −1 activesupport/lib/active_support/deprecation/proxy_wrappers.rb
  113. +33 −6 activesupport/lib/active_support/json.rb
  114. +19 −20 activesupport/lib/active_support/json/encoders/date.rb
  115. +19 −20 activesupport/lib/active_support/json/encoders/date_time.rb
  116. +11 −12 activesupport/lib/active_support/json/encoders/enumerable.rb
  117. +4 −5 activesupport/lib/active_support/json/encoders/false_class.rb
  118. +45 −44 activesupport/lib/active_support/json/encoders/hash.rb
  119. +4 −5 activesupport/lib/active_support/json/encoders/nil_class.rb
  120. +4 −5 activesupport/lib/active_support/json/encoders/numeric.rb
  121. +6 −3 activesupport/lib/active_support/json/encoders/object.rb
  122. +4 −5 activesupport/lib/active_support/json/encoders/regexp.rb
  123. +4 −36 activesupport/lib/active_support/json/encoders/string.rb
  124. +4 −5 activesupport/lib/active_support/json/encoders/symbol.rb
  125. +19 −20 activesupport/lib/active_support/json/encoders/time.rb
  126. +4 −5 activesupport/lib/active_support/json/encoders/true_class.rb
  127. +6 −4 activesupport/lib/active_support/json/encoding.rb
  128. +4 −3 activesupport/lib/active_support/json/variable.rb
  129. +20 −22 activesupport/lib/active_support/time_with_zone.rb
  130. +162 −0 activesupport/lib/active_support/xml_mini/jdom.rb
  131. +1 −1 activesupport/test/json/encoding_test.rb
  132. +153 −0 activesupport/test/xml_mini/jdom_engine_test.rb
  133. +1 −1 ci/geminstaller.yml
  134. +0 −1 railties/lib/commands/server.rb
  135. +2 −0 railties/lib/console_app.rb
  136. +29 −4 railties/lib/initializer.rb
  137. +3 −0 railties/lib/rails/backtrace_cleaner.rb
  138. +17 −4 railties/lib/rails/gem_dependency.rb
  139. +0 −4 railties/lib/rails/plugin.rb
  140. +16 −2 railties/lib/tasks/gems.rake
  141. +5 −1 railties/lib/tasks/misc.rake
  142. +1 −0 railties/test/abstract_unit.rb
  143. +1 −0 railties/test/boot_test.rb
  144. +43 −0 railties/test/gem_dependency_test.rb
  145. +2 −2 railties/test/plugin_loader_test.rb
  146. +2 −1 railties/test/plugin_test_helper.rb
  147. +29 −0 railties/test/vendor/gems/dummy-gem-h-1.0.0/.specification
  148. +1 −0 railties/test/vendor/gems/dummy-gem-h-1.0.0/lib/dummy-gem-h.rb
  149. +41 −0 railties/test/vendor/gems/dummy-gem-i-1.0.0/.specification
  150. 0 railties/test/vendor/gems/dummy-gem-i-1.0.0/ext/dummy-gem-i/Makefile
  151. +1 −0 railties/test/vendor/gems/dummy-gem-i-1.0.0/lib/dummy-gem-i.rb
  152. +41 −0 railties/test/vendor/gems/dummy-gem-j-1.0.0/.specification
  153. +1 −0 railties/test/vendor/gems/dummy-gem-j-1.0.0/lib/dummy-gem-j.rb
  154. +49 −0 railties/test/vendor/gems/dummy-gem-k-1.0.0/.specification
  155. +1 −0 railties/test/vendor/gems/dummy-gem-k-1.0.0/lib/dummy-gem-k.rb
View
11 actionmailer/lib/action_mailer/base.rb
@@ -475,7 +475,7 @@ def create!(method_name, *parameters) #:nodoc:
# if @parts.empty?
template_root.find_all_by_parts(@template, {}, template_path).each do |template|
@parts << Part.new(
- :content_type => Mime::Type.lookup_by_extension(template.content_type || "text").to_s,
+ :content_type => template.mime_type ? template.mime_type.to_s : "text/plain",
:disposition => "inline",
:charset => charset,
:body => render_template(template, @body)
@@ -555,12 +555,13 @@ def initialize_defaults(method_name)
end
def render_template(template, body)
- if template.respond_to?(:content_type)
- @current_template_content_type = template.content_type
+ if template.respond_to?(:mime_type)
+ @current_template_content_type = template.mime_type && template.mime_type.to_sym.to_s
end
@template = initialize_template_class(body)
- layout = _pick_layout(layout, true) unless template.exempt_from_layout?
+ layout = _pick_layout(layout, true) unless
+ ActionController::Base.exempt_from_layout.include?(template.handler)
@template._render_template_with_layout(template, layout, {})
ensure
@current_template_content_type = nil
@@ -584,7 +585,7 @@ def render(opts)
end
layout = _pick_layout(layout,
- !template || !template.exempt_from_layout?)
+ !template || ActionController::Base.exempt_from_layout.include?(template.handler))
if template
@template._render_template_with_layout(template, layout, opts)
View
4 actionmailer/test/mail_service_test.rb
@@ -994,13 +994,13 @@ def test_starttls_is_not_enabled
class InheritableTemplateRootTest < Test::Unit::TestCase
def test_attr
- expected = "#{File.dirname(__FILE__)}/fixtures/path.with.dots"
+ expected = File.expand_path("#{File.dirname(__FILE__)}/fixtures/path.with.dots")
assert_equal expected, FunkyPathMailer.template_root.to_s
sub = Class.new(FunkyPathMailer)
sub.template_root = 'test/path'
- assert_equal 'test/path', sub.template_root.to_s
+ assert_equal File.expand_path('test/path'), sub.template_root.to_s
assert_equal expected, FunkyPathMailer.template_root.to_s
end
end
View
44 actionpack/lib/action_controller/base/base.rb
@@ -238,7 +238,7 @@ class Base
cattr_reader :protected_instance_variables
# Controller specific instance variables which will not be accessible inside views.
@@protected_instance_variables = %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller
- @action_name @before_filter_chain_aborted @action_cache_path @_session @_headers @_params
+ @action_name @before_filter_chain_aborted @action_cache_path @_headers @_params
@_flash @_response)
# Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets,
@@ -356,7 +356,9 @@ class Base
# Holds a hash of objects in the session. Accessed like <tt>session[:person]</tt> to get the object tied to the "person"
# key. The session will hold any type of object as values, but the key should be a string or symbol.
- attr_internal :session
+ def session
+ request.session
+ end
# Holds a hash of header names and values. Accessed like <tt>headers["Cache-Control"]</tt> to get the value of the Cache-Control
# directive. Values should always be specified as strings.
@@ -365,6 +367,8 @@ class Base
# Returns the name of the action this controller is processing.
attr_accessor :action_name
+ attr_reader :template
+
class << self
def call(env)
# HACK: For global rescue to have access to the original request and response
@@ -492,8 +496,18 @@ def filter_parameter_logging(*filter_words, &block)
end
protected :filter_parameters
end
+
+ @@exempt_from_layout = [ActionView::TemplateHandlers::RJS]
+
+ def exempt_from_layout(*types)
+ types.each do |type|
+ @@exempt_from_layout <<
+ ActionView::Template.handler_class_for_extension(type)
+ end
+
+ @@exempt_from_layout
+ end
- delegate :exempt_from_layout, :to => 'ActionView::Template'
end
public
@@ -787,7 +801,6 @@ def expires_now #:doc:
# Resets the session by clearing out all the objects stored within and initializing a new session object.
def reset_session #:doc:
request.reset_session
- @_session = request.session
end
private
@@ -805,19 +818,13 @@ def _process_options(options)
def initialize_template_class(response)
@template = response.template = ActionView::Base.new(self.class.view_paths, {}, self, formats)
- response.template.helpers.send :include, self.class.master_helper_module
+ @template.helpers.send :include, self.class.master_helper_module
response.redirected_to = nil
@performed_render = @performed_redirect = false
end
def assign_shortcuts(request, response)
- @_request, @_params = request, request.parameters
-
- @_response = response
- @_response.session = request.session
-
- @_session = @_response.session
-
+ @_request, @_response, @_params = request, response, request.parameters
@_headers = @_response.headers
end
@@ -861,13 +868,13 @@ def perform_action
return (performed? ? ret : default_render) if called
begin
- default_render
- rescue ActionView::MissingTemplate => e
- raise e unless e.action_name == action_name
- # If the path is the same as the action_name, the action is completely missing
+ view_paths.find_by_parts(action_name, {:formats => formats, :locales => [I18n.locale]}, controller_path)
+ rescue => e
raise UnknownAction, "No action responded to #{action_name}. Actions: " +
"#{action_methods.sort.to_sentence}", caller
end
+
+ default_render
end
# Returns true if a render or redirect has already been performed.
@@ -894,10 +901,6 @@ def complete_request_uri
"#{request.protocol}#{request.host}#{request.request_uri}"
end
- def close_session
- # @_session.close if @_session && @_session.respond_to?(:close)
- end
-
def default_template(action_name = self.action_name)
self.view_paths.find_template(default_template_name(action_name), default_template_format)
end
@@ -921,7 +924,6 @@ def template_path_includes_controller?(path)
end
def process_cleanup
- close_session
end
end
View
2 actionpack/lib/action_controller/base/mime_responds.rb
@@ -127,7 +127,7 @@ def custom(mime_type, &block)
@order << mime_type
@responses[mime_type] ||= Proc.new do
- @response.template.formats = [mime_type.to_sym]
+ @controller.template.formats = [mime_type.to_sym]
@response.content_type = mime_type.to_s
block_given? ? block.call : @controller.send(:render, :action => @controller.action_name)
end
View
9 actionpack/lib/action_controller/base/render.rb
@@ -254,7 +254,7 @@ def render(options = nil, extra_options = {}, &block) #:doc:
render_for_text(js)
elsif json = options[:json]
- json = ActiveSupport::JSON.encode(json) unless json.is_a?(String)
+ json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str)
json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
response.content_type ||= Mime::JSON
render_for_text(json)
@@ -378,13 +378,14 @@ def render_for_name(name, layout, options)
# ==== Arguments
# parts<Array[String, Array[Symbol*], String, Boolean]>::
# Example: ["show", [:html, :xml], "users", false]
- def render_for_parts(parts, layout, options = {})
+ def render_for_parts(parts, layout_details, options = {})
parts[1] = {:formats => parts[1], :locales => [I18n.locale]}
tmp = view_paths.find_by_parts(*parts)
- layout = _pick_layout(*layout) unless tmp.exempt_from_layout?
-
+ layout = _pick_layout(*layout_details) unless
+ self.class.exempt_from_layout.include?(tmp.handler)
+
render_for_text(
@template._render_template_with_layout(tmp, layout, options, parts[3]))
end
View
2 actionpack/lib/action_controller/caching/actions.rb
@@ -121,7 +121,7 @@ def cache_layout?
end
def content_for_layout(controller)
- controller.response.layout && controller.response.template.instance_variable_get('@cached_content_for_layout')
+ controller.template.layout && controller.template.instance_variable_get('@cached_content_for_layout')
end
end
View
1 actionpack/lib/action_controller/dispatch/middlewares.rb
@@ -7,7 +7,6 @@
use lambda { ActionController::Base.session_store },
lambda { ActionController::Base.session_options }
-use "ActionDispatch::RewindableInput"
use "ActionDispatch::ParamsParser"
use "Rack::MethodOverride"
use "Rack::Head"
View
32 actionpack/lib/action_controller/testing/assertions/response.rb
@@ -22,6 +22,8 @@ module ResponseAssertions
# assert_response 401
#
def assert_response(type, message = nil)
+ validate_request!
+
clean_backtrace do
if [ :success, :missing, :redirect, :error ].include?(type) && @response.send("#{type}?")
assert_block("") { true } # to count the assertion
@@ -30,8 +32,8 @@ def assert_response(type, message = nil)
elsif type.is_a?(Symbol) && @response.response_code == ActionDispatch::StatusCodes::SYMBOL_TO_STATUS_CODE[type]
assert_block("") { true } # to count the assertion
else
- if @response.error?
- exception = @response.template.instance_variable_get(:@exception)
+ if @controller && @response.error?
+ exception = @controller.template.instance_variable_get(:@exception)
exception_message = exception && exception.message
assert_block(build_message(message, "Expected response to be a <?>, but was <?>\n<?>", type, @response.response_code, exception_message.to_s)) { false }
else
@@ -57,6 +59,8 @@ def assert_response(type, message = nil)
# assert_redirected_to @customer
#
def assert_redirected_to(options = {}, message=nil)
+ validate_request!
+
clean_backtrace do
assert_response(:redirect, message)
return true if options == @response.redirected_to
@@ -89,25 +93,27 @@ def assert_redirected_to(options = {}, message=nil)
# assert_template :partial => false
#
def assert_template(options = {}, message = nil)
+ validate_request!
+
clean_backtrace do
case options
when NilClass, String
- rendered = @response.rendered[:template].to_s
+ rendered = (@controller.template.rendered[:template] || []).map { |t| t.identifier }
msg = build_message(message,
"expecting <?> but rendering with <?>",
- options, rendered)
+ options, rendered.join(', '))
assert_block(msg) do
if options.nil?
- @response.rendered[:template].blank?
+ @controller.template.rendered[:template].blank?
else
- rendered.to_s.match(options)
+ rendered.any? { |t| t.match(options) }
end
end
when Hash
if expected_partial = options[:partial]
- partials = @response.rendered[:partials]
+ partials = @controller.template.rendered[:partials]
if expected_count = options[:count]
- found = partials.detect { |p, _| p.to_s.match(expected_partial) }
+ found = partials.detect { |p, _| p.identifier.match(expected_partial) }
actual_count = found.nil? ? 0 : found.second
msg = build_message(message,
"expecting ? to be rendered ? time(s) but rendered ? time(s)",
@@ -117,10 +123,10 @@ def assert_template(options = {}, message = nil)
msg = build_message(message,
"expecting partial <?> but action rendered <?>",
options[:partial], partials.keys)
- assert(partials.keys.any? { |p| p.to_s.match(expected_partial) }, msg)
+ assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg)
end
else
- assert @response.rendered[:partials].empty?,
+ assert @controller.template.rendered[:partials].empty?,
"Expected no partials to be rendered"
end
end
@@ -145,6 +151,12 @@ def normalize_argument_to_redirection(fragment)
@request.protocol + @request.host_with_port + after_routing
end
end
+
+ def validate_request!
+ unless @request.is_a?(ActionDispatch::Request)
+ raise ArgumentError, "@request must be an ActionDispatch::Request"
+ end
+ end
end
end
end
View
188 actionpack/lib/action_controller/testing/integration.rb
@@ -17,9 +17,6 @@ class Session
include ActionController::TestCase::Assertions
include ActionController::TestProcess
- # Rack application to use
- attr_accessor :application
-
# The integer HTTP status code of the last request.
attr_reader :status
@@ -60,12 +57,9 @@ class Session
# A running counter of the number of requests processed.
attr_accessor :request_count
- class MultiPartNeededException < Exception
- end
-
# Create and initialize a new Session instance.
def initialize(app = nil)
- @application = app || ActionController::Dispatcher.new
+ @app = app || ActionController::Dispatcher.new
reset!
end
@@ -255,47 +249,37 @@ def interpret_uri(path)
# Performs the actual request.
def process(method, path, parameters = nil, headers = nil)
- data = requestify(parameters)
path = interpret_uri(path) if path =~ %r{://}
- path = "/#{path}" unless path[0] == ?/
@path = path
- env = {}
- if method == :get
- env["QUERY_STRING"] = data
- data = nil
+ [ControllerCapture, ActionController::ProcessWithTest].each do |mod|
+ unless ActionController::Base < mod
+ ActionController::Base.class_eval { include mod }
+ end
end
- env["QUERY_STRING"] ||= ""
+ ActionController::Base.clear_last_instantiation!
- data = data.is_a?(IO) ? data : StringIO.new(data || '')
+ opts = {
+ :method => method.to_s.upcase,
+ :params => parameters,
- env.update(
- "REQUEST_METHOD" => method.to_s.upcase,
"SERVER_NAME" => host,
"SERVER_PORT" => (https? ? "443" : "80"),
"HTTPS" => https? ? "on" : "off",
"rack.url_scheme" => https? ? "https" : "http",
- "SCRIPT_NAME" => "",
"REQUEST_URI" => path,
"PATH_INFO" => path,
"HTTP_HOST" => host,
"REMOTE_ADDR" => remote_addr,
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
- "CONTENT_LENGTH" => data ? data.length.to_s : nil,
- "HTTP_COOKIE" => encode_cookies,
"HTTP_ACCEPT" => accept,
-
- "rack.version" => [0,1],
- "rack.input" => data,
- "rack.errors" => StringIO.new,
- "rack.multithread" => true,
- "rack.multiprocess" => true,
- "rack.run_once" => false,
-
- "rack.test" => true
- )
+ "HTTP_COOKIE" => cookies.inject("") { |string, (name, value)|
+ string << "#{name}=#{value}; "
+ }
+ }
+ env = ActionDispatch::Test::MockRequest.env_for(@path, opts)
(headers || {}).each do |key, value|
key = key.to_s.upcase.gsub(/-/, "_")
@@ -303,78 +287,32 @@ def process(method, path, parameters = nil, headers = nil)
env[key] = value
end
- [ControllerCapture, ActionController::ProcessWithTest].each do |mod|
- unless ActionController::Base < mod
- ActionController::Base.class_eval { include mod }
- end
- end
-
- ActionController::Base.clear_last_instantiation!
-
- app = @application
- # Rack::Lint doesn't accept String headers or bodies in Ruby 1.9
- unless RUBY_VERSION >= '1.9.0' && Rack.release <= '0.9.0'
- app = Rack::Lint.new(app)
- end
-
+ app = Rack::Lint.new(@app)
status, headers, body = app.call(env)
+ response = ::Rack::MockResponse.new(status, headers, body)
+
@request_count += 1
+ @request = Request.new(env)
- @html_document = nil
+ @response = Response.new
+ @response.status = @status = response.status
+ @response.headers = @headers = response.headers
+ @response.body = @body = response.body
- @status = status.to_i
@status_message = ActionDispatch::StatusCodes::STATUS_CODES[@status]
-
- @headers = Rack::Utils::HeaderHash.new(headers)
-
- (@headers['Set-Cookie'] || "").split("\n").each do |cookie|
- name, value = cookie.match(/^([^=]*)=([^;]*);/)[1,2]
- @cookies[name] = value
- end
-
- if body.is_a?(String)
- @body_parts = [body]
- @body = body
- else
- @body_parts = []
- body.each { |part| @body_parts << part.to_s }
- @body = @body_parts.join
- end
-
- if @controller = ActionController::Base.last_instantiation
- @request = @controller.request
- @response = @controller.response
- @controller.send(:set_test_assigns)
- else
- # Decorate responses from Rack Middleware and Rails Metal
- # as an Response for the purposes of integration testing
- @response = ActionDispatch::Response.new
- @response.status = status.to_s
- @response.headers.replace(@headers)
- @response.body = @body_parts
- end
+ @cookies.merge!(@response.cookies)
+ @html_document = nil
# Decorate the response with the standard behavior of the
# TestResponse so that things like assert_response can be
# used in integration tests.
@response.extend(TestResponseBehavior)
- return @status
- rescue MultiPartNeededException
- boundary = "----------XnJLe9ZIbbGUYtzPQJ16u1"
- status = process(method, path,
- multipart_body(parameters, boundary),
- (headers || {}).merge(
- {"CONTENT_TYPE" => "multipart/form-data; boundary=#{boundary}"}))
- return status
- end
-
- # Encode the cookies hash in a format suitable for passing to a
- # request.
- def encode_cookies
- cookies.inject("") do |string, (name, value)|
- string << "#{name}=#{value}; "
+ if @controller = ActionController::Base.last_instantiation
+ @controller.send(:set_test_assigns)
end
+
+ return @status
end
# Get a temporary URL writer object
@@ -389,72 +327,6 @@ def generic_url_rewriter
}
UrlRewriter.new(ActionDispatch::Request.new(env), {})
end
-
- def name_with_prefix(prefix, name)
- prefix ? "#{prefix}[#{name}]" : name.to_s
- end
-
- # Convert the given parameters to a request string. The parameters may
- # be a string, +nil+, or a Hash.
- def requestify(parameters, prefix=nil)
- if TestUploadedFile === parameters
- raise MultiPartNeededException
- elsif Hash === parameters
- return nil if parameters.empty?
- parameters.map { |k,v|
- requestify(v, name_with_prefix(prefix, k))
- }.join("&")
- elsif Array === parameters
- parameters.map { |v|
- requestify(v, name_with_prefix(prefix, ""))
- }.join("&")
- elsif prefix.nil?
- parameters
- else
- "#{CGI.escape(prefix)}=#{CGI.escape(parameters.to_s)}"
- end
- end
-
- def multipart_requestify(params, first=true)
- returning Hash.new do |p|
- params.each do |key, value|
- k = first ? CGI.escape(key.to_s) : "[#{CGI.escape(key.to_s)}]"
- if Hash === value
- multipart_requestify(value, false).each do |subkey, subvalue|
- p[k + subkey] = subvalue
- end
- else
- p[k] = value
- end
- end
- end
- end
-
- def multipart_body(params, boundary)
- multipart_requestify(params).map do |key, value|
- if value.respond_to?(:original_filename)
- File.open(value.path, "rb") do |f|
- f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
-
- <<-EOF
---#{boundary}\r
-Content-Disposition: form-data; name="#{key}"; filename="#{CGI.escape(value.original_filename)}"\r
-Content-Type: #{value.content_type}\r
-Content-Length: #{File.stat(value.path).size}\r
-\r
-#{f.read}\r
-EOF
- end
- else
-<<-EOF
---#{boundary}\r
-Content-Disposition: form-data; name="#{key}"\r
-\r
-#{value}\r
-EOF
- end
- end.join("")+"--#{boundary}--\r"
- end
end
# A module used to extend ActionController::Base, so that integration tests
@@ -513,8 +385,8 @@ def reset!
# By default, a single session is automatically created for you, but you
# can use this method to open multiple sessions that ought to be tested
# simultaneously.
- def open_session(application = nil)
- session = Integration::Session.new(application)
+ def open_session(app = nil)
+ session = Integration::Session.new(app)
# delegate the fixture accessors back to the test instance
extras = Module.new { attr_accessor :delegate, :test_result }
View
184 actionpack/lib/action_controller/testing/process.rb
@@ -1,8 +1,9 @@
require 'rack/session/abstract/id'
+
module ActionController #:nodoc:
class TestRequest < ActionDispatch::Request #:nodoc:
- attr_accessor :cookies, :session_options
- attr_accessor :query_parameters, :path, :session
+ attr_accessor :cookies
+ attr_accessor :query_parameters, :path
attr_accessor :host
def self.new(env = {})
@@ -13,18 +14,13 @@ def initialize(env = {})
super(Rack::MockRequest.env_for("/").merge(env))
@query_parameters = {}
- @session = TestSession.new
- default_rack_options = Rack::Session::Abstract::ID::DEFAULT_OPTIONS
- @session_options ||= {:id => generate_sid(default_rack_options[:sidbits])}.merge(default_rack_options)
+ self.session = TestSession.new
+ self.session_options = TestSession::DEFAULT_OPTIONS.merge(:id => ActiveSupport::SecureRandom.hex(16))
initialize_default_values
initialize_containers
end
- def reset_session
- @session.reset
- end
-
# Wraps raw_post in a StringIO.
def body_stream #:nodoc:
StringIO.new(raw_post)
@@ -124,10 +120,6 @@ def user_agent=(user_agent)
end
private
- def generate_sid(sidbits)
- "%0#{sidbits / 4}x" % rand(2**sidbits - 1)
- end
-
def initialize_containers
@cookies = {}
end
@@ -156,54 +148,8 @@ def url_encoded_request_parameters
# A refactoring of TestResponse to allow the same behavior to be applied
# to the "real" CgiResponse class in integration tests.
module TestResponseBehavior #:nodoc:
- # The response code of the request
- def response_code
- status.to_s[0,3].to_i rescue 0
- end
-
- # Returns a String to ensure compatibility with Net::HTTPResponse
- def code
- status.to_s.split(' ')[0]
- end
-
- def message
- status.to_s.split(' ',2)[1]
- end
-
- # Was the response successful?
- def success?
- (200..299).include?(response_code)
- end
-
- # Was the URL not found?
- def missing?
- response_code == 404
- end
-
- # Were we redirected?
- def redirect?
- (300..399).include?(response_code)
- end
-
- # Was there a server-side error?
- def error?
- (500..599).include?(response_code)
- end
-
- alias_method :server_error?, :error?
-
- # Was there a client client?
- def client_error?
- (400..499).include?(response_code)
- end
-
- # Returns the redirection location or nil
- def redirect_url
- headers['Location']
- end
-
- # Does the redirect location match this regexp pattern?
- def redirect_url_match?( pattern )
+ def redirect_url_match?(pattern)
+ ::ActiveSupport::Deprecation.warn("response.redirect_url_match? is deprecated. Use assert_match(/foo/, response.redirect_url) instead", caller)
return false if redirect_url.nil?
p = Regexp.new(pattern) if pattern.class == String
p = pattern if pattern.class == Regexp
@@ -214,12 +160,13 @@ def redirect_url_match?( pattern )
# Returns the template of the file which was used to
# render this response (or nil)
def rendered
- template.instance_variable_get(:@_rendered)
+ ActiveSupport::Deprecation.warn("response.rendered has been deprecated. Use tempate.rendered instead", caller)
+ @template.instance_variable_get(:@_rendered)
end
# A shortcut to the flash. Returns an empty hash if no session flash exists.
def flash
- session['flash'] || {}
+ request.session['flash'] || {}
end
# Do we have a flash?
@@ -244,26 +191,16 @@ def has_session_object?(name=nil)
# A shortcut to the template.assigns
def template_objects
- template.assigns || {}
+ ActiveSupport::Deprecation.warn("response.template_objects has been deprecated. Use tempate.assigns instead", caller)
+ @template.assigns || {}
end
# Does the specified template object exist?
def has_template_object?(name=nil)
+ ActiveSupport::Deprecation.warn("response.has_template_object? has been deprecated. Use tempate.assigns[name].nil? instead", caller)
!template_objects[name].nil?
end
- # Returns the response cookies, converted to a Hash of (name => value) pairs
- #
- # assert_equal 'AuthorOfNewPage', r.cookies['author']
- def cookies
- cookies = {}
- Array(headers['Set-Cookie']).each do |cookie|
- key, value = cookie.split(";").first.split("=").map {|val| Rack::Utils.unescape(val)}
- cookies[key] = value
- end
- cookies
- end
-
# Returns binary content (downloadable file), converted to a String
def binary_content
raise "Response body is not a Proc: #{body_parts.inspect}" unless body_parts.kind_of?(Proc)
@@ -293,62 +230,12 @@ def recycle!
end
end
- class TestSession < Hash #:nodoc:
- attr_accessor :session_id
-
- def initialize(attributes = nil)
- reset_session_id
- replace_attributes(attributes)
- end
-
- def reset
- reset_session_id
- replace_attributes({ })
- end
-
- def data
- to_hash
- end
-
- def [](key)
- super(key.to_s)
- end
-
- def []=(key, value)
- super(key.to_s, value)
- end
-
- def update(hash = nil)
- if hash.nil?
- ActiveSupport::Deprecation.warn('use replace instead', caller)
- replace({})
- else
- super(hash)
- end
- end
+ class TestSession < ActionDispatch::Session::AbstractStore::SessionHash #:nodoc:
+ DEFAULT_OPTIONS = ActionDispatch::Session::AbstractStore::DEFAULT_OPTIONS
- def delete(key = nil)
- if key.nil?
- ActiveSupport::Deprecation.warn('use clear instead', caller)
- clear
- else
- super(key.to_s)
- end
- end
-
- def close
- ActiveSupport::Deprecation.warn('sessions should no longer be closed', caller)
- end
-
- private
-
- def reset_session_id
- @session_id = ''
- end
-
- def replace_attributes(attributes = nil)
- attributes ||= {}
- replace(attributes.stringify_keys)
+ def initialize(session = {})
+ replace(session.stringify_keys)
+ @loaded = true
end
end
@@ -363,34 +250,7 @@ def replace_attributes(attributes = nil)
#
# Pass a true third parameter to ensure the uploaded file is opened in binary mode (only required for Windows):
# post :change_avatar, :avatar => ActionController::TestUploadedFile.new(ActionController::TestCase.fixture_path + '/files/spongebob.png', 'image/png', :binary)
- require 'tempfile'
- class TestUploadedFile
- # The filename, *not* including the path, of the "uploaded" file
- attr_reader :original_filename
-
- # The content type of the "uploaded" file
- attr_accessor :content_type
-
- def initialize(path, content_type = Mime::TEXT, binary = false)
- raise "#{path} file does not exist" unless File.exist?(path)
- @content_type = content_type
- @original_filename = path.sub(/^.*#{File::SEPARATOR}([^#{File::SEPARATOR}]+)$/) { $1 }
- @tempfile = Tempfile.new(@original_filename)
- @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
- @tempfile.binmode if binary
- FileUtils.copy_file(path, @tempfile.path)
- end
-
- def path #:nodoc:
- @tempfile.path
- end
-
- alias local_path path
-
- def method_missing(method_name, *args, &block) #:nodoc:
- @tempfile.__send__(method_name, *args, &block)
- end
- end
+ TestUploadedFile = ActionDispatch::Test::UploadedFile
module TestProcess
def self.included(base)
@@ -460,9 +320,9 @@ def xml_http_request(request_method, action, parameters = nil, session = nil, fl
def assigns(key = nil)
if key.nil?
- @response.template.assigns
+ @controller.template.assigns
else
- @response.template.assigns[key.to_s]
+ @controller.template.assigns[key.to_s]
end
end
@@ -574,7 +434,7 @@ def set_test_assigns
(instance_variable_names - self.class.protected_instance_variables).each do |var|
name, value = var[1..-1], instance_variable_get(var)
@assigns[name] = value
- response.template.assigns[name] = value if response
+ @template.assigns[name] = value if response
end
end
end
View
15 actionpack/lib/action_dispatch.rb
@@ -32,13 +32,8 @@
end
require 'active_support/core/all'
-$:.unshift "#{File.dirname(__FILE__)}/action_dispatch/vendor/rack-1.0"
-begin
- gem 'rack', '~> 1.0.0'
- require 'rack'
-rescue Gem::LoadError
- require 'action_dispatch/vendor/rack-1.0/rack'
-end
+gem 'rack', '~> 1.0.0'
+require 'rack'
module ActionDispatch
autoload :Request, 'action_dispatch/http/request'
@@ -48,7 +43,6 @@ module ActionDispatch
autoload :Failsafe, 'action_dispatch/middleware/failsafe'
autoload :ParamsParser, 'action_dispatch/middleware/params_parser'
autoload :Reloader, 'action_dispatch/middleware/reloader'
- autoload :RewindableInput, 'action_dispatch/middleware/rewindable_input'
autoload :MiddlewareStack, 'action_dispatch/middleware/stack'
module Http
@@ -60,6 +54,11 @@ module Session
autoload :CookieStore, 'action_dispatch/middleware/session/cookie_store'
autoload :MemCacheStore, 'action_dispatch/middleware/session/mem_cache_store'
end
+
+ module Test
+ autoload :UploadedFile, 'action_dispatch/test/uploaded_file'
+ autoload :MockRequest, 'action_dispatch/test/mock'
+ end
end
autoload :Mime, 'action_dispatch/http/mime_type'
View
24 actionpack/lib/action_dispatch/http/request.rb
@@ -93,7 +93,11 @@ def content_type
end
end
end
-
+
+ def media_type
+ content_type.to_s
+ end
+
# Returns the accepted MIME type for the request.
def accepts
@accepts ||= begin
@@ -397,7 +401,7 @@ def parameters
alias_method :params, :parameters
def path_parameters=(parameters) #:nodoc:
- @env["rack.routing_args"] = parameters
+ @env["action_dispatch.request.path_parameters"] = parameters
@symbolized_path_parameters = @parameters = nil
end
@@ -413,7 +417,7 @@ def symbolized_path_parameters
#
# See <tt>symbolized_path_parameters</tt> for symbolized keys.
def path_parameters
- @env["rack.routing_args"] ||= {}
+ @env["action_dispatch.request.path_parameters"] ||= {}
end
# The request body is an IO input stream. If the RAW_POST_DATA environment
@@ -447,23 +451,15 @@ def body_stream #:nodoc:
@env['rack.input']
end
- def session
- @env['rack.session'] ||= {}
+ def reset_session
+ self.session_options.delete(:id)
+ self.session = {}
end
def session=(session) #:nodoc:
@env['rack.session'] = session
end
- def reset_session
- @env['rack.session.options'].delete(:id)
- @env['rack.session'] = {}
- end
-
- def session_options
- @env['rack.session.options'] ||= {}
- end
-
def session_options=(options)
@env['rack.session.options'] = options
end
View
105 actionpack/lib/action_dispatch/http/response.rb
@@ -34,15 +34,78 @@ class Response < Rack::Response
DEFAULT_HEADERS = { "Cache-Control" => "no-cache" }
attr_accessor :request
- attr_accessor :session, :assigns, :template, :layout
attr_accessor :redirected_to, :redirected_to_method_params
+ attr_writer :header
+ alias_method :headers=, :header=
+
+ def template
+ ActiveSupport::Deprecation.warn("response.template has been deprecated. Use controller.template instead", caller)
+ @template
+ end
+ attr_writer :template
+
+ def session
+ ActiveSupport::Deprecation.warn("response.session has been deprecated. Use request.session instead", caller)
+ @request.session
+ end
+
+ def assigns
+ ActiveSupport::Deprecation.warn("response.assigns has been deprecated. Use controller.assigns instead", caller)
+ @template.controller.assigns
+ end
+
+ def layout
+ ActiveSupport::Deprecation.warn("response.layout has been deprecated. Use template.layout instead", caller)
+ @template.layout
+ end
+
delegate :default_charset, :to => 'ActionController::Base'
def initialize
super
@header = Rack::Utils::HeaderHash.new(DEFAULT_HEADERS)
- @session, @assigns = [], []
+ end
+
+ # The response code of the request
+ def response_code
+ status.to_s[0,3].to_i rescue 0
+ end
+
+ # Returns a String to ensure compatibility with Net::HTTPResponse
+ def code
+ status.to_s.split(' ')[0]
+ end
+
+ def message
+ status.to_s.split(' ',2)[1] || StatusCodes::STATUS_CODES[response_code]
+ end
+
+ # Was the response successful?
+ def success?
+ (200..299).include?(response_code)
+ end
+
+ # Was the URL not found?
+ def missing?
+ response_code == 404
+ end
+
+ # Were we redirected?
+ def redirect?
+ (300..399).include?(response_code)
+ end
+
+ # Was there a server-side error?
+ def error?
+ (500..599).include?(response_code)
+ end
+
+ alias_method :server_error?, :error?
+
+ # Was there a client client?
+ def client_error?
+ (400..499).include?(response_code)
end
def body
@@ -53,7 +116,7 @@ def body
def body=(body)
@body =
- if body.is_a?(String)
+ if body.respond_to?(:to_str)
[body]
else
body
@@ -64,9 +127,14 @@ def body_parts
@body
end
- def location; headers['Location'] end
- def location=(url) headers['Location'] = url end
+ def location
+ headers['Location']
+ end
+ alias_method :redirect_url, :location
+ def location=(url)
+ headers['Location'] = url
+ end
# Sets the HTTP response's content MIME type. For example, in the controller
# you could write this:
@@ -165,8 +233,6 @@ def each(&callback)
if @body.respond_to?(:call)
@writer = lambda { |x| callback.call(x) }
@body.call(self, self)
- elsif @body.is_a?(String)
- callback.call(@body)
else
@body.each(&callback)
end
@@ -192,6 +258,23 @@ def set_cookie(key, value)
super(key, value)
end
+ # Returns the response cookies, converted to a Hash of (name => value) pairs
+ #
+ # assert_equal 'AuthorOfNewPage', r.cookies['author']
+ def cookies
+ cookies = {}
+ if header = headers['Set-Cookie']
+ header = header.split("\n") if header.respond_to?(:to_str)
+ header.each do |cookie|
+ if pair = cookie.split(';').first
+ key, value = pair.split("=").map { |v| Rack::Utils.unescape(v) }
+ cookies[key] = value
+ end
+ end
+ end
+ cookies
+ end
+
private
def handle_conditional_get!
if etag? || last_modified?
@@ -245,7 +328,13 @@ def convert_language!
end
def convert_cookies!
- headers['Set-Cookie'] = Array(headers['Set-Cookie']).compact
+ headers['Set-Cookie'] =
+ if header = headers['Set-Cookie']
+ header = header.split("\n") if header.respond_to?(:to_str)
+ header.compact
+ else
+ []
+ end
end
end
end
View
6 actionpack/lib/action_dispatch/middleware/failsafe.rb
@@ -11,7 +11,7 @@ def call(env)
@app.call(env)
rescue Exception => exception
# Reraise exception in test environment
- if env["rack.test"]
+ if defined?(Rails) && Rails.env.test?
raise exception
else
failsafe_response(exception)
@@ -29,9 +29,9 @@ def failsafe_response(exception)
def failsafe_response_body
error_path = "#{self.class.error_file_path}/500.html"
if File.exist?(error_path)
- File.read(error_path)
+ [File.read(error_path)]
else
- "<html><body><h1>500 Internal Server Error</h1></body></html>"
+ ["<html><body><h1>500 Internal Server Error</h1></body></html>"]
end
end
View
19 actionpack/lib/action_dispatch/middleware/rewindable_input.rb
@@ -1,19 +0,0 @@
-module ActionDispatch
- class RewindableInput
- def initialize(app)
- @app = app
- end
-
- def call(env)
- begin
- env['rack.input'].rewind
- rescue NoMethodError, Errno::ESPIPE
- # Handles exceptions raised by input streams that cannot be rewound
- # such as when using plain CGI under Apache
- env['rack.input'] = StringIO.new(env['rack.input'].read)
- end
-
- @app.call(env)
- end
- end
-end
View
30 actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
@@ -26,12 +26,12 @@ def session_id
def [](key)
load! unless @loaded
- super
+ super(key.to_s)
end
def []=(key, value)
load! unless @loaded
- super
+ super(key.to_s, value)
end
def to_hash
@@ -40,6 +40,24 @@ def to_hash
h
end
+ def update(hash = nil)
+ if hash.nil?
+ ActiveSupport::Deprecation.warn('use replace instead', caller)
+ replace({})
+ else
+ super(hash.stringify_keys)
+ end
+ end
+
+ def delete(key = nil)
+ if key.nil?
+ ActiveSupport::Deprecation.warn('use clear instead', caller)
+ clear
+ else
+ super(key.to_s)
+ end
+ end
+
def data
ActiveSupport::Deprecation.warn(
"ActionController::Session::AbstractStore::SessionHash#data " +
@@ -47,6 +65,10 @@ def data
to_hash
end
+ def close
+ ActiveSupport::Deprecation.warn('sessions should no longer be closed', caller)
+ end
+
def inspect
load! unless @loaded
super
@@ -61,7 +83,7 @@ def load!
stale_session_check! do
id, session = @by.send(:load_session, @env)
(@env[ENV_SESSION_OPTIONS_KEY] ||= {})[:id] = id
- replace(session)
+ replace(session.stringify_keys)
@loaded = true
end
end
@@ -74,7 +96,7 @@ def stale_session_check!
# Note that the regexp does not allow $1 to end with a ':'
$1.constantize
rescue LoadError, NameError => const_error
- raise ActionController::SessionRestoreError, "Session contains objects whose class definition isn\\'t available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: \#{const_error.message} [\#{const_error.class}])\n"
+ raise ActionController::SessionRestoreError, "Session contains objects whose class definition isn't available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: #{const_error.message} [#{const_error.class}])\n"
end
retry
View
7 actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -143,7 +143,8 @@ def load_session(env)
request = Rack::Request.new(env)
session_data = request.cookies[@key]
data = unmarshal(session_data) || persistent_session_id!({})
- [data[:session_id], data]
+ data.stringify_keys!
+ [data["session_id"], data]
end
# Marshal a session hash into safe cookie data. Include an integrity hash.
@@ -206,12 +207,12 @@ def persistent_session_id!(data)
end
def inject_persistent_session_id(data)
- requires_session_id?(data) ? { :session_id => generate_sid } : {}
+ requires_session_id?(data) ? { "session_id" => generate_sid } : {}
end
def requires_session_id?(data)
if data
- data.respond_to?(:key?) && !data.key?(:session_id)
+ data.respond_to?(:key?) && !data.key?("session_id")
else
true
end
View
114 actionpack/lib/action_dispatch/test/mock.rb
@@ -0,0 +1,114 @@
+module ActionDispatch
+ module Test
+ class MockRequest < Rack::MockRequest
+ MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
+
+ class << self
+ def env_for(path, opts)
+ method = (opts[:method] || opts["REQUEST_METHOD"]).to_s.upcase
+ opts[:method] = opts["REQUEST_METHOD"] = method
+
+ path = "/#{path}" unless path[0] == ?/
+ uri = URI.parse(path)
+ uri.host ||= "example.org"
+
+ if URI::HTTPS === uri
+ opts.update("SERVER_PORT" => "443", "HTTPS" => "on")
+ end
+
+ if method == "POST" && !opts.has_key?(:input)
+ opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
+
+ multipart = opts[:params].respond_to?(:any?) && opts[:params].any? { |k, v| UploadedFile === v }
+ if multipart
+ opts[:input] = multipart_body(opts.delete(:params))
+ opts["CONTENT_LENGTH"] ||= opts[:input].length.to_s
+ opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}"
+ else
+ params = opts.delete(:params)
+ opts[:input] = case params
+ when Hash then requestify(params)
+ when nil then ""
+ else params
+ end
+ end
+ end
+
+ params = opts[:params] || {}
+ if params.is_a?(String)
+ if method == "GET"
+ uri.query = params
+ else
+ opts[:input] = params
+ end
+ else
+ params.update(::Rack::Utils.parse_query(uri.query))
+ uri.query = requestify(params)
+ end
+
+ ::Rack::MockRequest.env_for(uri.to_s, opts)
+ end
+
+ private
+ def requestify(value, prefix = nil)
+ case value
+ when Array
+ value.map do |v|
+ requestify(v, "#{prefix}[]")
+ end.join("&")
+ when Hash
+ value.map do |k, v|
+ requestify(v, prefix ? "#{prefix}[#{::Rack::Utils.escape(k)}]" : ::Rack::Utils.escape(k))
+ end.join("&")
+ else
+ "#{prefix}=#{::Rack::Utils.escape(value)}"
+ end
+ end
+
+ def multipart_requestify(params, first=true)
+ p = Hash.new
+
+ params.each do |key, value|
+ k = first ? key.to_s : "[#{key}]"
+
+ if Hash === value
+ multipart_requestify(value, false).each do |subkey, subvalue|
+ p[k + subkey] = subvalue
+ end
+ else
+ p[k] = value
+ end
+ end
+
+ return p
+ end
+
+ def multipart_body(params)
+ multipart_requestify(params).map do |key, value|
+ if value.respond_to?(:original_filename)
+ ::File.open(value.path, "rb") do |f|
+ f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
+
+ <<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{key}"; filename="#{::Rack::Utils.escape(value.original_filename)}"\r
+Content-Type: #{value.content_type}\r
+Content-Length: #{::File.stat(value.path).size}\r
+\r
+#{f.read}\r
+EOF
+ end
+ else
+<<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{key}"\r
+\r
+#{value}\r
+EOF
+ end
+ end.join("")+"--#{MULTIPART_BOUNDARY}--\r"
+ end
+ end
+ end
+ end
+end
View
33 actionpack/lib/action_dispatch/test/uploaded_file.rb
@@ -0,0 +1,33 @@
+require "tempfile"
+
+module ActionDispatch
+ module Test
+ class UploadedFile
+ # The filename, *not* including the path, of the "uploaded" file
+ attr_reader :original_filename
+
+ # The content type of the "uploaded" file
+ attr_accessor :content_type
+
+ def initialize(path, content_type = "text/plain", binary = false)
+ raise "#{path} file does not exist" unless ::File.exist?(path)
+ @content_type = content_type
+ @original_filename = ::File.basename(path)
+ @tempfile = Tempfile.new(@original_filename)
+ @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
+ @tempfile.binmode if binary
+ FileUtils.copy_file(path, @tempfile.path)
+ end
+
+ def path
+ @tempfile.path
+ end
+
+ alias_method :local_path, :path
+
+ def method_missing(method_name, *args, &block) #:nodoc:
+ @tempfile.__send__(method_name, *args, &block)
+ end
+ end
+ end
+end
View
89 actionpack/lib/action_dispatch/vendor/rack-1.0/rack.rb
@@ -1,89 +0,0 @@
-# Copyright (C) 2007, 2008, 2009 Christian Neukirchen <purl.org/net/chneukirchen>
-#
-# Rack is freely distributable under the terms of an MIT-style license.
-# See COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-$:.unshift(File.expand_path(File.dirname(__FILE__)))
-
-
-# The Rack main module, serving as a namespace for all core Rack
-# modules and classes.
-#
-# All modules meant for use in your application are <tt>autoload</tt>ed here,
-# so it should be enough just to <tt>require rack.rb</tt> in your code.
-
-module Rack
- # The Rack protocol version number implemented.
- VERSION = [0,1]
-
- # Return the Rack protocol version as a dotted string.
- def self.version
- VERSION.join(".")
- end
-
- # Return the Rack release as a dotted string.
- def self.release
- "1.0 bundled"
- end
-
- autoload :Builder, "rack/builder"
- autoload :Cascade, "rack/cascade"
- autoload :Chunked, "rack/chunked"
- autoload :CommonLogger, "rack/commonlogger"
- autoload :ConditionalGet, "rack/conditionalget"
- autoload :ContentLength, "rack/content_length"
- autoload :ContentType, "rack/content_type"
- autoload :File, "rack/file"
- autoload :Deflater, "rack/deflater"
- autoload :Directory, "rack/directory"
- autoload :ForwardRequest, "rack/recursive"
- autoload :Handler, "rack/handler"
- autoload :Head, "rack/head"
- autoload :Lint, "rack/lint"
- autoload :Lock, "rack/lock"
- autoload :MethodOverride, "rack/methodoverride"
- autoload :Mime, "rack/mime"
- autoload :Recursive, "rack/recursive"
- autoload :Reloader, "rack/reloader"
- autoload :ShowExceptions, "rack/showexceptions"
- autoload :ShowStatus, "rack/showstatus"
- autoload :Static, "rack/static"
- autoload :URLMap, "rack/urlmap"
- autoload :Utils, "rack/utils"
-
- autoload :MockRequest, "rack/mock"
- autoload :MockResponse, "rack/mock"
-
- autoload :Request, "rack/request"
- autoload :Response, "rack/response"
-
- module Auth
- autoload :Basic, "rack/auth/basic"
- autoload :AbstractRequest, "rack/auth/abstract/request"
- autoload :AbstractHandler, "rack/auth/abstract/handler"
- autoload :OpenID, "rack/auth/openid"
- module Digest
- autoload :MD5, "rack/auth/digest/md5"
- autoload :Nonce, "rack/auth/digest/nonce"
- autoload :Params, "rack/auth/digest/params"
- autoload :Request, "rack/auth/digest/request"
- end
- end
-
- module Session
- autoload :Cookie, "rack/session/cookie"
- autoload :Pool, "rack/session/pool"
- autoload :Memcache, "rack/session/memcache"
- end
-
- # *Adapters* connect Rack with third party web frameworks.
- #
- # Rack includes an adapter for Camping, see README for other
- # frameworks supporting Rack in their code bases.
- #
- # Refer to the submodules for framework-specific calling details.
-
- module Adapter
- autoload :Camping, "rack/adapter/camping"
- end
-end
View
22 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/adapter/camping.rb
@@ -1,22 +0,0 @@
-module Rack
- module Adapter
- class Camping
- def initialize(app)
- @app = app
- end
-
- def call(env)
- env["PATH_INFO"] ||= ""
- env["SCRIPT_NAME"] ||= ""
- controller = @app.run(env['rack.input'], env)
- h = controller.headers
- h.each_pair do |k,v|
- if v.kind_of? URI
- h[k] = v.to_s
- end
- end
- [controller.status, controller.headers, [controller.body.to_s]]
- end
- end
- end
-end
View
37 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/abstract/handler.rb
@@ -1,37 +0,0 @@
-module Rack
- module Auth
- # Rack::Auth::AbstractHandler implements common authentication functionality.
- #
- # +realm+ should be set for all handlers.
-
- class AbstractHandler
-
- attr_accessor :realm
-
- def initialize(app, realm=nil, &authenticator)
- @app, @realm, @authenticator = app, realm, authenticator
- end
-
-
- private
-
- def unauthorized(www_authenticate = challenge)
- return [ 401,
- { 'Content-Type' => 'text/plain',
- 'Content-Length' => '0',
- 'WWW-Authenticate' => www_authenticate.to_s },
- []
- ]
- end
-
- def bad_request
- return [ 400,
- { 'Content-Type' => 'text/plain',
- 'Content-Length' => '0' },
- []
- ]
- end
-
- end
- end
-end
View
37 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/abstract/request.rb
@@ -1,37 +0,0 @@
-module Rack
- module Auth
- class AbstractRequest
-
- def initialize(env)
- @env = env
- end
-
- def provided?
- !authorization_key.nil?
- end
-
- def parts
- @parts ||= @env[authorization_key].split(' ', 2)
- end
-
- def scheme
- @scheme ||= parts.first.downcase.to_sym
- end
-
- def params
- @params ||= parts.last
- end
-
-
- private
-
- AUTHORIZATION_KEYS = ['HTTP_AUTHORIZATION', 'X-HTTP_AUTHORIZATION', 'X_HTTP_AUTHORIZATION']
-
- def authorization_key
- @authorization_key ||= AUTHORIZATION_KEYS.detect { |key| @env.has_key?(key) }
- end
-
- end
-
- end
-end
View
58 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/basic.rb
@@ -1,58 +0,0 @@
-require 'rack/auth/abstract/handler'
-require 'rack/auth/abstract/request'
-
-module Rack
- module Auth
- # Rack::Auth::Basic implements HTTP Basic Authentication, as per RFC 2617.
- #
- # Initialize with the Rack application that you want protecting,
- # and a block that checks if a username and password pair are valid.
- #
- # See also: <tt>example/protectedlobster.rb</tt>
-
- class Basic < AbstractHandler
-
- def call(env)
- auth = Basic::Request.new(env)
-
- return unauthorized unless auth.provided?
-
- return bad_request unless auth.basic?
-
- if valid?(auth)
- env['REMOTE_USER'] = auth.username
-
- return @app.call(env)
- end
-
- unauthorized
- end
-
-
- private
-
- def challenge
- 'Basic realm="%s"' % realm
- end
-
- def valid?(auth)
- @authenticator.call(*auth.credentials)
- end
-
- class Request < Auth::AbstractRequest
- def basic?
- :basic == scheme
- end
-
- def credentials
- @credentials ||= params.unpack("m*").first.split(/:/, 2)
- end
-
- def username
- credentials.first
- end
- end
-
- end
- end
-end
View
124 actionpack/lib/action_dispatch/vendor/rack-1.0/rack/auth/digest/md5.rb
@@ -1,124 +0,0 @@
-require 'rack/auth/abstract/handler'
-require 'rack/auth/digest/request'
-require 'rack/auth/digest/params'
-require 'rack/auth/digest/nonce'
-require 'digest/md5'
-
-module Rack
- module Auth
- module Digest
- # Rack::Auth::Digest::MD5 implements the MD5 algorithm version of
- # HTTP Digest Authentication, as per RFC 2617.
- #
- # Initialize with the [Rack] application that you want protecting,
- # and a block that looks up a plaintext password for a given username.
- #
- # +opaque+ needs to be set to a constant base64/hexadecimal string.
- #
- class MD5 < AbstractHandler
-
- attr_accessor :opaque
-
- attr_writer :passwords_hashed
-
- def initialize(*args)
- super
- @passwords_hashed = nil
- end
-
- def passwords_hashed?
- !!@passwords_hashed
- end
-
- def call(env)
- auth = Request.new(env)
-
- unless auth.provided?
- return unauthorized
- end
-
- if !auth.digest? || !auth.correct_uri? || !valid_qop?(auth)
- return bad_request
- end
-
- if valid?(auth)
- if auth.nonce.stale?
- return unauthorized(challenge(:stale => true))
- else
- env['REMOTE_USER'] = auth.username
-
- return @app.call(env)
- end
- end
-
- unauthorized
- end
-
-
- private
-
- QOP = 'auth'.freeze
-
- def params(hash = {})
- Params.new do |params|
- params['realm'] = realm
- params['nonce'] = Nonce.new.to_s
- params['opaque'] = H(opaque)
- params['qop'] = QOP
-
- hash.each { |k, v| params[k] = v }
- end
- end
-
- def challenge(hash = {})
- "Digest #{params(hash)}"
- end
-
- def valid?(auth)
- valid_opaque?(auth) && valid_nonce?(auth) && valid_digest?(auth)
- end
-
- def valid_qop?(auth)
- QOP == auth.qop
- end
-
- def valid_opaque?(auth)
- H(opaque) == auth.opaque
- end
-
- def valid_nonce?(auth)
- auth.nonce.valid?
- end
-
- def valid_digest?(auth)
- digest(auth, @authenticator.call(auth.username)) == auth.response
- end
-
- def md5(data)
- ::Digest::MD5.hexdigest(data)
- end
-
- alias :H :md5
-
- def KD(secret, data)
- H([secret, data] * ':')
- end
-
- def A1(auth, password)
- [ auth.username, auth.realm, password ] * ':'
- end
-
- def A2(auth)
- [ auth.method, auth.uri ] * ':'