Ruby has a way of letting it know where to find classes and modules and other constants - $LOAD_PATH
.
Rails adds some of its default directories like app/controllers/*
, app/models/*
, etc. to this path. It also allows you to append to this path by adding the directory or pattern to the magical configuration autoload_paths
in application.rb
or any of the environment files like test.rb
or production.rb
. This setting is often leveraged by gems to add files pertaining to the gem to the $LOAD_PATH
for rails/ruby to be able to load them when required or instructed to - autoload vs eager load. There are tons of articles covering the autoload vs eager load part.
Instead I would like to talk about a small issue I noticed when abusing the loadpath, sort of, and why following Rails' conventions become necessary.
Say, you have declared a model in the path app/models/solution/article.rb
, and kept app/models
in autoload_path
, Rails through ActiveSupport#safe_constantize will be able to load Solution::Article
class. This is because app/models/solution/
like all other subdirectories are part of the $LOAD_PATH
.
When trying to load a top level class called Article
, Rails will not be able to find it, because it simply does not exist.
Now, say, if you've added app/models/**/*
in the autoload_path
instead. This would flatten the paths so that everything is available globally. Now when Solution::Article
is tried to be load, it's available like before. But if Article
is attempted to be loaded, even that's available as article.rb
is in the $LOAD_PATH
and Rails will throw up an error saying expected app/models/solution/article.rb to define the class Article
. 🤦♂️
Hence, it is always advisable to avoid using patterns like **/*
for flattening load paths to make class definitions available. They tend to mess up how Rails resolves classes and constants and with Rails moving towards the faster and cleaner Zeitwerk library for auto/eager/reloading of classes and modules, it becomes imperative to follow clean class/namespace definition practises.
Top comments (0)