2016-09-07 80 views
0

我在看Ransack紅寶石的內容。基本上它叫做require_constants。這方法本身需要一個文件:在ransack.rb adapters.rb的需要一個方法內的文件

# ransack.rb 
require 'ransack/adapters' 
Ransack::Adapters.object_mapper.require_constants 

# adapters.rb 
module Ransack 
    module Adapters 

    def self.object_mapper 
     @object_mapper ||= instantiate_object_mapper 
    end 

    def self.instantiate_object_mapper 
     if defined?(::ActiveRecord::Base) 
     ActiveRecordAdapter.new 
     elsif defined?(::Mongoid) 
     MongoidAdapter.new 
     end 
    end 

    class ActiveRecordAdapter 
     def require_constants 
     require 'ransack/adapters/active_record/ransack/constants' 
     end 
     ... 

# constants.rb 
module Ransack 
    module Constants 

第一require副本的內容,我相信。因此,我們可以參考Ransack::Adapters而沒有未定義的錯誤。

但是,當我們調用require_constants時,它似乎將Ransack::Constants的內容複製到方法定義require_constants中。

我發現那種混亂。我們正在複製一個方法內的模塊。我們在方法中複製模塊有什麼好處,而不是像其他require那樣做?第二,我知道該模塊是不是一個局部變量,但在控制檯中我甚至不能定義一個模塊時,我試了一下:

class A 
    def a 
    module B end 
    end 
end 
SyntaxError: (irb):14: module definition in method body 

那麼,什麼是require這樣做不會導致語法錯誤?

回答

3

「複製」在這裏是錯誤的詞。 require不會複製任何內容。它讀取給定文件中的源代碼並在Ruby的全局(「main」)上下文中執行該代碼(除非該文件已經爲require d;那麼它什麼也不做,並返回false)。引述the docs(重點煤礦):

加載的源文件中的任何常量或全局將在調用程序的全局命名空間提供

require在方法調用內部或模塊內部或其他任何位置的行爲與在文件頂部的行爲不同。

如果在方法調用中看到require,原因通常是模塊只在特定場景中需要,並且在發生該場景之前加載它將是浪費的(因爲,例如,模塊需要很長時間才能在加載期間加載或訪問僅在該場景中可用的資源 - 考慮不同的數據庫驅動程序或操作系統)。這並不意味着該模塊被「加載」到方法或周圍的代碼中,因爲這不是require所做的。

爲了說明,假設我們有這樣一個模塊:

# baby_module.rb 
module BabyModule 
    NAME = "Baby" 
end 

並假設我們運行下面的程序:

module TheCorner 
    def self.load_baby_module 
    require File.expand_path("baby_module", __dir__) 
    end 
end 

TheCorner.load_baby_module 

if defined?(TheCorner::BabyModule) 
    puts "#{TheCorner::BabyModule::NAME} is in TheCorner" 
elsif defined?(BabyModule) 
    puts "Nobody puts #{BabyModule::NAME} in TheCorner" 
end 

如你或許已經猜到了,這個程序的輸出將是:

沒有人把嬰兒放在TheCorner上

0

那麼require這樣做會不會導致語法錯誤?

簡單:它運行該文件。

相關問題