2017-07-31 44 views
0

我想打電話給const_missinginstance_eval,但似乎失去了一些東西:紅寶石instance_eval的和const_missing

class A 
    def self.const_missing(c) 
    puts "Constant missing: #{c}" 
    end 

    def method_missing(m, *args, &block) 
    puts "Method missing: #{m}" 
    end  
end 

# Works: 
a = A.new 
a.myMethod # OK: "Method missing: myMethod" 
a.MYCONST # Sort of OK: "Method missing: MYCONST" 

# Doesn't work 
a.instance_eval { 
    myMethod # OK: "Method missing: myMethod" 
    MYCONST # uninitialized constant MYCONST (NameError) 
} 

問:在什麼地方const_missing呼叫在instance_eval去?如何將它重定向到類A? (Ruby 1.9.3如果這件事很重要)

上下文:我正在寫一個小型DSL,其中大寫字母用作州名。

DSL.evaluate { 
    ENTER_STATE_A 
    WAIT_FOR_INPUT 
} 

這些應該映射到方法,但我想保持它們的大寫。

+0

如果您的Ruby DSL需要違反已建立的[Ruby語法](https://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Variables_and_Constants#Constants)來定義常量,那麼您正在挖掘一個巨人孔。 – anothermh

+0

這就是爲什麼我想在instance_eval內真正發生任何變化的原因。 DSL文件在定義良好的階段加載,不要與代碼混合使用。 –

回答

1

注意,當你做

a.MYCONST 

你有Method missing: MYCONST(而不是Constant missing: MYCONST)。

你應該做到以下幾點:

a.instance_eval { 
    myMethod 
    A::MYCONST 
} 
+0

沒有幫助,我不想把DSL :: ENTER_STATE_A –

+0

這有點苛刻。他的回答會幫助你,如果你看看它。常量存在於Class或Singleton級別。您期待實例級方法調用來觸發類級別常量。你必須通過課程調用常數,因此爲什麼你需要A :: MYCONST – engineerDave

+0

是的,我明白,對於不開放的建議感到抱歉。但A :: MYCONST真的不是我正在尋找的解決方案。從技術上講,我不認爲從課堂級別到我的實例(Thread本地存儲是我的想法)是一個大問題。 –

2

你試圖訪問一個恆定的W/a.MYCONST它紅寶石將其解釋爲方法。你,而不是需要使用::沿W /訪問類本身,而不是該類的實例:

a = A.new 
a.instance_eval { 
    self::class::MYCONST # => Constant missing: MYCONST 
} 

似乎調用MYCONSTinstance_eval裏面當它被Object.const_missing抓住。例如,如果你重寫它,你會看到你的行爲:

def Object.const_missing(c) 
    puts "Constant missing: #{c}" 
end 

a = A.new 
a.instance_eval { 
    MYCONST # => Constant missing: MYCONST 
} 

我不建議實際做到這一點,雖然。我只是展示這個來說明發生了什麼。

+0

是的,我弄錯了。但是我想只寫'MYCONST'並委託給a。 –

+0

謝謝凱爾!有沒有辦法monkey_patch const_missing對象,而我在instance_eval? –

+0

@ChristopherOezbek我真的不確定。有可能有辦法做到這一點,而不必猴子補丁'對象'。不確定這是否可行,但您可能想在Ruby中查看[精化](https://ruby-doc.org/core-2.1.1/doc/syntax/refinements_rdoc.html)。 –