Permalink
Browse files

extract code into modules which are included/extended to ActionMailer

  • Loading branch information...
1 parent bf16d31 commit e1747db608dd2faa7ca01e495b5616bcf41693f4 @AnthonyCaliendo committed Jan 22, 2009
View
7 README
@@ -67,16 +67,13 @@ end
-== Anything Planned?
+== TODO
-First, I would like to clean up the code a bit (extract most of the logic into a separate module, etc.). I apologize for the messiness of the code, at the time I wrote it I just wanted something "that worked" and I was pressed for time.
-
-In terms of features, I would like to do at least three more things with this:
1) Add an around_deliver callback which would allow around advice
2) Add ability to skip filters
3) Add ability to prepend filters in the chain
-Feedback is welcomed.
+Any bug reports or features requests are welcomed.
View
@@ -1 +1,2 @@
-require File.join(File.dirname(__FILE__), 'lib', 'action_mailer_callbacks')
+ActionMailer::Base.send :extend, ActionMailerCallbacks::ClassMethods
+ActionMailer::Base.send :include, ActionMailerCallbacks::InstanceMethods
@@ -1,79 +1,4 @@
-class ActionMailer::Base
- cattr_accessor :callback_chain_halted
+module ActionMailerCallbacks; end
- def self.before_deliver(*args, &block)
- delivery_callback :before, *args, &block
- end
-
- def self.after_deliver(*args, &block)
- delivery_callback :after, *args, &block
- end
-
- def self.delivery_callback(type, *args, &block)
- args = args.dup
-
- method = args.first
- method = nil if method.is_a?(Hash)
-
- options = args.pop
- options = {} unless options.is_a?(Hash)
-
- callable = block || method
- raise 'Specify a block or method to invoke in "before_deliver"' unless callable
-
- callbacks = class_variable_defined?("@@#{type}_deliver_callbacks") ? class_variable_get("@@#{type}_deliver_callbacks") : ActiveSupport::OrderedHash.new
- callbacks[callable] = options.symbolize_keys
- class_variable_set("@@#{type}_deliver_callbacks", callbacks)
- end
-
- private
- def create_mail_with_method_stored
- mail = create_mail_without_method_stored
- mail.instance_variable_set '@method_name', @method_name
- mail
- end
- alias_method_chain :create_mail, :method_stored
-
- def create_with_method_stored!(method_name, *parameters)
- @method_name = method_name
- create_without_method_stored!(method_name, *parameters)
- end
- alias_method_chain :create!, :method_stored
-
- def deliver_with_callbacks!(mail = @mail)
- self.class.callback_chain_halted = false
- if invoke_delivery_callbacks(:before, mail)
- deliver_without_callbacks!
- invoke_delivery_callbacks(:after, mail)
- end
- end
- alias_method_chain :deliver!, :callbacks
-
- def invoke_delivery_callbacks(type, mail)
- callbacks = self.class.class_variable_defined?("@@#{type}_deliver_callbacks") ? self.class.send(:class_variable_get, "@@#{type}_deliver_callbacks") : {}
- method = mail.instance_variable_get '@method_name'
-
- callbacks.each do |callable, options|
- break if callback_chain_halted
-
- only = [].push(*options[:only]) if options[:only] && method
- next if only && !(only.include?(method.to_s) || only.include?(method.to_sym))
-
- except = [].push(*options[:except]) if options[:except] && method
- next if except && (except.include?(method.to_s) || except.include?(method.to_sym))
-
- if callable.is_a? Proc
- callable.call(mail)
- else
- send(callable, mail)
- end
- end
-
- return !callback_chain_halted
- end
-
- def self.halt_callback_chain
- self.callback_chain_halted = true
- end
-
-end
+require 'action_mailer_callbacks/class_methods'
+require 'action_mailer_callbacks/instance_methods'
@@ -0,0 +1,37 @@
+module ActionMailerCallbacks::ClassMethods
+
+ def self.extended(base)
+ base.cattr_accessor(:callback_chain_halted)
+ end
+
+ def before_deliver(*args, &block)
+ delivery_callback :before, *args, &block
+ end
+
+ def after_deliver(*args, &block)
+ delivery_callback :after, *args, &block
+ end
+
+ def halt_callback_chain
+ self.callback_chain_halted = true
+ end
+
+ private
+ def delivery_callback(type, *args, &block)
+ args = args.dup
+
+ method = args.first
+ method = nil if method.is_a?(Hash)
+
+ options = args.pop
+ options = {} unless options.is_a?(Hash)
+
+ callable = block || method
+ raise 'Specify a block or method to invoke in "before_deliver"' unless callable
+
+ callbacks = class_variable_defined?("@@#{type}_deliver_callbacks") ? class_variable_get("@@#{type}_deliver_callbacks") : ActiveSupport::OrderedHash.new
+ callbacks[callable] = options.symbolize_keys
+ class_variable_set("@@#{type}_deliver_callbacks", callbacks)
+ end
+
+end
@@ -0,0 +1,52 @@
+module ActionMailerCallbacks::InstanceMethods
+
+ def self.included(base)
+ base.alias_method_chain :create_mail, :method_stored
+ base.alias_method_chain :create!, :method_stored
+ base.alias_method_chain :deliver!, :callbacks
+ end
+
+ def create_mail_with_method_stored
+ mail = create_mail_without_method_stored
+ mail.instance_variable_set '@method_name', @method_name
+ mail
+ end
+
+ def create_with_method_stored!(method_name, *parameters)
+ @method_name = method_name
+ create_without_method_stored!(method_name, *parameters)
+ end
+
+ def deliver_with_callbacks!(mail = @mail)
+ self.class.callback_chain_halted = false
+ if invoke_delivery_callbacks(:before, mail)
+ deliver_without_callbacks!
+ invoke_delivery_callbacks(:after, mail)
+ end
+ end
+
+ private
+ def invoke_delivery_callbacks(type, mail)
+ callbacks = self.class.class_variable_defined?("@@#{type}_deliver_callbacks") ? self.class.send(:class_variable_get, "@@#{type}_deliver_callbacks") : {}
+ method = mail.instance_variable_get '@method_name'
+
+ callbacks.each do |callable, options|
+ break if callback_chain_halted
+
+ only = [].push(*options[:only]) if options[:only] && method
+ next if only && !(only.include?(method.to_s) || only.include?(method.to_sym))
+
+ except = [].push(*options[:except]) if options[:except] && method
+ next if except && (except.include?(method.to_s) || except.include?(method.to_sym))
+
+ if callable.is_a? Proc
+ callable.call(mail)
+ else
+ send(callable, mail)
+ end
+ end
+
+ return !callback_chain_halted
+ end
+
+end

0 comments on commit e1747db

Please sign in to comment.