[英]Rails 5: Load lib files in production
我已將我的一個應用程序從 Rails 4.2.6 升級到 Rails 5.0.0。 升級指南說,默認情況下,自動加載功能現在在生產中是禁用的。
現在我總是在我的生產服務器上收到錯誤,因為我在application.rb
文件中加載了自動加載的所有 lib 文件。
module MyApp
class Application < Rails::Application
config.autoload_paths += %W( lib/ )
end
end
現在,我已將config.enable_dependency_loading
設置為true
但我想知道是否有更好的解決方案。 默認情況下在生產中禁用自動加載肯定是有原因的。
移至 Rails 5 后我的更改列表:
lib
目錄放入app
因為app
所有代碼在 dev 中自動加載並在 prod 中預先加載,最重要的是在開發中自動重新加載,因此每次進行更改時都不必重新啟動服務器。lib
您自己的類的require
語句,因為如果它們的文件/目錄命名正確,它們都會自動加載,並且如果您保留require
語句,它可能會中斷自動重新加載。 更多信息在這里config.eager_load = true
以在 dev 中急切地查看代碼加載問題。Rails.application.eager_load!
在使用線程之前避免“循環依賴”錯誤。 如果您有任何 ruby/rails 擴展,則將該代碼保留在舊的lib
目錄中,並從初始化程序手動加載它們。 這將確保在可以依賴它的進一步邏輯之前加載擴展:
# config/initializers/extensions.rb Dir["#{Rails.root}/lib/ruby_ext/*.rb"].each { |file| require file } Dir["#{Rails.root}/lib/rails_ext/*.rb"].each { |file| require file }
我只是使用config.eager_load_paths
而不是config.autoload_paths
就像在 github 評論中提到 akostadinov 一樣: https : //github.com/rails/rails/issues/13142#issuecomment-275492070
# config/application.rb
...
# config.autoload_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('lib')
它適用於開發和生產環境。
感謝Johan建議用Rails.root.join('lib')
替換#{Rails.root}/lib
!
由於線程安全,自動加載在生產環境中被禁用。 感謝@Зелёный 提供鏈接。
我按照Github 上的建議將 lib 文件存儲在我的app
目錄中的lib
文件夾中,從而解決了這個問題。 Rails 會自動加載app
文件夾中的每個文件夾。
默認情況下在生產中禁用自動加載肯定是有原因的。
這是關於這個問題的長時間討論。 https://github.com/rails/rails/issues/13142
這允許 lib autoreload,並且也可以在生產環境中使用。
PS我已經改變了我的答案,現在它增加了兩個急切的自動加載路徑,無論環境如何,也允許在自定義環境中工作(如舞台)
# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...
只需將 config/application.rb 文件中的config.autoload_paths更改為config.eager_load_paths 即可。 因為在 rails 5 中,生產環境默認禁用自動加載。 欲了解更多詳情,請點擊鏈接。
#config.autoload_paths << "#{Rails.root}/lib"
config.eager_load_paths << Rails.root.join('lib')
它適用於環境開發和生產。
從某種意義上說,這是 Rails 5 中統一的方法來集中 Eager 和 Autoload 配置,同時它會在配置 Eager 加載時添加所需的自動加載路徑,否則將無法正常工作:
# config/application.rb
...
config.paths.add Rails.root.join('lib').to_s, eager_load: true
# as an example of autoload only config
config.paths.add Rails.root.join('domainpack').to_s, autoload: true
...
對於像我一樣為此苦苦掙扎的人,僅在app/
下放置一個目錄是不夠的。 是的,您將獲得自動加載,但不需要重新加載,這需要滿足命名空間約定。
此外,使用初始化程序加載舊的根級lib
將防止在開發過程中重新加載功能。
將 lib 文件夾移動到 app 有助於解決一個問題,我的 Twitter api 無法在生產環境中運行。 我有“未初始化的常量 TwitterApi”,我的 Twitter API 在我的 lib 文件夾中。 我的config.autoload_paths += Dir["#{Rails.root}/app/lib"]
有config.autoload_paths += Dir["#{Rails.root}/app/lib"]
但在移動文件夾之前它不起作用。
這成功了
我同意某些依賴項屬於lib
,有些可能屬於app/lib
。
我更喜歡為所有環境加載我選擇放在lib
所有文件,因此我在需要包之后但在打開MyApplicationName
模塊之前立即在config/application.rb
執行此操作。
# load all ruby files in lib
Dir[File.expand_path('../../lib/**/*.rb', __FILE__)].each { |file| require file }
這不依賴於Rails.root
(尚未定義),也不依賴於預先加載(對於環境可能已關閉)。
唯一對我有用的是在急切加載路徑中添加嵌套的 lib 路徑並在 config.to_prepare 塊中添加 require_dependency 。
# application.rb
...
config.to_prepare do
require_dependency("#{Rails.root}/lib/spree/core/product_filters.rb")
end
config.eager_load_paths << Rails.root.join('lib').join('spree').join('core')
...
總結 Lev 的回答: mv lib app
足以讓我所有的lib
代碼自動加載/自動重新加載。
(rails 6.0.0beta3 但在 rails 5.x 上也應該可以正常工作)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.