我在许多方面仍然对Ruby很陌生,所以尝试这样做有点困难(通过模块?或基类?)。
我想为在类上执行的每个方法调用执行“puts”。类似于黄瓜格式化程序的一种非常简单的形式,即:
class MyClass
def method_a
puts 'doing some stuff'
end
end
这样输出如下:
MyClass.new.method_a => 'methods_a', 'doing some stuff'
更重要的是,我希望它适用于任何类的任何方法(动态地,不会乱丢我的代码)。我想应用一些格式,即'method_a'=> '方法A'。最好的方法是什么? AOP框架?
答案 0 :(得分:2)
class MyClass
def method_a
puts "Doing A..."
end
def method_b
puts "Doing B..."
end
def self.call_before_all_methods
all_instance_methods = instance_methods - Class.instance_methods
all_instance_methods.each do |x|
class_eval <<-END
alias old_#{x} #{x}
def #{x}
print "\'#{x.to_s.split('_').each{|x| x.capitalize!}.join(' ')}\', "
old_#{x}
end
# remove_method old_#{x}.to_sym
END
end
end
private_class_method :call_before_all_methods
call_before_all_methods
end
a = MyClass.new
a.method_a
a.method_b
所以这里的技巧是首先为每个方法创建一个别名,然后通过“print formatted method name”+“original method as the alias”重新定义方法。它也由此处文档(&lt;&lt; -END)动态处理。
但是,由于重新定义每种方法都会调用其原始方法,因此最终不可能 remove_method 或 undef 别名。我认为将所有这些别名(old_method_a,old_method_b)留在那里并不是什么大不了的事。
答案 1 :(得分:0)
你在这里(除了before_filter),即使我不知道你为什么要这样做:
class MyClass
def puts_all(&blk)
# get all instance_methods, also including default ones, so remove them by - Class.instance_methods
all_other_methods = self.class.instance_methods - Class.instance_methods
# remove the method name itself dynamically by saying __callee__
all_other_methods.delete(__callee__)
# formatting as per your need
all_other_methods.each do |x|
print "#{x.to_s.split('_').each{|x| x.capitalize!}.join(' ')}, "
send(x)
end
end
def method_a
puts "Doing A..."
end
def method_b
puts "Doing B..."
end
def another_fancy_method
puts "Doing fancy..."
end
end
MyClass.new.puts_all
#=> Method A, Doing A...
#=> Method B, Doing B...
#=> Another Fancy Method, Doing fancy...
因此,要动态实现此功能,您只需使用 instance_methods 和 _ 被调用者 _ 。
答案 2 :(得分:0)
找到答案: How can I intercept method call in ruby?
鉴于它使用继承,它并不理想,但它的效果非常好。