2012-12-31 36 views
1

好吧,我加载一个特定的库或更多的图书馆可能会超出范围有点麻烦。这种情况发生了什么?要求范围/创业板走出范围?

主要问题:需要函数库中的库,以便它们可以在全局范围内可用。 例子:

class Foo 
     def bar 
     require 'twitter_oauth' 
     #.... 
     end 
     def bar_2 
     TwitterOAuth::Client.new(
      :consumer_key => 'asdasdasd', 
      :consumer_secret => 'sadasdasdasdasd' 
      ) 
     end 
    end 

    temp = Foo.new 
    temp.bar_2 

我们解决我的问题,我试图运行EVAL绑定到全球范围内......这样

$Global_Binding = binding 
    class Foo 
     def bar 
     eval "require 'twitter_oauth'", $Global_Binding 
     #.... 
     end 
     def bar_2 
     TwitterOAuth::Client.new(
      :consumer_key => 'asdasdasd', 
      :consumer_secret => 'sadasdasdasdasd' 
      ) 
     end 
    end 

    temp = Foo.new 
    temp.bar_2 

但是,这似乎并没有这样的伎俩.. 。有任何想法吗?有没有更好的方法来做到这一点?

+1

'require'总是在上面执行即使深入到内部类/模块中,也是如此。 'require'解析文件并执行它的代码,所以它的内容永远不会超出范围。你的代码发生的是你永远不会调用bar,因此require是永远不会执行的。 – BernardK

+1

类定义是“执行”的。如果在类中的任何地方但在方法定义之外的地方在类#{self.name}“'语句中写入'puts',您将立即看到控制台上显示”Foo类“。 'def'(也是唯一的def)也被执行,Ruby将该方法的名称存储到类的实例方法的表中,但此时方法的内容不会被执行。该方法的主体只在执行时执行,调用它,并将其作为消息发送给作为该类的实例的对象。 – BernardK

+0

啊你说得对。我的代码中发生的事情是,图书馆花了很长时间才开始加载,直到达到某一行时,库不可用。非常感谢你。 – foklepoint

回答

1

A.
文件test_top_level.rb:使用RSpec的

puts ' (in TestTopLevel ...)' 
class TestTopLevel 
end 

测试文件ttl.rb:

# This test ensures that an included module is always processed at the top level, 
# even if the include statement is deep inside a nesting of classes/modules. 

describe 'require inside nested classes/modules' do 
#  ======================================= 

    it 'is always evaluated at the top level' do 
     module Inner 
      class Inner 
       require 'test_top_level' 
      end 
     end 

     if RUBY_VERSION[0..2] == '1.8' 
     then 
      Module.constants.should include('TestTopLevel') 
     else 
      Module.constants.should include(:TestTopLevel) 
     end 
    end 
end 

执行:

$ rspec --format nested ttl.rb 

require inside nested classes/modules 
    (in TestTopLevel ...) 
    is always evaluated at the top level 

Finished in 0.0196 seconds 
1 example, 0 failures 

B.
如果您不想处理不必要的require语句,则可以使用autoload代替。 autoload(name, file_name)第一次访问模块名称时,注册要装入的file_name(使用Object#require)。

文件twitter_oauth.rb:

module TwitterOAuth 
    class Client 
     def initialize 
      puts "hello from #{self}" 
     end 
    end 
end 

文件t.rb:

p Module.constants.sort.grep(/^T/) 

class Foo 
    puts "in class #{self.name}" 

    autoload :TwitterOAuth, 'twitter_oauth' 

    def bar_2 
     puts 'in bar2' 
     TwitterOAuth::Client.new 
    end 
end 

temp = Foo.new 
puts 'about to send bar_2' 
temp.bar_2 

p Module.constants.sort.grep(/^T/) 

执行中的Ruby 1.8.6:

$ ruby -w t.rb 
["TOPLEVEL_BINDING", "TRUE", "Thread", "ThreadError", "ThreadGroup", "Time", "TrueClass", "TypeError"] 
in class Foo 
about to send bar_2 
in bar2 
hello from #<TwitterOAuth::Client:0x10806d700> 
["TOPLEVEL_BINDING", "TRUE", "Thread", "ThreadError", "ThreadGroup", "Time", "TrueClass", "TwitterOAuth", "TypeError"]