2011-08-21 26 views
9

Tôi hiện đang có một lớp cha có hàm mà tôi muốn tất cả các lớp con gọi trong mỗi hàm của nó. Hàm này được cho là hoạt động giống như hàm before_filter trong đường ray nhưng tôi không chắc chắn về cách thực hiện trước before_filter. Dưới đây là một ví dụLàm cách nào để chặn cuộc gọi phương pháp bằng ruby?

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

có thể trùng lặp [Thực thi mã cho mọi phương thức gọi trong mô-đun Ruby] (http://stackoverflow.com/questions/5513558/executing-code-for-every-method-call-in-a- ruby-module) –

+0

IMHO đó là một tình huống khác nhau và một câu hỏi rất hay. – lucapette

+0

http://stackoverflow.com/questions/29785454/call-before-methods-in-model-on-ruby/29837450#29837450 giải pháp Frederick –

Trả lời

10

Đây là một cách để làm điều đó:

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 

này sẽ tạo ra một phương pháp wrapper bằng cách sử dụng phương pháp alias_method_chaining càng sớm càng phương pháp này bạn muốn quấn được định nghĩa trong lớp con.

4

Đây là giải pháp của tôi:

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 

Để sử dụng nó, chỉ cần bao gồm BeforeEach vào lớp học của bạn như sau:

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 

Hy vọng rằng điều này sẽ làm việc cho bạn!

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 
Các vấn đề liên quan