【问题标题】:Is there a shorter way to require a file in the same directory in ruby?是否有更短的方法来要求 ruby​​ 中同一目录中的文件?
【发布时间】:2010-10-21 18:33:33
【问题描述】:

是否有更短的方法来要求位于同一目录中的文件(作为正在执行的脚本)?

require File.expand_path(File.dirname(__FILE__) + '/some_other_script')

我读到require "my_script"require "./my_script" 实际上会加载脚本两次(ruby 不会识别它实际上是同一个脚本),这就是为什么推荐File.expand_path 的原因:如果每次都使用它需要脚本的时间,那么它只会被加载一次。

在我看来,像 Ruby 这样简洁的语言似乎没有更短的解决方案。例如,python 就是这样:

import .some_other_module_in_the_same_directory

我想我可以给require 打猴子补丁……但这太邪恶了! ;-)

【问题讨论】:

    标签: ruby path require


    【解决方案1】:

    即使您从其他目录运行脚本,上述内容也可以正常工作。 但是,在同一目录中,您引用的较短形式按预期工作,至少对于 ruby​​ 1.9 不会导致双重要求。

    testa.rb

    puts "start test A"
    require 'testb'
    require './testb'
    puts "finish test A"
    

    testb.rb

    puts "start test B"
    puts "finish test B"
    

    运行“ruby testa.rb”将导致:

    start test A
    start test B
    finish test B
    finish test A
    

    但是,更长的格式甚至可以在另一个目录中工作(例如 ruby​​ somedir/script.rb)

    【讨论】:

      【解决方案2】:

      把它放在一个标准库目录中(某个地方已经在你的默认加载路径$:):

      # push-loadpath.rb
      if caller.first
        $: << File.expand_path(File.dirname(caller.first))
      end
      

      然后,这应该可以工作

      % ls /path/to/
      bin.rb lib1.rb lib2.rb #...
      % cat /path/to/bin.rb
      load 'push-loadpath.rb'
      require 'lib1'
      require 'lib2'
      #...
      

      caller 让您可以访问当前的调用堆栈,并告诉您什么文件和位置,因此push-loadpath.rb 使用它来将load 分配的文件添加到加载路径。

      请注意,您应该load 文件,而不是require 它,因此可以多次调用正文(每次要更改加载路径时调用一次)。

      或者,您可以将主体包装在一个方法中,

      # push-loadpath.rb
      def push_loadpath
        $: << File.expand_path(File.dirname(caller.first))
      end
      

      这将允许您require 它,并以这种方式使用它:

      % ls /path/to/
      bin.rb lib1.rb lib2.rb #...
      % cat /path/to/bin.rb
      require 'push-loadpath'
      push_loadpath
      require 'lib1'
      require 'lib2'
      #...
      

      【讨论】:

        【解决方案3】:

        只需要filename

        是的,如果你将它指定为filename./filename,它会导入两次,所以不要这样做。你没有指定.rb,所以不要指定路径。我通常将大部分应用程序逻辑放入lib 中的一个文件中,然后在bin 中创建一个看起来像这样的脚本:

        #!/usr/bin/env ruby
        
        $: << File.join(File.dirname(__FILE__), "/../lib")
        require 'app.rb'
        App.new.run(ARGV)
        

        另一个优点是,如果加载应用程序逻辑不会自动开始执行它,我发现进行单元测试会更容易。

        【讨论】:

          【解决方案4】:

          从 ruby​​ 1.9 开始,您可以使用require_relative

          latest doc 中检查 Core API 的 require_relativeanother version

          【讨论】:

          • 天哪,真希望我早点看到你的答案。
          猜你喜欢
          • 2010-10-18
          • 2011-01-30
          • 2013-05-27
          • 2015-09-05
          • 2021-06-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多