【问题标题】:Ruby binding instance_eval access to local vars?Ruby 绑定 instance_eval 访问本地变量?
【发布时间】:2021-06-12 08:28:35
【问题描述】:

处理一些我需要能够通过binding从字符串定义方法和本地变量的功能

我认为代码最能说明问题,所以这就是我想要完成的:

mybind = binding

mybind.eval("a = 5")
mybind.eval("a") #=> 5

a #=> NameError: undefined local variable or method `a'...
# Calling it in global/main scope doesn't find anything, but it's found in the `mybind` scope

mybind.eval("def thing; 3; end")
mybind.eval("thing") #=> 3

thing #=> NameError: undefined local variable or method `thing'...
# Calling it in global/main scope doesn't find anything, but it's found in the `mybind` scope

本质上,我不希望定义的任何方法/变量进入全局范围,但我希望它们可以在第二次调用同一个绑定/eval 时被调用。这些将作为字符串传递,因此也无法调用可调用块。

我试过instance_evalclass_evalevalinstance_exec

instance_eval 几乎是完美的,除非由于某种原因,在下一次调用的instance_eval 中无法访问定义的任何本地变量。

我对使用binding 有点陌生,所以如果有什么明显的遗漏,请告诉我。否则,如果有人对如何实现这一点有任何想法,即使使用不同的流程,我也会非常感谢任何帮助。

谢谢!

我使用的是 Ruby 2.7.2,但如果能提供解决方案,我可以升级。

【问题讨论】:

    标签: ruby ruby-on-rails-5 eval


    【解决方案1】:

    binding,根据其设计,在调用时获取 current 绑定。如果您在全局范围内调用它,您将获得全局绑定。听起来您想要的是用户无法访问的绑定。我们可以轻松地创建其中之一,只需在其他空函数中调用 binding

    def new_binding
      binding
    end
    

    现在,每次我调用new_binding,我都会得到一个新的范围,它在词法上继承自 Ruby 的标准全局范围,但如果没有该对象,其他任何人都无法访问。

    irb(main):012:0> new_binding == new_binding
    => false
    irb(main):013:0> my_binding = new_binding
    => #<Binding:0x00005562fd103a00>
    irb(main):014:0> my_binding.eval("a = 1")
    => 1
    irb(main):015:0> my_binding.eval("a")
    => 1
    

    --

    评论后编辑

    通过将new_binding 包装在一个简单的特征类中,我们可以更接近您正在寻找的内容。

    def new_binding
      class <<Object.new
        return binding
      end
    end
    

    现在您可以定义方法,但您必须使用显式的self

    new_binding.eval("def self.thing; 3; end")
    new_binding.eval("thing")
    

    很有可能method_added 可以使用一些技巧来绕过显式接收器,但无论出于何种原因,method_added 似乎都不想在特征类上工作。老实说,我可能最终会提出一个关于我自己的新问题,因为这种行为很奇怪。

    【讨论】:

    • 不幸的是,这将在全局级别定义方法:my_binding.eval("def d; 5; end") d #=&gt; 5 我可以接受它,因为它似乎无法解决这个问题。
    • 啊,我没有注意到关于方法的一点。如果我想到解决方法,我会编辑答案。我们可以做一些魔法。
    • 是的 - 方法部分是我正在努力解决的问题。我理解为什么要在全局范围内定义这些方法,只是希望有一种方法可以在上下文范围内以某种方式定义它们。现在我将按原样离开,因为我花了太多时间试图修复它。感谢您的帮助!
    猜你喜欢
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 2013-04-18
    • 1970-01-01
    • 2012-05-07
    相关资源
    最近更新 更多