Reading the Source · Card 1
What belongs_to :user actually adds to your model
One short line. Behind it: a handful of methods on the model, some extra info Rails stores about the class, a validation, and a little dirty-tracking. Knowing what shows up changes how you read every Rails model.
The familiar line
You've written this dozens of times. What does it actually generate?
class Post < ApplicationRecord
belongs_to :user
end What's visible at the API surface
A Post is now connected to a User. You can call post.user and assign with post.user = some_user, and most developers stop there. Everything else Rails wires up from that one line stays invisible: builder methods, dirty-tracking helpers, a reflection on the class, a presence validation. When a method appears in someone else's model and isn't defined anywhere in the file, it almost always came from a declaration like this one.
Take a moment. Without peeking at docs or a Rails console, name every method belongs_to :user adds to a Post. Most people get to two. There are actually about eight on the instance, plus a few more things on the class.
What Rails generates
On every Post object, belongs_to :user adds these methods:
post.user # read the associated User
post.user = other_user # assign
post.build_user(name: "Karim") # build an unsaved User
post.create_user(name: "Karim") # build + save
post.create_user!(...) # raises if save fails
post.reload_user # bypass the cached instance
post.user_changed? # dirty tracking on the association
post.user_previously_changed? # dirty tracking, after save On the Post class itself, the same one line also sets up:
- A bit of info Rails keeps about the association, reachable as
Post.reflect_on_association(:user). Other parts of Rails read this when they need to know that Post has a user (for example, the form builder and eager loading). - A validation that requires the user to be set when you save a Post. (This is on by default in Rails 5+. Pass
optional: trueto turn it off.) - If you pass
touch: true, a callback that bumpsusers.updated_atevery time the post is saved. - If you pass
counter_cache: true, callbacks that keep a counter column on the User up to date as posts get added and removed.
Where this happens in Rails
The starting point is the belongs_to class method, defined in activerecord/lib/active_record/associations.rb. It hands the work off to a helper class called Associations::Builder::BelongsTo in activerecord/lib/active_record/associations/builder/belongs_to.rb. That helper is what actually adds the methods to your model, stores the reflection, and sets up callbacks if you passed touch: or counter_cache:.
The validation that requires the user to be present is added by the same builder. It's controlled by a global setting called belongs_to_required_by_default, which flipped to true in Rails 5. That's why some apps upgrading from Rails 4 suddenly see "User must exist" errors without changing any model code.
Why this is worth knowing
Memorizing the exact list isn't the goal. The point is to get used to a pattern: every Rails declaration like this one adds a small family of methods, stores some info about the class, and sometimes plugs in a validation or a callback. Once that pattern is familiar, post.build_user in someone else's code reads as "oh, that came from belongs_to" instead of "where is this method defined?"
The same pattern shows up in has_many, enum, has_secure_password, attribute, and delegated_type. Each line is a declaration, and each declaration adds methods plus a bit of class-level info behind the scenes. Once you start noticing it, looking up what a new declaration actually generates becomes a habit, instead of something you only do when stuck.