diff --git a/actionmailer/lib/action_mailer/async.rb b/actionmailer/lib/action_mailer/async.rb deleted file mode 100644 index a364342745..0000000000 --- a/actionmailer/lib/action_mailer/async.rb +++ /dev/null @@ -1,41 +0,0 @@ -require 'delegate' - -module ActionMailer - module Async - def method_missing(method_name, *args) - if action_methods.include?(method_name.to_s) - QueuedMessage.new(queue, self, method_name, *args) - else - super - end - end - - def queue - Rails.queue - end - - class QueuedMessage < ::Delegator - attr_reader :queue - - def initialize(queue, mailer_class, method_name, *args) - @queue = queue - @mailer_class = mailer_class - @method_name = method_name - @args = args - end - - def __getobj__ - @actual_message ||= @mailer_class.send(:new, @method_name, *@args).message - end - - def run - __getobj__.deliver - end - - # Will push the message onto the Queue to be processed - def deliver - @queue << self - end - end - end -end \ No newline at end of file diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 4a099553c0..35ac0423a5 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -1,4 +1,5 @@ require 'mail' +require 'action_mailer/queued_message' require 'action_mailer/collector' require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/hash/except' @@ -464,19 +465,6 @@ module ActionMailer #:nodoc: super || action_methods.include?(method.to_s) end - # Will force ActionMailer to push new messages to the queue defined - # in the ActionMailer class when set to true. - # - # class WelcomeMailer < ActionMailer::Base - # self.async = true - # end - def async=(truth) - if truth - require 'action_mailer/async' - extend ActionMailer::Async - end - end - protected def set_payload_for_mail(payload, mail) #:nodoc: @@ -491,10 +479,18 @@ module ActionMailer #:nodoc: payload[:mail] = mail.encoded end - def method_missing(method, *args) #:nodoc: - return super unless respond_to?(method) - new(method, *args).message + def method_missing(method_name, *args) + if action_methods.include?(method_name.to_s) + QueuedMessage.new(queue, self, method_name, *args) + else + super + end end + + def queue + Rails.queue + end + end attr_internal :message diff --git a/actionmailer/lib/action_mailer/queued_message.rb b/actionmailer/lib/action_mailer/queued_message.rb new file mode 100644 index 0000000000..e5868ab43b --- /dev/null +++ b/actionmailer/lib/action_mailer/queued_message.rb @@ -0,0 +1,27 @@ +require 'delegate' + +module ActionMailer + class QueuedMessage < ::Delegator + attr_reader :queue + + def initialize(queue, mailer_class, method_name, *args) + @queue = queue + @mailer_class = mailer_class + @method_name = method_name + @args = args + end + + def __getobj__ + @actual_message ||= @mailer_class.send(:new, @method_name, *@args).message + end + + def run + __getobj__.deliver + end + + # Will push the message onto the Queue to be processed + def deliver + @queue << self + end + end +end diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb index 99c44179fd..e5f9bae897 100644 --- a/actionmailer/test/abstract_unit.rb +++ b/actionmailer/test/abstract_unit.rb @@ -11,6 +11,7 @@ end require 'minitest/autorun' require 'action_mailer' require 'action_mailer/test_case' +require 'rails/queueing' silence_warnings do # These external dependencies have warnings :/ @@ -27,6 +28,14 @@ ActionView::Template.register_template_handler :bak, lambda { |template| "Lame b FIXTURE_LOAD_PATH = File.expand_path('fixtures', File.dirname(__FILE__)) ActionMailer::Base.view_paths = FIXTURE_LOAD_PATH +class ActionMailer::Base < AbstractController::Base + class << self + def queue + @queue ||= Rails::Queueing::Container.new(Rails::Queueing::SynchronousQueue.new) + end + end +end + class MockSMTP def self.deliveries @@deliveries diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index c7b8f47d89..862b954f9e 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -575,11 +575,11 @@ class BaseTest < ActiveSupport::TestCase end test "being able to put proc's into the defaults hash and they get evaluated on mail sending" do - mail1 = ProcMailer.welcome + mail1 = ProcMailer.welcome['X-Proc-Method'] yesterday = 1.day.ago Time.stubs(:now).returns(yesterday) - mail2 = ProcMailer.welcome - assert(mail1['X-Proc-Method'].to_s.to_i > mail2['X-Proc-Method'].to_s.to_i) + mail2 = ProcMailer.welcome['X-Proc-Method'] + assert(mail1.to_s.to_i > mail2.to_s.to_i) end test "we can call other defined methods on the class as needed" do diff --git a/actionmailer/test/mailers/async_mailer.rb b/actionmailer/test/mailers/async_mailer.rb index ce601e7343..8a87e2e1cf 100644 --- a/actionmailer/test/mailers/async_mailer.rb +++ b/actionmailer/test/mailers/async_mailer.rb @@ -1,3 +1,2 @@ class AsyncMailer < BaseMailer - self.async = true end diff --git a/guides/source/action_mailer_basics.textile b/guides/source/action_mailer_basics.textile index 5f09b8e410..6d04a76088 100644 --- a/guides/source/action_mailer_basics.textile +++ b/guides/source/action_mailer_basics.textile @@ -472,7 +472,6 @@ The following configuration options are best made in one of the environment file |+delivery_method+|Defines a delivery method. Possible values are :smtp (default), :sendmail, :file and :test.| |+perform_deliveries+|Determines whether deliveries are actually carried out when the +deliver+ method is invoked on the Mail message. By default they are, but this can be turned off to help functional testing.| |+deliveries+|Keeps an array of all the emails sent out through the Action Mailer with delivery_method :test. Most useful for unit and functional testing.| -|+async+|Setting this flag will turn on asynchronous message sending, message rendering and delivery will be pushed to Rails.queue for processing.| |+default_options+|Allows you to set default values for the mail method options (:from, :reply_to, etc.).| h4. Example Action Mailer Configuration @@ -535,19 +534,7 @@ In the test we send the email and store the returned object in the +email+ varia h3. Asynchronous -You can turn on application-wide asynchronous message sending by adding to your config/application.rb file: - - -config.action_mailer.async = true - - -Alternatively you can turn on async within specific mailers: - - -class WelcomeMailer < ActionMailer::Base - self.async = true -end - +Rails provides a Synchronous Queue by default. If you want to use an Asynchronous one you will need to configure an async Queue provider like Resque. Queue providers are supposed to have a Railtie where they configure it's own async queue. h4. Custom Queues diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 0202e86f32..7a0bb21043 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -41,7 +41,7 @@ module Rails @exceptions_app = nil @autoflush_log = true @log_formatter = ActiveSupport::Logger::SimpleFormatter.new - @queue = Rails::Queueing::Queue + @queue = Rails::Queueing::SynchronousQueue @queue_consumer = Rails::Queueing::ThreadedConsumer @eager_load = nil diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index 1ac0248bcf..09b08d5663 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -59,8 +59,5 @@ module <%= app_const_base %> # Version of your assets, change this if you want to expire all your assets. config.assets.version = '1.0' <% end -%> - - # Enable app-wide asynchronous ActionMailer. - # config.action_mailer.async = true end end diff --git a/railties/lib/rails/queueing.rb b/railties/lib/rails/queueing.rb index baf6811d3e..7cd755b0f7 100644 --- a/railties/lib/rails/queueing.rb +++ b/railties/lib/rails/queueing.rb @@ -35,6 +35,14 @@ module Rails class Queue < ::Queue end + class SynchronousQueue < ::Queue + def push(job) + job.run + end + alias << push + alias enq push + end + # In test mode, the Rails queue is backed by an Array so that assertions # can be made about its contents. The test queue provides a +jobs+ # method to make assertions about the queue's contents and a +drain+