rails的自動(dòng)加載模塊

在 rails 的很多模塊定義里經(jīng)呈睿看到這樣的代碼:

module Rails
  extend ActiveSupport::Autoload
  autoload :FooBar

看名稱就知道它與自動(dòng)加載有關(guān)纸颜。實(shí)際上 ruby 的Kernel模塊里已經(jīng)定義了一個(gè)這樣的方法,autoload(module, filename)這個(gè)方法的作用是當(dāng)?shù)谝淮斡龅街付K時(shí)因篇,自動(dòng)按照指定的路徑加載戳晌。

為什么 rails 還要再定義一個(gè)這樣的方法呢鲫尊?原因是為了方便。rails 有大量的模塊分散在不同的文件里沦偎,并且這些文件按一定的規(guī)則組織在一起疫向。ActiveSupport::Autoload模塊中的autoload能根據(jù)模塊名稱和約定的規(guī)則生成文件路徑加載模塊,不用每次都指定路徑豪嚎。除此之外搔驼,該模塊還定義了 eager_load! 方法,用于提前加載指定的一組模塊侈询。
其用法如下:

module MyLib
  extend ActiveSupport::Autoload
  autoload :Model

  eager_autoload do
    autoload :Cache
  end
end
MyLib.eager_load!

ActiveSupport::Autoload的源代碼文件在
~/.rvm/gems/ruby-2.4.0/gems activesupport-5.0.1/lib/active_support/dependencies/autoload.rb這是我電腦上的路徑舌涨,根據(jù)不同的安裝環(huán)境可能會(huì)有不同。這個(gè)模塊的定義很簡(jiǎn)單扔字,只有70多行囊嘉,下面對(duì)其主要的方法進(jìn)行分析。

module Autoload
  # 當(dāng)宿主模塊 extend ActiveSupport::Autoload 時(shí)革为,在宿主模塊的上下文中初始化幾個(gè)變量扭粱。
  def self.extended(base) # :nodoc:
    base.class_eval do
      @_autoloads = {}  # 保存 eager_load! 所需加載的模塊
      @_under_path = nil  # 保存中間路徑
      @_at_path = nil  # 保存準(zhǔn)確路徑
      @_eager_autoload = false  
    end
  end

  # 該模塊的核心方法,主要作用是生成路徑震檩,并調(diào)用 ruby 自帶的 autoload琢蛤。
  def autoload(const_name, path = @_at_path)
    unless path
      # 路徑生成規(guī)則,name 為宿主模塊的類方法抛虏,返回宿主模塊名稱博其。
      # 例如在Rails模塊里 autoload :Foo,將返回路徑 Rails/Foo迂猴。
      # @_under_path 默認(rèn)是 nil贺奠,可通過 autoload_under(path)更改。
      full = [name, @_under_path, const_name.to_s].compact.join("::")
      # 將形如 Rails::Foo::Bar 改為 Rails/Foo/Bar
      path = Inflector.underscore(full)
    end

    # 為 true 時(shí)错忱,模塊保存到 @_autoloads儡率,從而可通過 eager_load! 提前加載
    if @_eager_autoload
      @_autoloads[const_name] = path
    end

    # 生成路徑后,調(diào)用 ruby 自帶的 autoload 方法
    super const_name, path
  end

  # 增加中間路徑
  def autoload_under(path)
    @_under_path, old_path = path, @_under_path
    yield
  ensure
    @_under_path = old_path
  end

  # 將模塊加入 @_autoloads以清,為 eager_load! 作準(zhǔn)備
  def eager_autoload
    old_eager, @_eager_autoload = @_eager_autoload, true
    yield
  ensure
    @_eager_autoload = old_eager
  end

  # 依次加載 @_autoloads 中的模塊
  def eager_load!
    @_autoloads.each_value { |file| require file }
  end
  ......
小結(jié)

ActiveSupport::Autoload按照 Rails 的約定規(guī)則生成路徑自動(dòng)加載模塊儿普。改寫了 autoload方法來自動(dòng)加載,提供eager_load!方法來提前加載掷倔。生成路徑的規(guī)則為當(dāng)前模塊名/加載模塊名眉孩,如有中間路徑,可通過autoload_under插入勒葱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末浪汪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凛虽,更是在濱河造成了極大的恐慌死遭,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凯旋,死亡現(xiàn)場(chǎng)離奇詭異呀潭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)至非,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門钠署,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人荒椭,你說我怎么就攤上這事谐鼎。” “怎么了趣惠?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵狸棍,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我信卡,道長(zhǎng)隔缀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任傍菇,我火速辦了婚禮猾瘸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丢习。我一直安慰自己牵触,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布咐低。 她就那樣靜靜地躺著揽思,像睡著了一般。 火紅的嫁衣襯著肌膚如雪见擦。 梳的紋絲不亂的頭發(fā)上钉汗,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天羹令,我揣著相機(jī)與錄音,去河邊找鬼损痰。 笑死福侈,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的卢未。 我是一名探鬼主播肪凛,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼辽社!你這毒婦竟也來了伟墙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤滴铅,失蹤者是張志新(化名)和其女友劉穎戳葵,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體失息,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡譬淳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了盹兢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邻梆。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绎秒,靈堂內(nèi)的尸體忽然破棺而出浦妄,到底是詐尸還是另有隱情,我是刑警寧澤见芹,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布剂娄,位于F島的核電站,受9級(jí)特大地震影響玄呛,放射性物質(zhì)發(fā)生泄漏阅懦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一徘铝、第九天 我趴在偏房一處隱蔽的房頂上張望耳胎。 院中可真熱鬧,春花似錦惕它、人聲如沸怕午。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽郁惜。三九已至,卻和暖如春甲锡,著一層夾襖步出監(jiān)牢的瞬間兆蕉,已是汗流浹背羽戒。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恨樟,地道東北人半醉。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像劝术,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子呆奕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容