2012-02-20 14 views
1

Modelmethod_1からmethod_10です。私もModelObserverを持っています。 method_9にmethod1を呼び出す前にnotftiy ModelObserverを入力しますが、method_10は入力しません。Railsで別のメソッドを実行する前にメソッドを呼び出す

9つのメソッドすべてでnotify_observers(:after_something)を繰り返す代わりに、これを書くDRY方法がありますか?

答えて

5

config/initializers dirctoryでmonkey_patches.rbというファイルを追加します。

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 

パッチを使用すると、クラスのインスタンスメソッドにbeforeafterコールバックを追加することができます。フックとすることができる:

  • つのパラメータ
  • 複数のフックは、同じ方法で登録することができる2つのパラメータ

を受け入れるラムダを受け入れるインスタンスメソッドの名前。フックされるメソッドは、フックの前に来る必要があります。例えば

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 
+0

回答! – AdamNYC

1

どうやってこのようなことができますか?

def notify; puts "Was notified."; end 
def method1; end 
def method2; end 
def method3; end 

def original 
    notify 
    method1 
    notify 
    method2 
    method3 
end 

def dry 
    [:method1, :method2].each do |m| 
    notify 
    send(m) 
    end 
    method3 
end 

original 
dry 
+0

おかげbdon。それはいい考えですが、うまくいかないでしょう。 notify_observersには、notify_observers(:after_method_1)、notify_observers(:after_method_2)など、method1に固有のオブザーバのメソッド名が必要です。さらに、notify文はmethod_1、method_2などに入れなければなりません。 – AdamNYC

関連する問題