2012-12-31 61 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"]