2017-03-18 75 views
0

我无法访问我在另一个文件中声明的模块,而且我想知道我是否在概念上拥有此权限。让我解释。需求范围

如果我有一个文件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" 

将是改变什么?在我看来,无论是什么文件,都可以访问gem,但是我在第二种情况下无法访问模块。任何帮助表示赞赏。

更新:我测试了两种情况,他们都工作,这导致我相信这不是一个概念性问题,而是我的代码中的错误。我将开始调试该项目。

+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 & b文件相对c文件。

或者你可以将下面的代码行添加到您的c.rb文件,它是用Ruby宝石用来加载自己的自定义脚本 常见的约定/库

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

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

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内部使用的文件名,找到,如果它没有给出 绝对路径

If the filename does not resolve to an absolute path, it will be searched for in the directories listed in $LOAD_PATH ($:) .

-- Kernel's require method

所以,当我再次运行你的代码,我看到下面的

$ ruby c.rb 
hello world 

应该注意的是,

A file will not be loaded again if its path already appears in $" . For example, require 'a'; require './a' will not load a.rb again.

-- Module: Kernel (Ruby 2_4_0)

所以只要你的require方法之一出现在 这个文件被调用的方法之一之前,它就应该工作;所以您的两个例子就可以了(如 只要任一目录下的仰卧被添加到$LOAD_PATH或使用 require_relative代替)

+0

当我自己测试时,我实际上在一分钟前注意到了这一点。 [这是实际的代码](https://github.com/space-hanger/apollo-8)。所以我有'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。 –

+0

对不起,我可能应该只是在问题中发布了原始源代码。 –

+0

看看示例应用程序代码,它看起来'send_text'帮助器方法正在导致您描述的痛点。我认为“每次在用户模型中设置'手机'属性时发送短信是一个好主意(特别是如果该模型尚未保存)?”。另外,似乎您已经在重新发送验证代码时使用了'send_text',但是可以在创建或更新用户控制器操作时(或者在用户表单对象保存方法中,如果您熟悉它们)使用它而不是API来自模型的呼叫。这确实取决于您在您的应用程序中调用的位置。 – sonna