动态地将类解析为全局范围

lin*_*ndy 2 ruby ruby-on-rails class autoload

我需要将类的引用保存到哈希:

@hash['foo'] = bar if bar.is_a?(Class)
Run Code Online (Sandbox Code Playgroud)

上面的代码存在于我的/lib目录中,每次都不会自动加载,并且bar通常是自动加载的类.为了避免在reload!我的代码中出现"xxx的副本已从模块树中删除但仍处于活动状态"错误,我试图解析bar到全局范围,即:::在类名称之前添加(Baz正在变为::Baz) .

我不知道如何在将类转换为字符串,前置::,然后将其转换回类的情况下动态执行此操作.

Ste*_*fan 5

为散列分配常量时,常量在赋值时解析:(不是特定于散列,这只是常量的工作原理)

hash = {}
A = 1
hash[:a] = A
#=> 1          # <- 1 is being assigned, not A

A = 2
hash[:a]
#=> 1
Run Code Online (Sandbox Code Playgroud)

解决它的一种方法是存储常量的名称:

hash = {}
A = 1
hash[:a] = 'A'
#=> 'A'
Run Code Online (Sandbox Code Playgroud)

并通过const_get/ 解决它constantize:

A = 2
Object.const_get(hash[:a])
#=> 2
Run Code Online (Sandbox Code Playgroud)

这也适用于嵌套常量:

hash[:pi] = 'Math::PI'
Object.const_get(hash[:pi])
#=> 3.141592653589793
Run Code Online (Sandbox Code Playgroud)

如果您的对象恰好是命名类(或模块),则可以通过Module#name以下方式检索其名称:

hash[:lazy_enum] = Enumerator::Lazy.name
#=> "Enumerator::Lazy"

Object.const_get(hash[:lazy_enum])
#=> Enumerator::Lazy
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用一个proc来引用其块中的常量:

hash = {}
A = 1
hash[:a] = -> { A }
#=> #<Proc:0x00007fc4ba05f510@(irb):10 (lambda)>
Run Code Online (Sandbox Code Playgroud)

调用块时将解析常量:

A = 2
hash[:a].call
#=> 2
Run Code Online (Sandbox Code Playgroud)