Permalink
Browse files

Merge commit 'mainstream/master'

Conflicts:

	activerecord/lib/active_record/association_preload.rb
  • Loading branch information...
2 parents 01159a6 + 4df45d8 commit 6090513cfb8acb5554a6653a6f2cb87648585d41 @lifo lifo committed Oct 5, 2008
Showing with 1,142 additions and 345 deletions.
  1. +3 −0 actionmailer/lib/action_mailer/base.rb
  2. +2 −0 actionmailer/test/abstract_unit.rb
  3. +2 −0 actionmailer/test/fixtures/test_mailer/body_ivar.erb
  4. +12 −0 actionmailer/test/mail_service_test.rb
  5. +7 −12 actionpack/lib/action_controller/base.rb
  6. +29 −1 actionpack/lib/action_controller/dispatcher.rb
  7. +1 −1 actionpack/lib/action_controller/integration.rb
  8. +2 −3 actionpack/lib/action_controller/request.rb
  9. +17 −113 actionpack/lib/action_controller/rescue.rb
  10. +1 −1 actionpack/lib/action_controller/test_case.rb
  11. +10 −8 actionpack/lib/action_view/base.rb
  12. +8 −2 actionpack/lib/action_view/helpers/form_tag_helper.rb
  13. +1 −1 actionpack/test/abstract_unit.rb
  14. +40 −1 actionpack/test/controller/render_test.rb
  15. +11 −24 actionpack/test/controller/rescue_test.rb
  16. +6 −0 actionpack/test/template/form_tag_helper_test.rb
  17. +17 −15 activerecord/lib/active_record/association_preload.rb
  18. +1 −1 activerecord/lib/active_record/associations/association_proxy.rb
  19. +11 −0 activerecord/lib/active_record/associations/has_many_through_association.rb
  20. +3 −1 activerecord/lib/active_record/attribute_methods.rb
  21. +4 −4 activerecord/lib/active_record/base.rb
  22. +8 −4 activerecord/lib/active_record/calculations.rb
  23. +17 −14 activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
  24. +3 −3 activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
  25. +4 −4 activerecord/lib/active_record/dynamic_finder_match.rb
  26. +82 −53 activerecord/lib/active_record/reflection.rb
  27. +5 −0 activerecord/test/cases/active_schema_test_mysql.rb
  28. +16 −0 activerecord/test/cases/associations/eager_test.rb
  29. +1 −0 activerecord/test/cases/associations/has_many_associations_test.rb
  30. +16 −1 activerecord/test/cases/associations/has_many_through_associations_test.rb
  31. +3 −3 activerecord/test/cases/calculations_test.rb
  32. +22 −5 activerecord/test/cases/finder_test.rb
  33. +4 −0 activerecord/test/cases/reflection_test.rb
  34. +20 −0 activerecord/test/cases/reload_models_test.rb
  35. +2 −0 activerecord/test/models/post.rb
  36. +2 −1 activeresource/lib/active_resource/base.rb
  37. +24 −0 activeresource/test/base_test.rb
  38. +2 −0 activesupport/CHANGELOG
  39. +2 −0 activesupport/lib/active_support.rb
  40. +33 −12 activesupport/lib/active_support/core_ext/object/extending.rb
  41. +108 −0 activesupport/lib/active_support/rescuable.rb
  42. +2 −2 activesupport/lib/active_support/secure_random.rb
  43. +7 −4 activesupport/lib/active_support/testing/core_ext/test/unit/assertions.rb
  44. +75 −0 activesupport/test/rescuable_test.rb
  45. +4 −0 activesupport/test/secure_random_test.rb
  46. +18 −0 activesupport/test/test_test.rb
  47. +62 −0 railties/configs/databases/ibm_db.yml
  48. +1 −1 railties/lib/initializer.rb
  49. +3 −3 railties/lib/rails/gem_builder.rb
  50. +111 −31 railties/lib/rails/gem_dependency.rb
  51. +1 −1 railties/lib/rails/plugin.rb
  52. +93 −0 railties/lib/rails/vendor_gem_source_index.rb
  53. +1 −1 railties/lib/rails_generator/generators/applications/app/app_generator.rb
  54. +1 −1 railties/lib/tasks/databases.rake
  55. +12 −8 railties/lib/tasks/gems.rake
  56. +44 −5 railties/test/gem_dependency_test.rb
  57. +28 −0 railties/test/vendor/gems/dummy-gem-a-0.4.0/.specification
  58. +1 −0 railties/test/vendor/gems/dummy-gem-a-0.4.0/lib/dummy-gem-a.rb
  59. +28 −0 railties/test/vendor/gems/dummy-gem-b-0.4.0/.specification
  60. +1 −0 railties/test/vendor/gems/dummy-gem-b-0.4.0/lib/dummy-gem-b.rb
  61. +28 −0 railties/test/vendor/gems/dummy-gem-b-0.6.0/.specification
  62. +1 −0 railties/test/vendor/gems/dummy-gem-b-0.6.0/lib/dummy-gem-b.rb
  63. +28 −0 railties/test/vendor/gems/dummy-gem-c-0.4.0/.specification
  64. +1 −0 railties/test/vendor/gems/dummy-gem-c-0.4.0/lib/dummy-gem-c.rb
  65. +28 −0 railties/test/vendor/gems/dummy-gem-c-0.6.0/.specification
  66. +1 −0 railties/test/vendor/gems/dummy-gem-c-0.6.0/lib/dummy-gem-c.rb
