Ruby 要求的范围

Ruby 要求的范围,ruby,scope,conceptual,Ruby,Scope,Conceptual,我在访问另一个文件中声明的模块时遇到问题,我想知道我在概念上是否有这种权利。让我解释一下 如果我有像这样的文件a、b和c设置 归档 module HelloWorld def greet "hello world" end end module HelloWorld def greet "hello world" end end 文件b require "a" include HelloWorld puts greet 文件c require "b" i

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

如果我有像这样的文件a、b和c设置 归档

module HelloWorld
  def greet
    "hello world"
  end
end
module HelloWorld
  def greet
    "hello world"
  end
end
文件b

require "a"
include HelloWorld

puts greet
文件c

require "b"
include HelloWorld

puts greet
require "a"
require "b"
所以是a->b->c,这样行吗

如果我这样做呢 归档

module HelloWorld
  def greet
    "hello world"
  end
end
module HelloWorld
  def greet
    "hello world"
  end
end
文件b

require "a"
include HelloWorld

puts greet
文件c

require "b"
include HelloWorld

puts greet
require "a"
require "b"
这会改变什么吗?在我看来,gems——一旦需要——无论是什么文件都可以访问,但在第二种情况下,我在访问模块时遇到了麻烦。感谢您的帮助


更新:我测试了这两个场景,它们都能工作,这让我相信这不是概念上的问题,而是代码中的一个bug。我将调试该项目。

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

$ 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>'
它会将这些a&b文件与c文件相关联

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

current_directory = File.expand_path("../", __FILE__)
$LOAD_PATH.unshift(current_directory) unless $LOAD_PATH.include?(current_directory)
这将从当前文件添加当前目录../, 将其展开为所述当前目录的aboslute路径,并将其添加到 现有负载路径全局变量;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"]
如果未提供文件名,则需要内部使用以按文件名查找 绝对路径

如果文件名未解析为绝对路径,则将对其进行搜索 在$LOAD_PATH$:中列出的目录中

-

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

$ ruby c.rb
hello world
应当指出的是

如果文件的路径已显示在$中,则不会再次加载该文件。对于 例如,要求“a”;require./a将不会再次加载a.rb

-

因此,只要您的一个require方法在中的一个方法之前出现一次 该文件被称为,它应该工作;因此,您的两个示例都将作为 只要sit所在的目录被添加到$LOAD_路径或您使用
相反,我在一分钟前亲自测试时注意到了这一点。所以我有app/controllers/application_controller.rb,它既有require./app/helpers/helpers,也有require./app/models/user。当我尝试从应用程序控制器中的app/helpers/helpers访问模块时,它可以工作,但从app/models/user尝试时失败。我通过将require./app/helpers/helpers添加到app/models/user来修复它,但我不需要这样做。从概念上讲,这与场景b相匹配。抱歉,我可能应该在问题中发布原始源代码。查看示例应用程序代码,它看起来是“发送文本”帮助程序方法造成了您描述的痛点。我想说的是,每次在用户模型上设置“phone”属性时发送短信是不是一个好主意,尤其是当模型尚未保存时?。此外,您似乎已经在重发验证代码时使用了“send_text”,但如果熟悉用户控制器操作或用户表单对象保存方法,则可以在创建或更新用户控制器操作时使用它,而不是在模型中使用API调用。这取决于你在应用程序中调用的位置,也取决于你自己。即使我删除了用户模型中的send_text调用,它仍然会发疯。我得到了这个错误名称error:uninitialized constant User::Helpers。如果我添加require./app/helpers/helpers,那么一切正常。似乎我加载文件的顺序不对,在调用之前没有定义某些内容,但是我在我的应用程序控制器中三次检查了我的requires。“NameError:uninitialized constant User::Helpers”错误将由“include Helpers”行引起,因为不再需要Helpers模块,并且在名为Helpers的用户类命名空间中没有类/模块。否则,我看不出在应用程序的其他地方是否有对“User::Helpers”的明确调用在其中一个答案中指出的代码中有一个bug。我没有为要求添加/。