Beginner
Rails Autoloading is what happens in the background that most developers don’t even think about. The Rails Autoload is something that is important for you to know about. Rails will automatically load certain files of your Rails app application when it boots up.
When you first learn Rails you learn about its basic structure:
app/
models/
views/
controllers/
We call this âMVCâ for âmodel-view-controller.â
Then you get a little more experience and you learn about domain architecture and services. Perhaps you make a new Rails app and you notice an empty folder
Controllers/concerns/
And you look at this folder and you think, âWhat do I put there?â
Sometimes you must use the ârequireâ keyword to load filesâ- as you see in specs oftenâ but sometimes you donât. When do you use ârequireâ and when donât you?
Rails has an important piece of magic thatâs significant for every new Rails dev to know: the autoload with same-name, or correctly named, files. That is, Rails will autoload files for you if you meet the three conditions below.
Before letting you in on the secret, lets review the concepts of underscores, title case, and namespaces.
Underscore
An underscore is a character on your keyboard (probably to the right of the 0 on your number line). On most keyboards, you press SHIFT-(-). Press SHIFT and the dash key to produce an underscore, which looks like this: _ . The underscore appears where the underline would just below where a letter would be but denotes that there is no letter or number. Do not confuse the underscore with the dash, which appears in the middle of the line. On your keyboard, you donât hold SHIFT to create a dash character, and you do hold shift to create an underscore.
What does the underscore mean? The underscore means the space of âno characterâ when in fact it does represent a character in the computerâs implementation. Because loading from operating systems is finicky with spaces, we donât use spaces in our file names. Instead, we use underscores.
Here are some examples of Ruby files with underscores in them. You always use underscores when naming the actual files on your disk. (Even though your operating system might actually allow you to put a space in a file name, don’t do this when naming Ruby files.)
payment_adjustor.rb
line_item.rb
subscriptions_controller.rb
Titlecase:
Titlecase refers to a special syntax used by Ruby and some other programming languages to represent objects. In short, if you have several words, you make each of the first letters of each word uppercase and then you string the words together. So, if you have a phrase like âsomething wicked this way comesâ to make it title case would look like:
SomethingWickedThisWayComes
Note how we capitalize (uppercase) the first letter of each word but the other letters are not capitalized. Also notice how there are no spaces or underscore separating the words. We call this titlecase and it is how we write all objects in Ruby. (Do not confuse titlecase with camelcase, often found in other programming languages, which is very similar to titlecase but the very first letter of the whole object name is lower case. In our example, the camelcase of what we have above would be somethingWicketThisWayComes
with lowercase s
in something)
Namespace or Namespacing
A namespace, or namespacing (the act of applying a namespace), is really just when we want to group things together and give them a common element in their name, typically prepended (or put before). In Rails, we have a special way to namespace (explained below) using subfolders. But, if, for example, we wanted all parts of our application involving subscription management to be under the name âsubscriptions,â we might (actually, as I will explain below, we can and should) move our Ruby objects into a subfolder called âsubscriptionsâ and also namespace our objects by renaming them Subscriptions::
plus what we first called them.
A namespace is really just a way for programmers to group ideas together (and truly, it is probably a relatively poor way to think about object abstraction. The examples provided in this post provide examples of what I would call good use of namespacing. If you find a large system that is highly namespaced or is overly convoluted, you may have some antipatterns. This is because developers overused namespacing, or relied on it when they should have created more extensible encapsulations. This advanced subject is beyond the scope fo this post. Just keep in mind that namespacing, while a quick way to clean up small messes, should not be overused when what you really need are better abstractions.)
OK, now the 3 magic rules of the Rails autoload:
Your Rails files will be loaded by Rails if (and only if):
1) they are in the app/
folder or any subfolder
2) The name of the file matches, using the correct underscore-to-titlecase conversion when writing your Ruby class names. Put another way, your file names must be in underscores (and lowercase), and your Ruby classes that each file defines must match exactly (in titlecase) the name of its file.
3) When a file appears in a subfolder, which is encouraged, you must namespace it ââ the folderâs name (or namespace) is titlecased and prepended to the class name with ::
Those 3 rules are key. If you get them, you will master the Rails autoload.
Rails has all kinds of reasons why you would want to create sub folders INSIDE of other folders. For example, letâs say you have a polymorphic set of Products. That is, you have a Product object with a type column that Rails will use to instantiate the objects.
to verify you run
 bin/rails zeitwerk:check
