【问题标题】:require scope / gem going out of scope?要求范围/宝石超出范围?
【发布时间】:2012-12-15 07:58:32
【问题描述】:

好的,我在加载特定库或更多库时遇到了一点问题,该库可能超出范围。在这种情况下会发生这种情况吗?

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

   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

但这似乎没有奏效……有什么想法吗?有没有更好的方法来做到这一点?

【问题讨论】:

  • require 始终在顶层执行,即使在内部类/模块的深处调用也是如此。 require 解析文件并执行其代码,因此其内容永远不会超出范围。您的代码中发生的情况是您从不调用 bar,因此永远不会执行 require。
  • 一个类定义被“执行”。如果您在类内部但在方法定义之外的任何位置编写puts "in class #{self.name}" 语句,您会立即看到in class Foo 显示在控制台上。 def(并且只有def)也被执行了,Ruby将方法的名称存储到类的实例方法表中,但是此时方法的内容并没有被执行。该方法的主体仅在您执行、调用它、将其作为消息发送到作为该类实例的对象时才会执行。
  • 啊,你确实是对的。我的代码中发生的事情是,当到达某一行时,库花了很长时间才加载,这些库不可用。非常感谢。

标签: ruby gem twitter


【解决方案1】:

答。
文件 test_top_level.rb :

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

使用 RSpec 测试文件 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 ) 注册第一次访问模块名称时要加载的文件名(使用 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"]

【讨论】:

    猜你喜欢
    • 2011-02-04
    • 2018-02-12
    • 1970-01-01
    • 2023-03-27
    • 2017-04-01
    • 1970-01-01
    • 2013-11-01
    • 1970-01-01
    相关资源
    最近更新 更多