在Rails中运行另一个方法之前调用方法

Ada*_*NYC 4 ruby-on-rails callback observer-pattern

我有一个Model,其中有method_1method_10.我也有ModelObserver.我想ModelObserver在调用method1之前注意method_9,但不是method_10.

是否有一种干燥的方式来编写它,而不是在所有9种方法中重复notify_observers(:after_something)?

Har*_*tty 8

添加一个monkey_patches.rbconfig/initializersdirctory中调用的文件.

class Object
  def self.method_hook(*args)
    options = args.extract_options!
    return unless (options[:before].present? or options[:after].present?)
    args.each do |method_name|      
      old_method = instance_method(method_name) rescue next

      define_method(method_name) do |*args|
        # invoke before callback
        if options[:before].present?
          options[:before].is_a?(Proc) ? options[:before].call(method_name, self):
            send(options[:before], method_name) 
        end

        # you can modify the code to call after callback 
        # only when the old method returns true etc..
        old_method.bind(self).call(*args)

        # invoke after callback
        if options[:after].present?
          options[:after].is_a?(Proc) ? options[:after].call(method_name, self): 
            send(options[:after], method_name) 
        end
      end
    end
  end
end  
Run Code Online (Sandbox Code Playgroud)

该补丁使您可以在类的实例方法上添加beforeafter回调.一个钩子可以是:

  • 接受一个参数的实例方法的名称
  • lambda接受两个参数

可以在同一方法上注册多个挂钩.挂钩的方法应该在钩子之前.

例如:

class Model < ActiveRecord::Base

  def method1
  end

  def method2
  end

  def method3
  end

  def method4
  end

  def update_cache
  end

  # instance method name as `after` callback parameter
  method_hook :method1, :method2, :after => :update_cache

  # lambda as `before` callback parameter
  method_hook :method1, :method2, 
    :before => lambda{|name, record| p name;p record}

  # lambda as `after` callback parameter
  method_hook :method3, :method4, 
    :after => lambda{|name, record| 
       Model2.increment_counter(:post_count, record.model2_id)}

end
Run Code Online (Sandbox Code Playgroud)