Fat Models
Unlike the fashion world, we Rails geeks prefer fat models. When we see Kirstie Alley we say, “That’s what I’m talkin’ about.”
A fat model, um, carries its weight. Not slacking off, it does everything it’s capable of doing for itself. This makes a fat model responsible for itself. It’s responsible for managing its own associations; for wiring its dependent objects to itself. It’s responsible for any business logic that it should be taking care of, including validation of its state. A fat model is more likely to be reusable; at a minimum it will be easier to use. Fat models are not deadbeats.
Fat models, consuming all that responsibility for themselves, result in skinny controllers. The role of a controller is to drive the application flow, not baby-sit the model. Controllers respond to input, use the model to get state and behavior, and render the right responses. When the controller is doing work that the model should be taking care of itself, it’s much harder to reuse that behavior.
Encapsulation
To any experienced OO advocate this sounds like basic encapsulation, and it is. In an MVC world, it sounds like basic separation of concerns, and it is. Fat models encapsulate their state (typically what’s stored in the database) and behavior (business logic, relationships, validation). However, I think it bears repeating for a couple of reasons:
- It’s easy, and therefore tempting, to hack some business logic into a controller, even
a view. Not even Rails, which embraces MVC like few other frameworks, can do much to prevent laziness and sloppiness. Not everyone is an experienced OO advocate.
Benefits
Besides reusability, another benefit of fat models, and encapsulation in general, is testability. It’s easier to write a unit test for a model than to write a functional test for a controller. It’s just less work; there are fewer dependencies/collaborators/fingers in the pie, and you can test the model in relative isolation. You’ll still want to write a functional test for every controller, but you should have to test little more than the responses to different requests, not the business logic, because business logic is covered by your simpler unit tests.
You’ll also find that your controllers, where much of the complicated interaction between the crazy user and your application is handled, are much simpler. They’ll be easier to read and maintain, which at least as important as how easy they were to create. When responsibilities are focused, noise is reduced, and we’re more capable of understanding intent. That makes us better at identifying patterns and where we can improve design by refactoring away repetition.

Now me, personally, I like a woman with a little meat on her bones. It gives me something to hold on to… What?… Ruby models? Oh (eyes blink). Great write up. I really like the part about testing and separation of concerns. Ruby and it’s lovechild, Ruby on Rails, never cease to amaze me.