Ruby on rails 按名称记录调试日志中的每个方法调用

Ruby on rails 按名称记录调试日志中的每个方法调用,ruby-on-rails,ruby,methods,Ruby On Rails,Ruby,Methods,我试图调试一些不起作用的测试,我遇到了一些问题。我在运行测试并将关键消息输出到日志时跟踪test.log,但由于所有交织的回调和挂钩,我不确定哪个模型的哪个方法调用哪个SQL:) 我写了一些东西来记录方法名: def log_mname caller[0]=~/`(.*?)'/ # note the first quote is a backtick Rails.logger.debug '=' * 80 Rails.logger.debug ">> #{Time.no

我试图调试一些不起作用的测试,我遇到了一些问题。我在运行测试并将关键消息输出到日志时跟踪test.log,但由于所有交织的回调和挂钩,我不确定哪个模型的哪个方法调用哪个SQL:)

我写了一些东西来记录方法名:

def log_mname
  caller[0]=~/`(.*?)'/  # note the first quote is a backtick
  Rails.logger.debug '=' * 80
  Rails.logger.debug ">> #{Time.now} - #{$1}"
  Rails.logger.debug '=' * 80
end
这非常有效,但需要将
log\mname
添加到模型中的每个方法中,这是不现实的。我想要的是在我的rails应用程序中添加一个简单的行或块,让我基本上说“在调试日志中调用所有方法时记录它们”

我尝试在模型顶部使用ruby的
set\u trace\u func
,但没有成功。我还希望不必为每个模型添加一些内容,而是为test/debug.rb环境文件或类似文件添加一些内容


有什么想法吗?

你所问的概念被称为反射;如果你有兴趣阅读更多关于它的内容

为了回答您的问题,在您想要知道其名称的方法中,
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
将方法名称作为符号返回

i、 e

这是从Ruby 1.8.7开始的

编辑 上面是打印方法名称的步骤

为了动态显示方法调用,我将使用ActiveSupport的#constantize混合
set_trace_func
show call traces

# in your test environment initializer file
require 'active_support/inflector/inflections'
MODELS_TO_WATCH = Dir.entries("#{Rails.root}/app/models/").
                      gsub(".rb", ""). # strip all extensions from filenames
                      capitalize!. # no reason for the bang, just saving space
                    # constantize # make "User" string into User model, for e.g.
# if you constantize, remove `to_s` from `classname` in the proc below
# the version that worked for me was without constantizing but I figure both 
# variations yield the same result

class_eval do |c| # Replace this with a "class DummyClass" for proper sandboxing
  set_trace_func proc { |event, id, classname|
    if event == "call" && MODELS_TO_WATCH.include?(classname.to_s)
      puts "called #{classname}'s #{id}"
    end
  }
end
注意
set\u trace\u func
是一个leech函数。它将锁定到您的Ruby进程,直到进程被杀死(许多IRB的死亡可以证明这一点)。我还没有找到撤消
set\u trace\u func
的方法。如果没有引入这些条件,它的打印结果会很糟糕;这看起来像是错误,但事实并非如此

这就是为什么我建议将其放入测试初始值设定项中的原因;而且很可能是在一个虚拟类中!这样,当您在开发、生产或您设置的任何其他环境中重新启动Rails应用程序时,这种黑客行为不会影响它


在类上下文中对其进行评估是非常重要的。我发现如果它是在实例上下文中计算的,那么它会打印Ruby程序执行过程中发生的所有事件,除了被调用的函数。

你使用了什么代码来
set_trace_func
?set_trace_func proc{事件、文件、行、id、绑定、类名| printf“%8s%s:%-2d%10s%8s\n”,事件、文件、行、id、类名}放在模型类的外部和内部。两次都出现返回错误。抱歉-这不能回答问题。我知道如何获取方法名,即上面的代码。我不知道的是如何将一个方法动态地添加到我所有的类方法中,这样当它们被执行时,我就可以打印出方法名。这就是我的工作。我做了一些额外的研究,并提出了这个新的编辑。这适用于普通的Ruby类。如果Rails中有修改,您可能需要根据具体情况进行调整。谢谢你的提问。为了回答这个问题,我学到了很多!
# in your test environment initializer file
require 'active_support/inflector/inflections'
MODELS_TO_WATCH = Dir.entries("#{Rails.root}/app/models/").
                      gsub(".rb", ""). # strip all extensions from filenames
                      capitalize!. # no reason for the bang, just saving space
                    # constantize # make "User" string into User model, for e.g.
# if you constantize, remove `to_s` from `classname` in the proc below
# the version that worked for me was without constantizing but I figure both 
# variations yield the same result

class_eval do |c| # Replace this with a "class DummyClass" for proper sandboxing
  set_trace_func proc { |event, id, classname|
    if event == "call" && MODELS_TO_WATCH.include?(classname.to_s)
      puts "called #{classname}'s #{id}"
    end
  }
end