在没有rails的ruby中实现rails before_filter

我在所有课程中使用ga logger。 我希望每个msg都以类名和方法名开头,如下所示:

Class_name::Method_name 

这就是我现在正在做的事情:

 class FOO def initialize end def bar msg_prefix = "#{self.class}::#{__method__}" ... some code ... @logeer = "#{msg_prefix} msg ..." end def bar2 msg_prefix = "#{self.class}::#{__method__}" ... some code 2 ... @logeer = "#{msg_prefix} msg2 ..." end end 

我想使用像rails中的before_filter来防止两面性,我使用sinatra但是这些类是普通的老ruby 1.9.3

想法?

您可以使用Module#method_added创建任何方法的回调,为旧方法别名,然后定义一个先调用before_filter方法的新方法。 这是我(非常)粗略的第一个概念:

 module Filter def before_filter name @@filter = name end def method_added name return if @filtering # Don't add filters to original_ methods return if @@filter == name # Don't filter filters return if name == :initialize @filtering = true alias_method :"original_#{name}", name define_method name do |*args| self.send @@filter, name self.send :"original_#{name}", *args end @filtering = false end end class FilterTest extend Filter before_filter :prepare_logs def baz puts "#{@msg_prefix} message goes here" end def prepare_logs name @msg_prefix = "#{self.class}::#{name}" end end ft = FilterTest.new ft.baz 

通过使用__method__就像你在create_prefix ,你将获得过滤方法的名称,而不是原始方法,所以你必须传递方法名称。可能还有其他解决方案可以使它更清洁。

您可以使用ActiveModel :: Callbacks在纯Ruby类中获得before_filter的行为(尽管在您的情况下,仅仅执行一行就太过分了):

 require 'active_model' class FOO extend ActiveModel::Callbacks define_model_callbacks :baz, only: :before before_baz :create_prefix def initialize end def bar run_callbacks :baz do ... some code ... @logeer = "#{@msg_prefix} msg ..." end end def bar2 run_callbacks :baz do ... some code 2 ... @logeer = "#{@msg_prefix} msg2 ..." end end private def create_prefix @msg_prefix = "#{self.class}::#{__method__}" end end