Ruby:将常量转换为字符串

dor*_*emi 3 ruby

我想将常量转换FOO::BAR为 string "BAR"

这与constantize所做的相反并且非常相似demodulize,除了我期望一个字符串而不是实际的 Module 引用。

我想我可以让我自己的助手来做到这一点,但我无法获得FOO::BAR.

理想情况下,我想避免使用任何 3rd 方宝石。

例子:

class FOO
  BAR = {}
end

# this works
FOO            #=> FOO
FOO.name       #=> "FOO"    

# this doesn't
FOO::BAR       #=> {} 
FOO::BAR.name  #=> NoMethodError: undefined method `name' for {}:Hash
Run Code Online (Sandbox Code Playgroud)

Ste*_*fan 5

不能传递常量,只能传递对象。如果传递FOO::BAR给方法,则传递的不是常量,而是已分配给 的对象FOO::BAR,即散列。

为了从对象本身检索已分配给对象的常量名称,对象必须以某种方式存储名称。

模块确实存储了它们已分配给的常量名称(Ruby 在第一次将模块分配给常量时设置名称)。因为FOO是一个模块(类是模块),所以你可以调用FOO.name它并返回"FOO". 但这只是因为对象“知道”它的名字才有效。

从内置对象中,只有Module(因此Class)具有以name这种方式工作的方法。

可以nameFOO::BAR所指的哈希实例添加一个方法,尽管这可能不是您想要的:

def (FOO::BAR).name
  'FOO::BAR'
end

FOO::BAR.name #=> "FOO::BAR"
Run Code Online (Sandbox Code Playgroud)

另一种方法是将常量(实际上是对象)及其模块都传递给一个方法:

def find_const(mod, obj)
  mod.constants.find { |c| mod.const_get(c).equal?(obj) }
end

find_const(FOO, FOO::BAR) #=> :BAR
Run Code Online (Sandbox Code Playgroud)

该方法遍历模块的常量并返回引用传递对象的(第一个)常量。