需要

时间:2017-03-18 00:41:11

标签: ruby scope conceptual

我无法访问我在另一个文件中声明的模块,我想知道我是否在概念上有这个权利。让我解释一下。

如果我有文件a,b和c设置如此

归档

module HelloWorld
  def greet
    "hello world"
  end
end

档案b

require "a"

档案c

require "b"
include HelloWorld

puts greet

所以这是a -> b -> c,这会有效吗?

现在怎么办呢

归档

module HelloWorld
  def greet
    "hello world"
  end
end

档案b

include HelloWorld

puts greet

档案c

require "a"
require "b"

这会改变什么吗?在我看来,宝石 - 一旦需要 - 无论什么文件都可以访问,但我在第二种情况下访问模块时遇到问题。任何帮助表示赞赏。

更新:我测试了两个场景,它们都有效,这让我相信这不是一个概念问题,而是我的代码中的一个错误。我打算调试项目。

1 个答案:

答案 0 :(得分:1)

当我尝试运行您的代码时,我收到以下错误消息

$ ruby c.rb
~/.rbenv/versions/2.3.1/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- a (LoadError)
  from /Users/Sonna/.rbenv/versions/2.3.1/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
  from c.rb:2:in `<main>'

只是说它使用Kernel's require method 它无法找到a.rb文件,然后引发LoadError异常。

要获取该文件,您可以使用Kernal's require_relative method

require_relative "a"
require_relative "b"

这将是那些a&amp;相对于b文件的c个文件。

或者您可以将以下代码行添加到c.rb文件中,这是一个 Ruby Gems中用于加载其自定义脚本/库的常用约定

current_directory = File.expand_path("../", __FILE__)
$LOAD_PATH.unshift(current_directory) unless $LOAD_PATH.include?(current_directory)

这将从当前文件../添加当前目录__FILE__, 将它扩展为所述当前目录的aboslute路径并将其添加到 现有的Load Path全局变量; e.g。

puts $LOAD_PATH
# => ["~/Projects/ruby/stackoverflow_questions/the_scope_of_require",
#     "/usr/local/Cellar/rbenv/1.0.0/rbenv.d/exec/gem-rehash",
#     "~/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/did_you_mean-1.0.0/lib",
#     "~/.rbenv/versions/2.3.1/lib/ruby/site_ruby/2.3.0",
#     "~/.rbenv/versions/2.3.1/lib/ruby/site_ruby/2.3.0/x86_64-darwin15",
#     "~/.rbenv/versions/2.3.1/lib/ruby/site_ruby",
#     "~/.rbenv/versions/2.3.1/lib/ruby/vendor_ruby/2.3.0",
#     "~/.rbenv/versions/2.3.1/lib/ruby/vendor_ruby/2.3.0/x86_64-darwin15",
#     "~/.rbenv/versions/2.3.1/lib/ruby/vendor_ruby",
#     "~/.rbenv/versions/2.3.1/lib/ruby/2.3.0",
#     "~/.rbenv/versions/2.3.1/lib/ruby/2.3.0/x86_64-darwin15"]

如果没有给出require内部用于通过文件名查找的内容 绝对路径

  

如果文件名未解析为绝对路径,则会搜索该文件名   在$LOAD_PATH ($:)

中列出的目录中      

- Kernel's require method

所以,当我再次运行代码时,我会看到以下内容

$ ruby c.rb
hello world

应该注意

  

如果文件的路径已经显示在$"中,则不会再次加载该文件。对于   例如,require 'a'; require './a'将无法再次加载a.rb

     

- Module: Kernel (Ruby 2_4_0)

只要您的require方法之一出现在其中一个方法之前,就会发生一次 该文件被调用,它应该工作;所以你的两个例子都可行(如 只要将sit的目录添加到$LOAD_PATH或您使用 require_relative代替)