2013-12-10 63 views
2

我試圖創建一個將包含在許多不同類中的模塊。它需要將調用者的路徑記錄到類文件 ,以便我可以在後面的代碼中引用該路徑。此代碼嘗試向調用類中添加方法,但因爲它僅返回@@ x的當前值而失敗。在許多不同類型的Ruby在運行時將變量轉換爲常量

# /home/eric/FindMe.rb 
class FindMe 
    include GladeGUI 
end 

# /home/eric/GladeGUI.rb 
module GladeGUI 

def self.included(obj) 
    @@x, = caller[0].partition(":") # this works @@x = "/home/eric/FindMe.rb" 
    obj.class_eval do 
     def my_class_file_path 
     return ????? # I want to return "/home/eric/FindMe.rb" 
     end 
    end 
    end 

end 

的GladeGUI模塊將被「納入」,所以我不能只是添加代碼,調用的類。我需要一種方法來使@@ X編譯成一個恆定值,所以存儲在類中的方法是這樣的:

 def my_class_file_path 
     return "/home/eric/FindMe.rb" 
     end 

如何將變量轉換爲固定代碼?

謝謝。

回答

2

看起來你實際上並不需要它是一個「常量」 - 你只需要一些方法來讓方法始終返回正確的值,並且不允許其他代碼出現並更改值(與目前的@@x解決方案,有人可以修改@@x,它會中斷)

解決方案是將數據存儲在本地變量而不是類或實例變量,然後通過閉包訪問該局部變量。
沒有其他代碼會有範圍'查看'本地變量,因此它不能被改變。

但隨後問題就變成了,當你在class_eval裏面使用def時,調用者的作用域並沒有被捕獲,所以代碼看不到你的局部變量。您可以使用define_method代替

下面是一個例子

# /home/eric/GladeGUI.rb 
module GladeGUI 

def self.included(obj) 
    caller_file_path = caller[0].split(":").first 
    obj.class_eval do 
     define_method :my_class_file_path do 
     return caller_file_path 
     end 
    end 
    end 

end 

# /home/eric/FindMe.rb 
class FindMe 
    include GladeGUI 
end 

puts FindMe.new.my_class_file_path # prints the correct path 

但是 - 如果你想my_class_file_path成爲方法,而不是一個實例方法 - 使用define_singleton_method代替:

module GladeGUI 
def self.included(obj) 
    caller_file_path = caller[0].split(":").first 
    obj.class_eval do 
     define_singleton_method :my_class_file_path do 
     return caller_file_path 
     end 
    end 
    end 
end 

... 
puts FindMe.my_class_file_path 

有趣的一面說明:這是你如何在javascript中僞造「私有變量」:-)

+0

謝謝!!!現在看起來很容易。 :) – user1182000