@@ -296,6 +296,9 @@ class Base
@@default_implicit_parts_order = [ "text/html", "text/enriched", "text/plain" ]
cattr_accessor :default_implicit_parts_order
+ cattr_reader :protected_instance_variables
+ @@protected_instance_variables = %w(@body)
+
# Specify the BCC addresses for the message
adv_attr_accessor :bcc
@@ -1,6 +1,8 @@
require 'test/unit'
$:.unshift "#{File.dirname(__FILE__)}/../lib"
+$:.unshift "#{File.dirname(__FILE__)}/../../activesupport/lib"
+$:.unshift "#{File.dirname(__FILE__)}/../../actionpack/lib"
require 'action_mailer'
require 'action_mailer/test_case'
@@ -0,0 +1,2 @@
+body: <%= @body %>
+bar: <%= @bar %>
@@ -273,6 +273,13 @@ def return_path
headers "return-path" => "another@somewhere.test"
end
+ def body_ivar(recipient)
+ recipients recipient
+ subject "Body as a local variable"
+ from "test@example.com"
+ body :body => "foo", :bar => "baz"
+ end
+
class <<self
attr_accessor :received_body
end
@@ -926,6 +933,11 @@ def test_return_path_with_deliver
TestMailer.deliver_return_path
assert_match %r{^Return-Path: <another@somewhere.test>}, MockSMTP.deliveries[0][0]
end
+
+ def test_body_is_stored_as_an_ivar
+ mail = TestMailer.create_body_ivar(@recipient)
+ assert_equal "body: foo\nbar: baz", mail.body
+ end
end
end # uses_mocha
@@ -290,8 +290,6 @@ class Base
@@allow_concurrency = false
cattr_accessor :allow_concurrency
- @@guard = Monitor.new
-
# Modern REST web services often need to submit complex data to the web application.
# The <tt>@@param_parsers</tt> hash lets you register handlers which will process the HTTP body and add parameters to the
# <tt>params</tt> hash. These handlers are invoked for POST and PUT requests.
@@ -532,12 +530,7 @@ def process(request, response, method = :perform_action, *arguments) #:nodoc:
assign_names
log_processing
-
- if @@allow_concurrency
- send(method, *arguments)
- else
- @@guard.synchronize { send(method, *arguments) }
- end
+ send(method, *arguments)
send_response
ensure
@@ -975,13 +968,15 @@ def head(*args)
# Sets the Last-Modified response header. Returns 304 Not Modified if the
# If-Modified-Since request header is <= last modified.
def last_modified!(utc_time)
- head(:not_modified) if response.last_modified!(utc_time)
+ response.last_modified= utc_time
+ head(:not_modified) if response.last_modified == request.if_modified_since
end
# Sets the ETag response header. Returns 304 Not Modified if the
# If-None-Match request header matches.
def etag!(etag)
- head(:not_modified) if response.etag!(etag)
+ response.etag = etag
+ head(:not_modified) if response.etag == request.if_none_match
end
# Clears the rendered results, allowing for another render to be performed.
@@ -1256,15 +1251,15 @@ def default_template_name(action_name = self.action_name)
action_name = strip_out_controller(action_name)
end
end
- "#{self.class.controller_path}/#{action_name}"
+ "#{self.controller_path}/#{action_name}"
end
def strip_out_controller(path)
path.split('/', 2).last
end
def template_path_includes_controller?(path)
- self.class.controller_path.split('/')[-1] == path.split('/')[0]
+ self.controller_path.split('/')[-1] == path.split('/')[0]
end
def process_cleanup
@@ -2,6 +2,8 @@ module ActionController
# Dispatches requests to the appropriate controller and takes care of
# reloading the app after each request when Dependencies.load? is true.
class Dispatcher
+ @@guard = Mutex.new
+
class << self
def define_dispatcher_callbacks(cache_classes)
unless cache_classes
@@ -20,6 +22,7 @@ def define_dispatcher_callbacks(cache_classes)
end
if defined?(ActiveRecord)
+ after_dispatch :checkin_connections
before_dispatch { ActiveRecord::Base.verify_active_connections! }
to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers }
end
@@ -98,7 +101,7 @@ def initialize(output = $stdout, request = nil, response = nil)
@output, @request, @response = output, request, response
end
- def dispatch
+ def dispatch_unlocked
begin
run_callbacks :before_dispatch
handle_request
@@ -109,6 +112,16 @@ def dispatch
end
end
+ def dispatch
+ if ActionController::Base.allow_concurrency
+ dispatch_unlocked
+ else
+ @@guard.synchronize do
+ dispatch_unlocked
+ end
+ end
+ end
+
def dispatch_cgi(cgi, session_options)
if cgi ||= self.class.failsafe_response(@output, '400 Bad Request') { CGI.new }
@request = CgiRequest.new(cgi, session_options)
@@ -145,6 +158,21 @@ def flush_logger
Base.logger.flush
end
+ def mark_as_test_request!
+ @test_request = true
+ self
+ end
+
+ def test_request?
+ @test_request
+ end
+
+ def checkin_connections
+ # Don't return connection (and peform implicit rollback) if this request is a part of integration test
+ return if test_request?
+ ActiveRecord::Base.clear_active_connections!
+ end
+
protected
def handle_request
@controller = Routing::Routes.recognize(@request)
@@ -276,7 +276,7 @@ def process(method, path, parameters = nil, headers = nil)
ActionController::Base.clear_last_instantiation!
env['rack.input'] = data.is_a?(IO) ? data : StringIO.new(data || '')
- @status, @headers, result_body = ActionController::Dispatcher.new.call(env)
+ @status, @headers, result_body = ActionController::Dispatcher.new.mark_as_test_request!.call(env)
@request_count += 1
@controller = ActionController::Base.last_instantiation
@@ -167,7 +167,7 @@ def template_format
parameter_format = parameters[:format]
if parameter_format
- parameter_format.to_sym
+ parameter_format
elsif xhr?
:js
else
@@ -176,8 +176,7 @@ def template_format
end
def cache_format
- parameter_format = parameters[:format]
- parameter_format && parameter_format.to_sym
+ parameters[:format]
end
# Returns true if the request's "X-Requested-With" header contains
@@ -41,10 +41,9 @@ def self.included(base) #:nodoc:
base.rescue_templates = Hash.new(DEFAULT_RESCUE_TEMPLATE)
base.rescue_templates.update DEFAULT_RESCUE_TEMPLATES
- base.class_inheritable_array :rescue_handlers
- base.rescue_handlers = []
-
base.extend(ClassMethods)
+ base.send :include, ActiveSupport::Rescuable
+
base.class_eval do
alias_method_chain :perform_action, :rescue
end
@@ -54,82 +53,12 @@ module ClassMethods
def process_with_exception(request, response, exception) #:nodoc:
new.process(request, response, :rescue_action, exception)
end
-
- # Rescue exceptions raised in controller actions.
- #
- # <tt>rescue_from</tt> receives a series of exception classes or class
- # names, and a trailing <tt>:with</tt> option with the name of a method
- # or a Proc object to be called to handle them. Alternatively a block can
- # be given.
- #
- # Handlers that take one argument will be called with the exception, so
- # that the exception can be inspected when dealing with it.
- #
- # Handlers are inherited. They are searched from right to left, from
- # bottom to top, and up the hierarchy. The handler of the first class for
- # which <tt>exception.is_a?(klass)</tt> holds true is the one invoked, if
- # any.
- #
- # class ApplicationController < ActionController::Base
- # rescue_from User::NotAuthorized, :with => :deny_access # self defined exception
- # rescue_from ActiveRecord::RecordInvalid, :with => :show_errors
- #
- # rescue_from 'MyAppError::Base' do |exception|
- # render :xml => exception, :status => 500
- # end
- #
- # protected
- # def deny_access
- # ...
- # end
- #
- # def show_errors(exception)
- # exception.record.new_record? ? ...
- # end
- # end
- def rescue_from(*klasses, &block)
- options = klasses.extract_options!
- unless options.has_key?(:with)
- block_given? ? options[:with] = block : raise(ArgumentError, "Need a handler. Supply an options hash that has a :with key as the last argument.")
- end
-
- klasses.each do |klass|
- key = if klass.is_a?(Class) && klass <= Exception
- klass.name
- elsif klass.is_a?(String)
- klass
- else
- raise(ArgumentError, "#{klass} is neither an Exception nor a String")
- end
-
- # Order is important, we put the pair at the end. When dealing with an
- # exception we will follow the documented order going from right to left.
- rescue_handlers << [key, options[:with]]
- end
- end
end
protected
# Exception handler called when the performance of an action raises an exception.
def rescue_action(exception)
- if handler_for_rescue(exception)
- rescue_action_with_handler(exception)
- else
- log_error(exception) if logger
- erase_results if performed?
-
- # Let the exception alter the response if it wants.
- # For example, MethodNotAllowed sets the Allow header.
- if exception.respond_to?(:handle_response!)
- exception.handle_response!(response)
- end
-
- if consider_all_requests_local || local_request?
- rescue_action_locally(exception)
- else
- rescue_action_in_public(exception)
- end
- end
+ rescue_with_handler(exception) || rescue_action_without_handler(exception)
end
# Overwrite to implement custom logging of errors. By default logs as fatal.
@@ -185,15 +114,20 @@ def rescue_action_locally(exception)
render_for_file(rescues_path("layout"), response_code_for_rescue(exception))
end
- # Tries to rescue the exception by looking up and calling a registered handler.
- def rescue_action_with_handler(exception)
- if handler = handler_for_rescue(exception)
- if handler.arity != 0
- handler.call(exception)
- else
- handler.call
- end
- true # don't rely on the return value of the handler
+ def rescue_action_without_handler(exception)
+ log_error(exception) if logger
+ erase_results if performed?
+
+ # Let the exception alter the response if it wants.
+ # For example, MethodNotAllowed sets the Allow header.
+ if exception.respond_to?(:handle_response!)
+ exception.handle_response!(response)
+ end
+
+ if consider_all_requests_local || local_request?
+ rescue_action_locally(exception)
+ else
+ rescue_action_in_public(exception)
end
end
@@ -216,36 +150,6 @@ def response_code_for_rescue(exception)
rescue_responses[exception.class.name]
end
- def handler_for_rescue(exception)
- # We go from right to left because pairs are pushed onto rescue_handlers
- # as rescue_from declarations are found.
- _, handler = *rescue_handlers.reverse.detect do |klass_name, handler|
- # The purpose of allowing strings in rescue_from is to support the
- # declaration of handler associations for exception classes whose
- # definition is yet unknown.
- #
- # Since this loop needs the constants it would be inconsistent to
- # assume they should exist at this point. An early raised exception
- # could trigger some other handler and the array could include
- # precisely a string whose corresponding constant has not yet been
- # seen. This is why we are tolerant to unknown constants.
- #
- # Note that this tolerance only matters if the exception was given as
- # a string, otherwise a NameError will be raised by the interpreter
- # itself when rescue_from CONSTANT is executed.
- klass = self.class.const_get(klass_name) rescue nil
- klass ||= klass_name.constantize rescue nil
- exception.is_a?(klass) if klass
- end
-
- case handler
- when Symbol
- method(handler)
- when Proc
- handler.bind(self)
- end
- end
-
def clean_backtrace(exception)
if backtrace = exception.backtrace
if defined?(RAILS_ROOT)
@@ -84,7 +84,7 @@ class TestCase < ActiveSupport::TestCase
module RaiseActionExceptions
attr_accessor :exception
- def rescue_action(e)
+ def rescue_action_without_handler(e)
self.exception = e
if request.remote_addr == "0.0.0.0"
Oops, something went wrong.

0 comments on commit 6090513

Please sign in to comment.