【问题标题】:In Ruby is there a way to define the context for load?在 Ruby 中有没有办法定义加载的上下文?
【发布时间】:2016-07-11 21:25:04
【问题描述】:

我想在一个块中加载一个文件,并在对象实例的上下文中评估语句。例如这样的:

我有一个名为 foo_file 的文件,其中仅包含这一行(语句)

some_method

我希望在 Foo 实例的上下文中调用这个“语句”,如下所示。

class Foo
  def some_method
    puts "hello"
  end
end

foo = Foo.new

foo.instance_eval  do
    load "foo_file"     # load and execute statement some_method from a foo_file.  
end

这失败了:

 foo_file:1:in `<top (required)>': undefined local variable or method `some_method' for main:Object (NameError)

虽然这工作正常:

foo.instance_eval do
  some_method
end

所以似乎当我在传递给 instance_eval 的块中调用 load 时,语句被加载到顶部上下文中,而不是实例 foo。

我可以使用下面显示的代码解决这个问题。我创建了一个顶级方法来包装对实例方法的调用。我仍然需要提供上下文,这是我用单例完成的。

require 'singleton'

class Context
  include Singleton
  attr_accessor :ctx 
end

def some_method
  ctx = Context.instance.ctx
  ctx.some_method
end

Context.instance.ctx = foo
load "bar_file"

我认为这会起作用,但似乎应该有更好的方法(比如只是加载到正确的上下文中开始)。有什么建议吗?

【问题讨论】:

    标签: ruby


    【解决方案1】:

    在这种特殊情况下,得到你想要的很容易,甚至不需要调用load

    foo.instance_eval(File.read(file))
    

    例如,如果file 仅包含文本length,则

    "Hello".instance_eval(File.read(file))
    

    将返回5

    更一般地说,如果你想指定一个 任意 上下文,这基本上就是你想在Kernel#eval 中使用可选的Binding 参数的确切情况:

    bnd = 'Hello'.instance_exec { x = 3; binding }
    eval('length + x',bnd) #=> 8
    

    【讨论】:

    • 请不要在文本中使用“编辑”或“更新”标题。我们可以看到编辑了什么以及何时需要。相反,将更改合并到您的文本中,就像您最初添加它一样。见meta.stackexchange.com/q/127639/153968
    • @theTinMan:很公平。更好?
    猜你喜欢
    • 1970-01-01
    • 2011-03-17
    • 2013-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多