Let’s say you have a folder in jobs called abc and a file called xyz_job.rb, but it doesn’t correctly define the object Abc::XyzJob
. (Maybe it defines no object or mis-spelled version of the object.). You would get:
expected file app/jobs/abc/xyz_job.rb to define constant Abc::XyzJob
in dev the eager load doesn’t happen, but in prod and asset compile it does, which it why unreferenced files don’t hiccup in dev but they do in prod. (so you didn’t see the load error in dev)
A Basic Polymorphic Example
class Product < ApplicationRecord
end
class Shirt < Product
end
class Purse < Product
end
In the type column, you will see the name of the subclass directly. I will start by making a new Purse called “Little Clutch”
2.6.4 :004 > Purse.create(name: “Little Clutch”)
(0.2ms) begin transaction
Purse Create (2.0ms) INSERT INTO “products” (“name”, “type”, “created_at”, “updated_at”) VALUES (?, ?, ?, ?) [[“name”, “Little Clutch”], [“type”, “Purse”], [“created_at”, “2020-05-13 16:55:49.132712”], [“updated_at”, “2020-05-13 16:55:49.132712”]]
(2.0ms) commit transaction
=> #<Purse id: 1, name: “Little Clutch”, type: “Purse”, created_at: “2020-05-13 16:55:49”, updated_at: “2020-05-13 16:55:49”>
Then, I will create a Shirt called “Button down”
2.6.4 :005 > Shirt.create(name: “Button-down”)
(0.1ms) begin transaction
Shirt Create (0.6ms) INSERT INTO “products” (“name”, “type”, “created_at”, “updated_at”) VALUES (?, ?, ?, ?) [[“name”, “Button-down”], [“type”, “Shirt”], [“created_at”, “2020-05-13 16:56:05.042379”], [“updated_at”, “2020-05-13 16:56:05.042379”]]
(1.0ms) commit transaction
=> #<Shirt id: 2, name: “Button-down”, type: “Shirt”, created_at: “2020-05-13 16:56:05”, updated_at: “2020-05-13 16:56:05”>
In the example above, the three Ruby files (Product, Shirt, Purse) all appear in the root of the models/ folder
In the example above, the three Ruby files (Product, Shirt, Purse) all appear in the root of the models/ folder
Polymorphic Autoload Example
Now letâs say we have many products and we want to move them into a sub folder called products/
We’ll want to do this with a little change to our class objects. Here’s what our new files & folders will look like:
Notice we did some things here: One, the superclass Product
(was product.rb) has been renamed to products/base.rb
The class names now have namespacesâ that’s because they are in the products/
folder. You must always match the folder name to the namespace, but you will titleize the namespace and keep the folder names lowercase.
So our new Purse becomes
class Producs::Purse < Products::Base
end
And now, our Shirt becomes
class Products::Shirt < Products::Base
end
One last thing, in our Products::Base we’ll need to set the table name:
class Products::Base < ApplicationRecord
self.table_name = 'products'
end
Now, Rails knows how to magically load your files. Never do anything else– like put non-namespaced files into subfolders. That is a Very Bad Thing and Very Bad Things will happen to you if you do.
Remember, Rails will magically load all of your objects in models/ controllers/ but only when the name of the object matches exactlyâ including the namespace to in titleized formâ with the name of your Ruby class. THE RAILS COACH
EXAMPLE APP FOR THIS POST CAN BE FOUND AT