2013-12-10 32 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