class RailsBestPractices::Reviews::UseObserverReview

Make sure to use observer (sorry we only check the mailer deliver now).

See the best practice details here rails-bestpractices.com/posts/2010/07/24/use-observer/

TODO: we need a better solution, any suggestion?

Implementation:

Review process:

check all command nodes to see if they are callback definitions, like after_create, before_destroy,
if so, remember the callback methods.

check all method define nodes to see
if the method is a callback method,
and there is a mailer deliver call,
then the method should be replaced by using observer.

Public Class Methods

new(options = {}) click to toggle source
Calls superclass method RailsBestPractices::Core::Check::new
# File lib/rails_best_practices/reviews/use_observer_review.rb, line 26
def initialize(options = {})
  super
  @callbacks = []
end

Private Instance Methods

callback_method?(node) click to toggle source

check a defn node to see if the method name exists in the @callbacks.

# File lib/rails_best_practices/reviews/use_observer_review.rb, line 64
def callback_method?(node)
  @callbacks.find { |callback| callback == node.method_name.to_s }
end
deliver_mailer?(node) click to toggle source

check a def node to see if it contains a actionmailer deliver call.

if the message of call node is deliver, and the receiver of the call node is with receiver node who exists in @callbacks, then the call node is actionmailer deliver call.

# File lib/rails_best_practices/reviews/use_observer_review.rb, line 73
def deliver_mailer?(node)
  node.grep_nodes(sexp_type: :call) do |child_node|
    if child_node.message.to_s == 'deliver'
      if child_node.receiver.sexp_type == :method_add_arg &&
           mailers.include?(child_node.receiver[1].receiver.to_s)
        return true
      end
    end
  end
  false
end
mailers() click to toggle source
# File lib/rails_best_practices/reviews/use_observer_review.rb, line 85
def mailers
  @mailers ||= Prepares.mailers
end
remember_callback(node) click to toggle source

check a command node, if it is a callback definition, such as after_create, before_create, then save the callback methods in @callbacks

# File lib/rails_best_practices/reviews/use_observer_review.rb, line 54
def remember_callback(node)
  if node.message.to_s =~ /^after_|^before_/
    node.arguments.all.each do |argument|
      # ignore callback like after_create Comment.new
      @callbacks << argument.to_s if argument.sexp_type == :symbol_literal
    end
  end
end