Efficiently Architect Ruby on Rails Applications

by Nathaniel Rowe on September 9, 2016

It doesn't take much reading in regards to rails before you hit the "Convention over configuration" line. In my early days of development I had little idea of what that meant, either in terms of implications or for concrete uses. Now when I see that, I immediately think of arranging files within your application, how everything has a place, and how putting things where they belong make it quick and therefore efficient to find the files that need to change, make those changes and then update specs or associated files easily. That's less headaches, more features and happier client and developers at the end of the day.

{% capture efficient-development-toc %}{% include series/efficient-development-toc.md %}{% endcapture %}
{{ efficient-development-toc | markdownify }}

(No) God Models

When I look at old Rails apps, even ones that I wrote, the biggest thing that sticks out to me is how messy they are. Without fail, the messier a model is, the closer it becomes to a God Object. I'll save some posts on refactoring for another day, but ideally, we don't want to ever hit the point where our models get that bad. Better to give everything its proper place beforehand, and have the responsibilities and functionality of the models laid out beforehand and separated into their appropriate files. If you can isolate a subsection of the methods and attributes within a model, then chances are that code can be assigned a class name and moved into its own file. Now, there's such a thing as overkill, which at it's extreme is subdividing each model down to the point where it's only got one method and one attribute. Design your app to use skinny models that have what they need within them.

Controllers

Speaking of skinny and fat, for a solid few months there was article after article about "skinny controller, fat model," and that still pops up to this day. That's been pretty well established be an anti-pattern, and if you think about it, is really contradictory. At the end of the day, what you want is for each class, of which models and controllers are both made of, to only do what it needs. Nothing more, and certainly nothing less. The most consistent, and therefor in my mind, the best, way of doing this, is limiting all controllers to only restful actions.

Stay RESTful

Ever seen a controller like this?

class ProductsController < ApplicationController
  def index
    #index logic
  end

  #all other CRUD actions here

  def destroy
    #destroy logic
  end

  def main_report
    #report logic
  end

  def weekly_report
    #gives weekly products report
  end

  def annual_report
    #gives annual products report
  end
end

Now, not only is your controller doing things not associated directly with products, but your routes file is going to be messy as well. This is where convention comes in. Reports, of any variety, are different than CRUD actions for your products. Instead, what you want for each of those reports is a controller that looks like this:

class Reports::Products::WeeklyController < ApplicationController
  def index
    #index logic
  end
end

Do that for each of your reports, add the routes and then move any report logic into some appropriate PORO and you're set. Now everything has an appropriate place and can be easily found.

Views

Given that you've already stuck to RESTful routes, that will force your views to be architected in a proper manner. The following sections move away from what's considered architecture, but need to be touched on. Namely, using Slim and Simple Form to keep your app structured nicely and consistently so that way new developers can be brought on or you can come back at a later date and easily pick up where you need to. This section arguably could belong in my developing efficiently article, but the spirit of it fits better here than there.

Slim

I'll have a post up soon about how to setup and use slim for your application. Slim allows you to take a structured approach to your view files via indentation. HTML tags work on a whitespace/indent level basis, much like blocks in python. As such, it's incredibly easy to jump straight into a slim file then read and understand what's happening. Besides having cleaner syntax than erb, this enforcement of indent blocks solves my two main problems with erb, which were troubleshooting nested blocks of ruby code by properly identifying where to put the appropriate <% end %>, and working with the view file in an editor. I tried many html/erb editing modes across various text editors, but none would auto indent correctly and consistently when mixing ruby and html via erb. Slim editing mode has always been rock solid for me.

Simple Form

Much how slim provides consistency for your view files, simple form provides it for your forms. Using a variety of smarter inputs, helpers and options. Since forms are always user facing, it's important that they look nice. That's why I started using simple form: it integrates perfectly with bootstrap via a simple form bootstrap config file that can be auto generated on installing the gem and then running the bootstrap configuration generator. It's highly configurable, so any tweaks you need to make to out of the box behaviour are easy to do.

Modules

For both models, controllers and views, modules have ended up being my one stop shop. There should be a direct correlation between the directory and file structure of your models, controller, and views. When in doubt, remember that views and controllers should have the exact same namespacing as whatever model they're describing.

Wrap Up

Most of the suggestions in here were more abstract than my usual code and example based approach, but there are many more posts to come which will dive into the specifics of the sections described here.

The Value

At the end of the day, each of these articles on efficiency comes back to providing value to you, your customers, and future developers.

Ruby On Rails

Let's Get In Touch!


Our best work gets done when we can work face-to-face with you.

770-317-4866