Welcome to Giant Robots Smashing Into Other Giant Robots — a weblog about development, business, design and technology — written by thoughtbot.
Skinny Controllers, Skinny Models
I hear a lot of people recommending the “skinny controller, fat model” approach
to Rails development. I’m all for keeping controllers simple, but who wants a
fat model? If your editor slows down while loading up your model files, I have
some advice: put your models on a diet.
Let’s say you have an application that needs to handle PDF documents. You have a very simple Document model to keep track of them:
1 2 3 4 5 |
class Document < ActiveRecord::Base validates_presence_of :title has_attached_file :pdf validates_attachment_presence :pdf end |
It’s just you and a skinny, attractive model. It’s going to be a good day.
But after your application has been live for a few days, it becomes clear that you need to provide a way to view these documents online, and your client’s weapon of choice is HTML. So, you add a method to convert your PDFs to HTML documents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class Document < ActiveRecord::Base # ... def convert_to_html # ...some fancy magic... end def converted_to_html? File.exist?(html_file_path) end def html_file_path File.join(HTML_STORAGE_DIR, pdf.original_filename + '.html') end # probably a few more methods... end |
Everything is working great, but now you have to look through all this HTML junk whenever you’re working on Document. Worse, the tests for HTML conversion and documents are all mixed up. Even worse, Document is getting pretty fat, and its model friends won’t stop making fun of it. If you don’t do something soon, this could mark the end of your good days with skinny models. A very common and simple technique can save us from this message: composition.
For some reason, many Rails developers seem to avoid using model classes that are not stored in the database. This leads to shoving too much key functionality into one of your key models, which of course leads to fat, incomprehensible model files and tests. I see no reason for an HTML file to have its own, separate entry in the database, but it certainly has enough behavior to warrant its own class. Let’s pull that functionality into an HtmlFile class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
class HtmlFile attr_reader :source_path def initialize (source_path) @source_path = source_path end def name @name ||= File.basename(source_path) + '.html' end def generate # ...some magic with file.path here... self end def path @path ||= File.join(HTML_STORAGE_DIR, name) end def exists? File.exist?(path) end # ... some other useful methods ... end |
Now we have another beautiful model. Let’s get these two acquainted:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Document # ... def html_file @html_file ||= HtmlFile.new(pdf.original_filename) end def convert_to_html @html_file = HtmlFile.new(pdf.original_filename).generate end end |
Result: two beautiful, skinny models. Analysis: it’s going to be a very good day.
About this entry
You're reading an entry on GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS, the company weblog of thoughtbot, inc.
- Author:
- Joe Ferris
- Published:
- May 1st 12:01 PM
- Updated:
- May 1st 12:01 PM
- Sections:
- Development
thoughtbot is hiring
We are hiring web developers and web designers in both Boston and New York, NY.
What are we up to?
We built Shoulda, an eclectic set of additions to Test::Unit; Paperclip to manage uploaded files without hassle; Jester, a REST/ActiveResource client library written in Javascript, and Squirrel, an enhancement for ActiveRecord's find syntax; — amongst some other projects.

Chad (President) and Jon (CTO) co-authored a technical book titled Pro Active Record: Databases with Ruby and Rails, which explores the ins and outs of the ActiveRecord ruby library. You can buy it today at Amazon.com.
About thoughtbot, inc.
We are a small web application development consulting business, with offices in Boston, MA and New York, NY. If you're looking to find a team for your next web development project or your new web application — get in touch.
14 comments
Jump to comment form