2016-03-02 122 views
1

我想將常量FOO::BAR轉換爲字符串"BAR"Ruby:將常量轉換爲字符串

這與constantize所做的相反,並且與demodulize非常相似,除了我期望使用字符串而不是實際的模塊引用。

我想我可以讓我自己的助手做到這一點,但我無法獲得FOO::BAR的「字符串」版本。

理想情況下,我想避免任何第三方寶石。

實施例:

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 
+0

你想做什麼沒有意義。你爲什麼想獲得一個恆定名稱的「名字」?這是什麼用例? –

+0

常量名稱也是我正在實施的服務的值。它使我無需做'BAR = {name:'BAR',other_field:other_value}'。如果我可以使用拐點將const名稱串起來,我會保持DRY。 – doremi

+1

你的問題不清楚:在你的標題中,你說你想要一個模塊的名字,在第一段中,你說你想要一個模塊或類的名稱,但在你的代碼示例中,你實際上有一個散列這顯然沒有名字)。 –

回答

3

你不能傳遞常量,你只能傳遞對象。如果您將FOO::BAR傳遞給某個方法,則不會傳遞常量,而是已分配給FOO::BAR的對象,即散列。

爲了檢索常量的名稱已經從對象本身分配了一個對象,對象必須以某種方式存儲該名稱。

模塊確實存儲了它們分配給它的常量名稱(Ruby在第一次將模塊分配給常量時設置了名稱)。由於FOO是一個模塊(類是模塊),因此您可以撥打FOO.name並返回"FOO"。但那只是因爲對象「知道」它的名字才起作用。

從內置對象中,只有Module(因此Class)具有以此方式工作的name方法。

可以一個name方法添加到FOO::BAR自己,雖然這可能不是你想要的東西:

FOO::BAR.define_singleton_method(:name) { "BAR" } 

FOO::BAR.name #=> "BAR" 

另一種方式是通過兩者的常數(實際的對象)及其模塊方法:

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

find_const(FOO, FOO::BAR) #=> :BAR 

該方法遍歷模塊的常量並返回引用傳遞對象的(第一個)常量。

0
class FOO 
    class BAR   
    end 
end 

FOO::BAR.to_s.split('::').last 
    #=> "BAR" 

注意,方法Module#to_s「返回表示此模塊或類的字符串對於基本類和模塊,這就是名字」。可以使用Module#name來代替to_s

+0

這將無法正常工作,因爲它會在const值上調用'.to_s',而不是常量名稱本身。 – doremi

+0

我不明白你的評論。你不想要一個採用嵌套類的方法嗎?,'FOO :: BAR')作爲參數,並返回最內層的類作爲字符串(這裏是「BAR」)?這樣做。 –

+0

我想將一個類const的'FOO :: BAR'的引用傳遞給一個方法,該方法將轉換並返回常量名稱「BAR」爲字符串「BAR」。你的方法返回'FOO :: BAR'的值,並且在const值上調用'.to_s',而不是const名稱本身。 – doremi