略過內容 略過搜尋

Lazy Load Hooks

LazyLoadHooks 允許 Rails 延遲載入許多元件,從而讓應用程式啟動得更快。因為這個特性的緣故,現在在啟動時不再需要載入 ActiveRecord::Base 僅用於套用組態。反之,會註冊一個 Hook,在載入 ActiveRecord::Base 後套用組態。這裡將 ActiveRecord::Base 作為範例使用,但這個特性也可以套用在其他地方。

以下是呼叫 on_load 方法來註冊 Hook 的範例。

initializer 'active_record.initialize_timezone' do
  ActiveSupport.on_load(:active_record) do
    self.time_zone_aware_attributes = true
    self.default_timezone = :utc
  end
end

當整個 ActiveRecord::Base 已評估完畢後,run_load_hooks 就會被呼叫。最後一行 ActiveRecord::Base

ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)

run_load_hooks 接著會執行所有透過 on_load 方法註冊的 Hooks。針對以上的範例,它會執行 initializer 中的程式碼區塊。

註冊一個已經執行的 Hook,會導致 Hook 立即執行。這允許 Hook 在仰賴多個延遲載入元件的程式碼中巢狀

initializer "action_text.renderer" do
  ActiveSupport.on_load(:action_controller_base) do
    ActiveSupport.on_load(:action_text_content) do
      self.default_renderer = Class.new(ActionController::Base).renderer
    end
  end
end
方法
O
R

執行個體 Public 方法

on_load(name, options = {}, &block)

宣告一個區塊,當 Rails 元件完全載入時會執行。如果元件已載入,區塊會立即執行。

選項

  • :yield - 產生 blockrun_load_hooks 的物件。

  • :run_once - 給予的 block 只會執行一次。

# File activesupport/lib/active_support/lazy_load_hooks.rb, line 60
def on_load(name, options = {}, &block)
  @loaded[name].each do |base|
    execute_hook(name, base, options, block)
  end

  @load_hooks[name] << [block, options]
end

run_load_hooks(name, base = Object)

執行所有透過 on_load 註冊到 name 的區塊,使用 base 作為評估內容。

ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)

針對以上的範例,它會在類別 ActiveRecord::Base 中執行所有註冊到 :active_record 的 Hooks。

# File activesupport/lib/active_support/lazy_load_hooks.rb, line 75
def run_load_hooks(name, base = Object)
  @loaded[name] << base
  @load_hooks[name].each do |hook, options|
    execute_hook(name, base, options, hook)
  end
end