You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby中为何无法获取块的上下文(Proc)?技术求助

问题:无法获取块(Proc)的上下文原因分析

现有代码实现

MyBuilder类(用于存储Proc)

class MyBuilder
    attr_reader :values
  
    def initialize(something)
      @something = something
      @values = {}
    end
  
    def inner(name, &block)
      @values[name] = block 
    end
end

Out类(使用instance_exec处理块)

require './my_builder'
class Out 
    def self.outer(sth, builder, &block)
        builder.instance_exec(&block) 
        p "result", builder.values
    end
end 

正常工作的测试场景

此场景能正确得到结果:oneone:

Out.outer(:hello, builder) do
            builder.inner(:one) { :oneone }
        end 

无法正常工作的场景

尝试捕获do event :assign do ...这个块时失败:

#   datan status: {unassigned: 0, assigned: 1, resolved: 2} do
#     event :assign do
#       transition :unassigned => :assigned
#     end
#   end

def self.datan(name = nil, values = nil, **options, &block)
# options is {unassigned: 0, assigned: 1, resolved: 2}
# block should `do event :assign do ...`

Out.outer(:hello, builder) do
            builder.inner(:one) { block }
        end 
end

问题原因及解决方案

核心原因

你当前写法的问题在于:builder.inner(:one) { block }只是把block这个Proc对象本身放进新块里存储,既没有执行原block的逻辑,也没正确绑定原block的上下文。后续调用存储的块时,得到的只是原Proc对象,而非它执行后的结果,甚至可能因为作用域问题导致原Proc无法正确运行。

修正方案

方案1:直接传递原block给inner方法

不需要包裹新块,直接把原block作为参数传递给inner,就能正确保存原Proc及其上下文:

Out.outer(:hello, builder) do
  builder.inner(:one, &block)
end

方案2:需要额外逻辑时显式调用原block

如果要在保存的块里添加自定义逻辑,可在新块中用instance_exec显式调用原block,确保上下文正确绑定:

Out.outer(:hello, builder) do
  builder.inner(:one) do
    # 这里可以添加自定义逻辑
    instance_exec(&block)
  end
end

补充说明

你在Out.outer中用builder.instance_exec(&block)是把块的上下文绑定到builder实例,但之前的错误写法里,传递给outer的块只是把原block变量存起来,完全没处理它的上下文绑定,自然无法正确获取原块的执行结果和上下文。

内容的提问来源于stack exchange,提问作者Snny Pictures

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 20:23:13