2011-08-21 22 views
9

Şu anda, tüm alt sınıfların işlevlerinin her birinde aranmasını istediğim bir işlevi olan bir üst sınıfı var. Fonksiyonun, raylarda bir before_filter işlevi gibi davranması gerekiyordu, ancak before_filter uygulamasının nasıl uygulanacağına emin değilim. İşte bir örnekRuby'de yöntem çağrısını nasıl engelleyebilirim?

class Superclass 
    def before_each_method 
    puts "Before Method" #this is supposed to be invoked by each extending class' method 
    end 
end 

class Subclass < Superclass 
    def my_method 
    #when this method is called, before_each_method method is supposed to get invoked 
    end 
end 
+0

[Ruby modülündeki her bir yöntem çağrısı işlem yapılması kod] (olası çift http://stackoverflow.com/questions/5513558/executing-code-for-every-method-call-in-a- ruby-modülü) –

+0

IMHO bu farklı bir durum ve çok güzel bir soru. – lucapette

+0

http://stackoverflow.com/questions/29785454/call-before-methods-in-model-on-ruby/29837450#29837450 Frederick çözümü –

cevap

10

Bunu yapmanın bir yolu:

class Superclass 
    def before_each_method name 
    p [:before_method, name] 
    end 

    def self.method_added name 
    return if @__last_methods_added && @__last_methods_added.include?(name) 
    with = :"#{name}_with_before_each_method" 
    without = :"#{name}_without_before_each_method" 
    @__last_methods_added = [name, with, without] 
    define_method with do |*args, &block| 
     before_each_method name 
     send without, *args, &block 
    end 
    alias_method without, name 
    alias_method name, with 
    @__last_methods_added = nil 
    end 
end 

class SubclassA < Superclass 
    def my_new_method 
    p :my_new_method 
    end 

    def my_new_other_method 
    p :my_new_other_method 
    end 
end 

SubclassA.new.my_new_method 
SubclassA.new.my_new_other_method 

Bu kısa sürede yöntemi olarak size tanımlanır sarmak istiyorum alias_method_chaining yöntemini kullanarak bir sarıcı yöntemi yaratacak alt sınıf.

require 'active_support/all' 

module BeforeEach 
    extend ActiveSupport::Concern 

    module InstanceMethods 
    def before_each 
     raise NotImplementedError('Please define before_each method') 
    end 
    end 

    module ClassMethods 
    def method_added(method) 
     method = method.to_s.gsub(/_with(out)?_before$/, '') 
     with_method, without_method = "#{method}_with_before", "#{method}_without_before" 

     return if method == 'before_each' or method_defined?(with_method) 

     define_method(with_method) do |*args, &block| 
     before_each 
     send(without_method, *args, &block) 
     end 
     alias_method_chain(method, :before) 
    end 
    end 
end 

Kullanmak için, sadece bu yüzden gibi sınıfa BeforeEach şunlardır:

class Superclass 
    include BeforeEach 

    def before_each 
    puts "Before Method" #this is supposed to be invoked by each extending class' method 
    end 
end 

class Subclass < Superclass 
    def my_method 
    #when this method is called, before_each_method method is supposed to get invoked 
    end 
end 

Subclass.new.my_method 

# => Before Method 

Umarım bu sizin için çalışacaktır

4

Bu benim çözümdür!

0
class BalanceChart < BalanceFind 
include ExecutionHooks 

attr_reader :options 

def initialize(options = {}) 
@options = options 
@begin_at = @options[:begin_at] 
end 

def months_used 
range.map{|date| I18n.l date, format: :month_year}.uniq! 
end 

before_hook :months_data, :months_used, :debits_amount 
end 

module ExecutionHooks 

def self.included(base) 
base.send :extend, ClassMethods 
end 

module ClassMethods 

def before 
    @hooks.each do |name| 
    m = instance_method(name) 
    define_method(name) do |*args, &block| 

     return if @begin_at.blank? ## the code you can execute before methods 

     m.bind(self).(*args, &block) ## your old code in the method of the class 
    end 
    end 
end 

def before_hook(*method_name) 
    @hooks = method_name 
    before 
end 

def hooks 
    @hooks ||= [] 
end 
end 
end 
İlgili konular