A namespace is a way to group related functionality together in a modular way. Rails 7 has improved the support for the custom namespace, now there is a better way of adding the custom namespace to application components while autoloading.
Rails by default autoloads all the subdirectories in the
app folder except assets
, views
, and javascript
.
Even if there is a custom directory inside the app, for example, app/services
, we
don’t need to configure anything to autoload it, Rails does it automatically.
In a Rails application, file names have to match the constants they define,
with directories acting as namespaces.
For example, the file app/services/users/signup.rb
has to define the constant
like Users::Signup
.
But what if we would like all our services in app/services
under Services
namespace, it means that we would want to
define a constant like Services::Users::Signup
.
One way to accomplish this is to create a subdirectory
like app/services/services
and
then we can put all our services under the services namespace.
But this doesn’t feel right, there should be a way to define file
app/services/users/signup.rb
constant like Services::Users::Signup
Before
Now there are two modes of autoloading files in Rails, one is the classic
mode
and the other is zeitwerk
mode.
Classic
In classic
mode we can define constant in both ways for a
file app/services/users/signup.rb
. It means that Services::Users::Signup
and Users::Signup
are valid constant names.
But it creates ambiguity.
Zeitwerk
In zeitwerk
mode we can only define Users::Signup
but
there is a workaround.
Zeitwerk supports custom root namespaces
and we can customize main autoloader.
In the above code, we created a Services
namespace, we can create it like this or
we can create it elsewhere and then require
it here.
Next, we used the main
autoloader to do the task.
The push_dir
method takes a module or class object as the second argument.
Applications running on Rails < 7.1 have to additionally delete the
directory app/services
from ActiveSupport::Dependencies.autoload_paths
.
After
Now after this patch, we can add the custom namespace Services
without
creating a subdirectory like app/services/services
.
We just have to customize the main autoloader like below and that is it.
There is no need to delete app/services
from ActiveSupport::Dependencies.autoload_paths
.
For more information about this patch, please go through
this PR.