Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

ruby - How can I preload concerns in a rails initializer using Rails 6/Zeitwerk?

I'm working with an initializer that does some monkey patching on app start by including some app concerns into a third party lib. Basically:

# config/initializers/my_initializer.rb

class SomeExternalLib
  include MyConcern1
  include MyConcern2
end

This works fine in Rails 5.2.3, but I got the following deprecation message when upgrading to Rails 6:

DEPRECATION WARNING: Initialization autoloaded the constants MyConcern1, and MyConcern2.

Being able to do this is deprecated. Autoloading during initialization is going to be an error condition in future versions of Rails.

Reloading does not reboot the application, and therefore code executed during initialization does not run again. So, if you reload ApplicationHelper, for example, the expected changes won't be reflected in that stale Module object.

These autoloaded constants have been unloaded.

Please, check the "Autoloading and Reloading Constants" guide for solutions. (called from at /Users/myuser/code/myapp/config/environment.rb:7)

My concerns are in app/controllers/concerns/. After some investigation, I figured out that that path wasn't being autoloaded, but I can't figure out how to make Zeitwerk—Rails 6's new autoloader—load this dynamically. I tried following the pattern for STI autoloading described here, but no luck. Any idea how to address this deprecation warning?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As described by @Glyoko's answer, using require on dependencies prevents autoloading in initializers. However, doing so leads to problems during reloading as @Puhlze mentioned in his comment.

I stumbled across an alternate approach that utilizes Rails.configuration.to_prepare in this post.

An example would be:

# config/initializers/my_initializer.rb

Rails.configuration.to_prepare do
  class SomeExternalLib
    include MyConcern1
    include MyConcern2
  end
end

Note that this runs before every request in development but only once before eager loading in production.

Edit: it appears to also work with reloading.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...