【问题标题】:Ruby - Share local variable with the obj's eigenclassRuby - 与 obj 的特征类共享局部变量
【发布时间】:2015-03-24 02:17:19
【问题描述】:

我正在尝试基于散列 my_hash 在已初始化的 Ruby 对象 MyObject 上动态定义方法,我传递给它的 initialize 方法。在initialize 方法的主体中,我有以下内容:

my_hash.each do |key|
  class << self
    define_method(key.underscore.to_sym) do
      my_hash[key]
    end
  end
end

这会失败并显示undefined local variable or method 'key' for #&lt;Class:#&lt;MyObject:0x007fc7abw0cra0&gt;&gt;。任何想法为什么?

my_hash 是由带有许多驼峰键的 json 响应组成的,因此使用简单的 ruby​​ 方法来获取我想要的值会更方便。

【问题讨论】:

  • 将您的哈希转换为 OpenStruct,这将为您的每个密钥创建一个方法。
  • 但这不会使 MyObject 对象上的方法可用吗?除非我以某种方式重新定义 method_missing 以将调用传递给 OpenStruct 对象。

标签: ruby metaprogramming eigenclass


【解决方案1】:

局部变量在定义它们的范围内是局部的。Ruby 中的(词法)范围是脚本范围、模块/类定义范围、方法定义范围和块范围。只有块作用域嵌套在它们的外部作用域中(也就是靠近它们周围的作用域)。所以,你必须使用一个块:

my_hash.each_key do |key|
  singleton_class.class_eval do
    define_method(key.to_sym) do
      my_hash[key]
    end
  end
end

甚至更好:

my_hash.each_key do |key|
  define_singleton_method(key.underscore.to_sym) do
    my_hash[key]
  end
end

注意:我还修复了一个错误,您应该使用 each_key 而不是 each(这是 each_pair 的别名)来迭代键。

【讨论】:

  • 太棒了。谢谢约尔格。
【解决方案2】:

您可以使用define_singleton_method 而不是class &lt;&lt; self。另请注意,Hash#each 会生成一个包含键和值的二元素数组。

my_hash.each do |key, val|
  define_singleton_method(key.underscore.to_sym) do
    val
  end
end

【讨论】:

  • 是的,正是我需要的。
  • 如果你编辑解释第一句话,我会投赞成票。
猜你喜欢
  • 1970-01-01
  • 2021-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-14
  • 1970-01-01
  • 2017-08-19
  • 1970-01-01
相关资源
最近更新 更多