Rails loads ActionCable via Zeitwerk

0
42
Saeloun Logo


Starting with Rails 6, Rails shipped with a new
and better way to autoload,
which delegates loading to the
Zeitwerk gem.
This is the zeitwerk mode.
Before Rails 7, it was still possible to switch back to the classic mode
which used an autoloader implemented in Active Support.
Rails now does not include this autoloader anymore.

Unfortunately,
not all native Rails modules
have been moved to the Zeitwerk yet.

Before

The classic autoloader has been extremely useful,
but had several issues that made autoloading a bit tricky
and confusing at times.
At a high level,
the classic mode loads files
by looking them up on Module.nesting
and Module.ancestors.
This was a traversal, therefore, the first match would be loaded.
While this works fine most of the time the classic mode ran into some obscure failures.
Zeitwerk takes an entirely different approach
in auto-loading by registering constants to be autoloaded instead.
This removes the dependency load order.

Let’s look at a quick example,

# app/models/user.rb
class User < ApplicationRecord
end

# app/models/admin/user.rb
module Admin
  class User < ApplicationRecord
  end
end

# app/models/admin/user_manager.rb
module Admin
  class UserManager
    def self.all
      User.all # Want to load all admin users
    end
  end
end

In the classic mode,
if Admin::UserManager was loaded
before Admin::User,
then calling User.all would load from User
instead of Admin::User.

However with Zeitwerk,
Rails will call Zeitwek#setup.
This method takes care of setting up the autoloaders
for all of the known autoload_paths.
The above example will look something like this,

  autoload :User, Rails.root.join('app/models/user.rb')
  autoload :Admin::User, Rails.root.join('app/models/admin/user.rb')
  autoload :Admin::UserManager, Rails.root.join('app/models/admin/user_manager.rb')

Back to ActionCable! Prior to this change,
one had to specifically autoload all dependencies
of ActionCable so as to not run into any const_missing error callbacks.

  # actioncable/lib/action_cable.rb

  autoload :Server
  autoload :Connection
  autoload :Channel
  autoload :RemoteConnections
  autoload :SubscriptionAdapter
  autoload :TestHelper
  autoload :TestCase

After

Thanks to this PR, much of this ‘bureaucratic’ code can now be removed!



Source link

Leave a reply

Please enter your comment!
Please enter your name here