使用 Ruby 的 TracePoint 获取方法参数

2024-01-05

我可以使用 TracePoint API 访问 Ruby 方法的参数:

def foo(foo_arg)
end

trace = TracePoint.trace(:call, :c_call) do |tp|
  tp.disable
  case tp.method_id
  when :foo, :sub
    method = eval("method(:#{tp.method_id})", tp.binding)
    method.parameters.each do |p|
      puts "#{p.last}: #{tp.binding.local_variable_get(p.last)}"
    end
  end
  tp.enable
end

trace.enable

foo(10)
# => foo_arg: 10

但是,当我尝试使用 c 方法调用时,出现错误。

"foo".sub(/(f)/) { $1.upcase }
script.rb:20:in `method': undefined method `sub' for class `Object' (NameError)
    from script.rb:20:in `<main>'
    from script.rb:8:in `eval'
    from script.rb:8:in `block in <main>'
    from script.rb:20:in `<main>'

发生这种情况的原因似乎是使用 C 方法调用和常规 Ruby 方法调用时返回的绑定之间存在差异。

在红宝石案例中tp.self等于tp.binding.eval("self") is main然而在C情况下tp.self is "foo" and tp.binding.eval("self") is main。对于 Ruby 和 C 定义的方法,是否有一种方法可以使用 TracePoint 将参数传递到方法中?


正如您在问题中指出的那样以及它记录在红宝石文档 http://ruby-doc.org/core-2.2.0/TracePoint.html#method-i-self, tp.self返回一个跟踪对象,该对象有一个method您正在寻找的方法。 我认为你应该使用

method = tp.self.method(tp.method_id)

代替

method = eval("method(:#{tp.method_id})", tp.binding)

UPDATE。关于您有问题的最后一段的一些解释。tp.self在第一种情况下(当你打电话时foo) 是指向main,因为你定义了foo主要上下文中的方法,它指向String反对第二种情况,因为sub在那里定义。但tp.binding.eval("self")回报main在这两种情况下,因为它返回一个调用上下文(不是您期望的“定义”上下文),并且在这两种情况下它都是main.

更新(回复评论)我认为做到这一点的唯一方法是猴子补丁sub以及您感兴趣的所有其他方法。代码示例:

class String
  alias_method :old_sub, :sub
  def sub(*args, &block)
    old_sub(*args, &block)
  end
end

trace = TracePoint.trace(:call, :c_call) do |tp|
  tp.disable
  case tp.method_id
  when :sub
    method = tp.self.method(tp.method_id)
    puts method.parameters.inspect
  end
  tp.enable
end

trace.enable

"foo".sub(/(f)/) { |s| s.upcase }

