Ruby—在类中的大多数方法之后执行相同的代码

Ruby—在类中的大多数方法之后执行相同的代码,ruby,class,methods,Ruby,Class,Methods,我试图创建某种模块或超类,在子类的每个方法之后封装一个方法调用。 不过也有一些限制:我不希望在调用initialize()之后或在调用我选择的其他一些方法之后运行该方法。 另一个约束条件是,我只希望在标志@check_ec设置为true时执行该方法。 我有60多个方法的类,这些方法都是我硬编码的,而这段代码到处都是。 有没有一种方法可以使包装器自动为我的类方法执行该方法 所以这个想法是: class Abstract def initialize(check_ec) @check_e

我试图创建某种模块或超类,在子类的每个方法之后封装一个方法调用。 不过也有一些限制:我不希望在调用initialize()之后或在调用我选择的其他一些方法之后运行该方法。 另一个约束条件是,我只希望在标志@check_ec设置为true时执行该方法。 我有60多个方法的类,这些方法都是我硬编码的,而这段代码到处都是。 有没有一种方法可以使包装器自动为我的类方法执行该方法

所以这个想法是:

class Abstract
  def initialize(check_ec)
    @check_ec = check_ec
  end
  def after(result) # this is the method that I'd like to be added to most methods
    puts "ERROR CODE: #{result[EC]}"
  end
  def methods(method) # below each method it would execute after
    result = method() # execute the given method normally
    after(result) if @check_ec and method != :initialize and method != :has_valid_params
  end
end

class MyClass < Abstract
  def initialize(name, some_stuff, check_error_code)
   # do some stuff...
    @name = name
    super(check_error_code)
  end
  def my_method_a() # execute after() after this method
    return {EC: 0}
  end   
  def my_method_b() # execute after() after this method
    return {EC: 7}
  end
  def has_valid_params() # don't execute after() on this method
    return true
  end

end
类摘要
def初始化(检查)
@check_ec=check_ec
结束
def after(result)#这是我希望添加到大多数方法中的方法
放置“错误代码:#{result[EC]}”
结束
def methods(method)#它将在之后执行的每个方法下面
结果=方法()#正常执行给定的方法
如果@check_ec和method!=(结果)之后:初始化和方法!=:是否有有效的参数
结束
结束
类MyClass<抽象
def初始化(名称、一些内容、检查错误代码)
#做些事情。。。
@name=name
超级(检查错误代码)
结束
定义my_method_a()#在此方法之后执行after()
返回{EC:0}
结束
定义my_method_b()#在此方法之后执行after()
返回{EC:7}
结束
def具有_valid_params()#不在此方法上执行after()
返回真值
结束
结束

这个怎么样?它有一个主要缺点,即在调用
check\u error\u code
之前必须定义方法,但它可能适合您的需要。您可以在Rails回调中寻找更好的解决方案,或者推迟每个方法的重新定义,直到使用
method\u added
hook添加该方法

在要检查错误代码的每个类中包括
ErrorCodeChecker
并调用
check\u error\u code
(如代码段的最后一行)

模块ErrorCodeChecker
def自带(基本)
base.send(:extend,ClassMethods)
结束
def after(result)#这是我希望添加到大多数方法中的方法
放置“错误代码:#{result[:ec]}”
结束
模块类方法
def检查错误代码(选项={})
check\u on=instance\u methods(false)-数组(选项[:除外])
如果选项[:only],则选中&=数组(选项[:only])
课堂评估
检查每个do方法|
别名_method“#{method}_,不带_ec”,method
定义_方法(方法)do |*args和block|
发送(“#{method}_而不带_ec”、*args和block)。如果@check_ec},则在(result)之后点击{result}
#如果要在以下时间之后实际返回调用的返回值:
#结果=发送(“#{method}_,不带#ec”)
#@检查一下?后(结果):结果
结束
结束
结束
结束
结束
结束
类摘要
包括ErrorCodeChecker
def初始化(检查)
@check_ec=check_ec
结束
结束
类MyClass<抽象
def初始化(名称、一些内容、检查错误代码)
#做些事情。。。
@name=name
超级(检查错误代码)
结束
def my_method_a#在此方法之后执行after()
{ec:0}
结束
def my_method_b#在此方法之后执行after()
{ec:7}
结束
def具有_valid_params#不在此方法上执行after()
真的
结束
检查错误代码,除了::具有有效参数
#或白名单:
#仅检查错误代码:[:我的方法a,:我的方法b]
#或两者兼而有之:
#只检查\u错误\u代码::我的\u方法\u a,除了:[:具有有效的\u参数,不检查此\u参数]
结束

使用singleton类的解决方案

class MyClass
  def initialize(name, some_stuff)
   # do some stuff...
    @name = name
  end
  def my_method_a # execute after() after this method
    return {EC: 0}
  end
  def my_method_b() # execute after() after this method
    return {EC: 7}
  end
  def has_valid_params() # don't execute after() on this method
    return true
  end
end

module ErrorCodeChecker
  def after(result) # this is the method that I'd like to be added to most methods
    puts "ERROR CODE: #{result[:EC]}"
  end

  def addErrorCodeCheck(exclude = [])
    methods = self.class.superclass.public_instance_methods(false) - exclude
    class << self
      self
    end.class_exec {
      methods.each {|method|
        define_method(method) {|*p|
          super(*p).tap {|res| after(res)}
        }
      }
    }
  end
end

class MyClassEC < MyClass
  include ErrorCodeChecker

  def initialize(name, some_stuff, check_error_code, exclude = [])
    super name, some_stuff
    addErrorCodeCheck(exclude) if check_error_code
  end
end

这非常容易使用,而且是组合而不是继承。您可以构建一个非常简单的类,该类转发方法调用,然后在回调之后执行
,除了特定的方法名称:

class Abstract
  def initialize(object)
    @object = object
  end

  def method_missing(method, *arguments)
    result = @object.send(method, *arguments)

    after() unless method == "has_valid_params"

    result
  end

  def after
    # whatever
  end
end

o = Abstract.new(MyClass.new)

哥伦布的蛋!简单而美丽。:)
my = MyClassEC.new('test', 'abc', true, [:has_valid_params])

my.my_method_a    # => ERROR CODE: 0
my.my_method_b    # => ERROR CODE: 7
my.has_valid_params    # => (nothing)
class Abstract
  def initialize(object)
    @object = object
  end

  def method_missing(method, *arguments)
    result = @object.send(method, *arguments)

    after() unless method == "has_valid_params"

    result
  end

  def after
    # whatever
  end
end

o = Abstract.new(MyClass.new)