2017-03-18 80 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