一大缺点是你不能使用$1, $2, ...原始块中的变量。正如所指出的here https://www.ruby-forum.com/topic/198458哪里没有办法让它发挥作用。但是您仍然可以使用块参数(s在我的例子中)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Ruby 的 TracePoint 获取方法参数 的相关文章

  • REXML - 如何提取单个元素

    我正在用 ruby 编写一些验收测试 其中涉及断言响应 XML 中值的存在 我的 XML 是这样的
  • Rails - 渲染:目标锚标记的操作?

    我希望像这样使用渲染 render action gt page form 我也尝试过这个 render template gt site page form 那也没用 这个特定页面上的表单位于最底部 如果提交时发生任何错误 我不希望用户被
  • 已定义方法的 Ruby 钩子?

    我一直在谷歌上搜索这个问题 但找不到答案 这让我认为答案是否定的 但我想我会在这里问 以防有人确切知道 Ruby 是否有一个钩子来定义方法 即在模块或类上 如果没有 是否有人足够熟悉该实施的情况main对象以了解它到底如何将方法复制到Obj
  • Bundle 说 gem 丢失了 - 但事实并非如此?

    背景 我正在维护contentRuby On Rails 站点 但我确实没有 Rails 的经验 当尝试运行 Rails 服务器时 rails s我明白了 在任何来源中均找不到 activesupport 3 2 0 Run bundle
  • 在 Ruby 中创建一个空文件:相当于“touch”?

    创建一个的最佳方式是什么emptyRuby 中的文件 类似于 Unix 命令的东西 touch https en wikipedia org wiki Touch 28Unix 29 touch file txt FileUtils tou
  • Shoulda/RSpec 匹配器 - 条件验证

    在我的代码中 我使用 Shoulda 匹配器进行了以下验证 效果很好 it should validate presence of name 在我的模型中 我已将条件添加到验证中 validates presence of name if
  • 正则表达式的 o 修饰符是什么意思?

    Ruby 正则表达式有一些选项 例如i x m o i例如 意味着忽略大小写 什么是o选项是什么意思 在ri Regexp 它说o意味着执行 仅插值一次 但是当我这样做时 a one b a a two b不改变 它保持 one 我缺少什么
  • Watir Webdriver 加载 Chrome 扩展

    我正在尝试使用 Watir 加载 chrome 扩展 但遇到了问题 我发现这个相关问题 能够启动带有 watir webdriver 加载扩展的 chrome https stackoverflow com questions 125867
  • Ruby 中的 url_encode

    I read 的文档url encode http rdoc info stdlib erb 1 9 3 ERB Util 3Aurl encode 是否有一个表可以准确地告诉我哪个字符被编码为什么 使用url encode ERB s u
  • 比较 ruby​​ 哈希值[重复]

    这个问题在这里已经有答案了 可能的重复 如何比较两个哈希值 https stackoverflow com questions 4928789 how do i compare two hashes 我有两个 ruby 哈希值 本质上是模型
  • 子文件夹和关系中的 Rails 模型

    我在自动加载的文件夹中组织了一些轨道模型 config autoload paths Dir Rails root join app models 我可以直接使用所有模型 例如Image first file name 但是当我尝试通过关系
  • 在 Rails 中本地化嵌套虚拟属性

    怎么可能本地化嵌套虚拟属性在 Rails 中 该模型 class User lt ActiveRecord Base attr accessor company information This is used in callbacks e
  • ruby 字符串到哈希值的转换

    我有一个这样的字符串 str uu p xx m yy n zz m 我想知道如何将给定的字符串转换为哈希值 即我的实际要求是 有多少个值 符号之前 有m n和p 我不需要计数 我需要一个精确的值 这样输出效果会更好 m gt xx zz
  • 当模板类不包含可用的成员函数时,如何在编译时验证模板参数?

    我有以下模板struct template
  • 使用 HTTPClient 发布嵌套参数(哈希)

    我需要从一个应用程序到另一个应用程序的多部分 http 帖子 其中包括文件附件和嵌套的参数哈希 我尝试使用HTTPClient这适用于文件附件 但是我无法获取以嵌套格式发送的参数 data params Hash new data para
  • 带有 Rake 的 RubyMine 调试器?

    使用 RubyMine 3 0 我设置了 Rake 配置来运行单元测试 然后我设置了一些断点 然后运行 Rake 任务 没有命中断点 测试只是像平常一样执行 然后退出 RubyMine 调试器无法通过 Rake 运行吗 尝试这个 转到运行
  • 错误:执行 gem 时... (Gem::FilePermissionError)

    我检查了所有其他类似的答案 没有一个与我的完全一样 这些解决方案也不适合我 gem environment and sudo gem environment给出相同的结果 RubyGems Environment RUBYGEMS VERS
  • 使用哈希时 fetch 与 [] ? [复制]

    这个问题在这里已经有答案了 来自鲁比 科恩斯about hashes rb 为什么你可能想使用 fetch代替 当访问哈希键时 默认情况下 使用 如果存在则检索哈希值 如果不存在则返回 nil Using fetch给你一些选择 请参阅文档
  • 为什么递归会出现“堆栈级别太深”?

    我有这个红宝石代码 def get sum n return 0 if n lt 1 n 3 0 n 5 0 n get sum n 1 get sum n 1 continue execution end puts get sum 999
  • 迭代带有小胡子的数组

    如何获取迭代中当前元素的引用 my array p what goes here p my array 我希望我只是忽略了显而易见的事情 根据规范的变更日志 https github com mustache spec blob maste

随机推荐