簡體   English   中英

從Rails 3的lib文件夾加載模塊/類的最佳方法?

[英]Best way to load module/class from lib folder in Rails 3?

由於最新的Rails 3版本不再從lib中自動加載模塊和類,因此最好的加載方式是什么?

來自github:

 A few changes were done in this commit: Do not autoload code in *lib* for applications (now you need to explicitly require them). This makes an application behave closer to an engine (code in lib is still autoloaded for plugins); 

從Rails 2.3.9開始config/application.rb中存在一個設置,您可以在其中指定包含要自動加載的文件的目錄。

從application.rb:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

來源: Rails 3快速提示:自動加載包括所有子目錄的lib目錄,避免延遲加載

請注意,lib文件夾中包含的文件僅在服務器啟動時加載。 如果您希望自動重新加載這些文件,請閱讀: Rails 3快速提示:在開發模式下自動重新加載lib文件夾 請注意,這並不適合生產環境,因為永久性重新加載會降低機器的速度。

自動加載東西的魔力

我認為其他答案已經充分介紹了控制從中完成自動加載的文件夾的選項。 但是,如果有人根據需要修改了自動加載路徑后卻加載了麻煩的東西,那么此答案將試圖解釋自動加載背后的魔力是什么。

因此,從子目錄加載內容時,您應該知道一個陷阱或約定。 有時,Ruby / Rails的魔力(這次主要是Rails)可能使人們很難理解為什么發生了事情。 僅當模塊名稱與父目錄名稱相對應時,才會加載在自動加載路徑中聲明的任何模塊。 因此,如果您嘗試將lib/my_stuff/bar.rb

module Foo
  class Bar
  end
end

它不會自動加載。 再一次,如果您將父目錄重命名為foo從而將模塊托管在路徑: lib/foo/bar.rb 它將為您服務。 另一個選擇是使用模塊名稱來命名要自動加載的文件。 顯然,那時只有一個文件具有該名稱。 萬一您需要將您的內容拆分為多個文件,您當然可以使用一個文件來要求其他文件,但是我不建議這樣做,因為在開發模式下修改其他文件時,Rails無法自動進行為您重新加載。 但是,如果您確實想要,則可以在模塊名稱旁有一個文件,然后指定使用該模塊所需的實際文件。 因此,您可能有兩個文件: lib/my_stuff/bar.rblib/my_stuff/foo.rb ,前一個與上面相同,而后者只包含一行: require "bar"並且工作原理相同。

附言:我感到不得不添加另一件重要的事情。 最近,每當我想在lib目錄中有需要自動加載的內容時,我就會開始思考,如果這是我真正為該項目專門開發的(通常是一天)變成許多項目或git子模塊等中使用的“靜態”代碼段。在這種情況下,它絕對應該在lib文件夾中),那么它的位置可能根本不在lib文件夾中。 也許應該在app文件夾下的子文件夾中。我感覺這是新的Rails處理方式。 顯然,無論您在何處放置自動加載路徑,同樣的魔力都在起作用,因此對這些事情都有利。 無論如何,這只是我對這個問題的想法。 您可以自由地不同意。 :)


更新:關於魔術的類型

正如severin在他的評論中指出的那樣,核心“自動加載模塊機制”當然是Ruby的一部分,但是自動加載路徑的內容卻不是。 您不需要Rails來autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar") 當您第一次嘗試引用模塊Foo時,它將為您加載。 但是,Rails所做的是,它為我們提供了一種嘗試從注冊的文件夾中自動加載內容的方法,並且這種實現方式需要假設一些有關命名約定的方式。 如果尚未實現,則每次引用當前未加載的內容時,都必須遍歷所有自動加載文件夾中的所有文件,並檢查其中是否包含您要引用的內容。 這反過來會破壞自動加載和自動重新加載的想法。 但是,有了這些約定,它可以從模塊/類中扣除您嘗試加載可能定義的位置並僅加載該內容的嘗試。

警告:如果要從“ lib”文件夾中加載“ monkey patch”或“ open class”,請不要使用“ autoload”方法

  • config.autoload_paths ”方法:僅在加載僅在一個位置定義的類時有效。 如果已經在其他地方定義了某個類,則無法通過這種方法再次加載它。

  • config / initializer / load_rb_file.rb ”方法:總是有效! 無論目標類是新類,還是現有類的“開放類”或“猴子補丁”,它始終有效!

有關更多詳細信息,請參閱: https : //stackoverflow.com/a/6797707/445908

非常相似,但是我認為這有點優雅:

config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]

就我而言,我試圖直接在lib目錄下直接加載文件。

在application.rb中...

require '/lib/this_file.rb' 

即使在控制台中也無法正常工作,然后當我嘗試

require './lib/this_file.rb' 

Rails會完美加載文件。

我仍然還是個菜鳥,不知道為什么能行,但是行得通。 如果有人想向我解釋它,我將不勝感激:DI希望這對任何人都可以有所幫助。

我有同樣的問題。 這是我解決的方法。 該解決方案將加載lib目錄和所有子目錄(不僅是直接目錄)。 當然,您可以將其用於所有目錄。

# application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

config.autoload_paths對我不起作用。 我用其他方式解決

Ruby on Rails 3不會從/ lib文件夾自動重新加載(自動加載)代碼。 我通過放入ApplicationController解決它

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 

如果只有某些文件需要訪問lib中的模塊,則只需在需要文件的文件中添加一條require語句即可。 例如,如果一個模型需要訪問一個模塊,請添加:

require 'mymodule'

在model.rb文件的頂部。

Rails 5 ,建議將lib文件夾放置在app目錄下,或者為該文件夾創建其他有意義的名稱空間,如servicespresentersfeatures等,並將其放置在app目錄下以供Rails自動加載。

請同時查看此GitHub討論鏈接

有幾種原因可能會導致您從lib加載時遇到問題-有關詳細信息,請參見此處-http: //www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/

  • 修復自動加載路徑
  • 線程安全相關
  • 命名相關
  • ...

正確拼寫文件名。

說真的 我與一個班級競爭了一個小時,因為該班級是Governance :: ArchitectureBoard,並且文件位於lib / governance / architecture_baord.rb中(“ board”中的O和A換位了)

回想起來似乎很明顯,但這是魔鬼的追蹤。 如果該類未在Rails希望基於修改類名的文件中定義,則根本不會找到它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM