美文网首页
ruby钩子

ruby钩子

作者: SecondRocker | 来源:发表于2015-05-29 18:19 被阅读197次

    ruby有很多有用的钩子,如included,inhered,以及method_missing。对方法调用添加钩子可以用alias环绕别名实现,但终归有些麻烦,alias_method_chain需要定义with_feature方法也较麻烦,因此实现了下列module,include后调用method_callback :before_method,:after_method即可为before_method添加after_method钩子,目前方法不可传参,目前没有解决思路

    module MethodCallback
      def self.included(base)
        base.extend ClassMethods
      end
      module ClassMethods
        def method_callback(before_m,after_m)
          target_with = "#{before_m}_with_#{after_m}}"
          target_without = "#{before_m}_without_#{after_m}"
          alias_method target_without, before_m
          define_method before_m do
            eval(target_without)
            eval(after_m.to_s)
          end
          alias_method target_with, before_m
        end
      end
    end
    
    class Student
      include MethodCallback
      def enter_class
        puts "enter class"
      end
      def after_enter_class
        puts "after enter class"
      end
      method_callback :enter_class ,:after_enter_class
    end
    Student.new.enter_class
    

    今天又重新思考了下,参数问题得以解决,代码如下

    module AfterCall
      def self.included(base)
        base.extend(ClassMethods)
      end
      module ClassMethods
        def after_call when_call,then_call,*args_then,&block_then
          alias_method "old_#{when_call}",when_call
          define_method when_call do |*args_when,&block_when|
            send "old_#{when_call}",*args_when,&block_when
            send then_call,*args_then,&block_then
          end
        end
      end
    end
    class Student
      include AfterCall
      def enter_class sb
        puts "enter class #{sb}"
        yield('before') if block_given?
      end
      private
      def after_enter_class pop
        puts "after enter class #{pop}"
        yield('after') if block_given?
      end
      protected
      def third_after
        puts "from third enter"
      end
      
      after_call :after_enter_class ,:third_after
      after_call :enter_class ,:after_enter_class,"doubi", &lambda {|x|puts "from lambda #{x}"}
    end
    Student.new.enter_class "1" do |x|
      puts "from lambda #{x}"
    end
    #运行结果如下
    #enter class 1
    #from lambda before
    #after enter class doubi
    #from lambda after
    #from third enter
    

    相关文章

      网友评论

          本文标题:ruby钩子

          本文链接:https://www.haomeiwen.com/subject/tkxqtttx.html