With the exception of some basic HTML back in middle school, my first exposure to programming was during my sophomore year of college. At the time, I was majoring solely in astrophysics. To satisfy one of the requirements for my degree, I took a class called Introduction to Numerical Techniques in Physics, which had been described to me as basically “programming for physicists”. Since I’d always been interested in both computers and computing, I excitedly signed up for the only 8 AM class I would ever take in college.
I quickly came to realize that, even though the course claimed to be an “Introduction” and there were no CS prereqs, this class wasn’t going to teach me anything about programming. I struggled through the semester; by the time finals rolled around, I barely had a clue about such advanced topics as “loops” and “conditionals”.1
The following summer, I took a truly introductory programming class. The difference between the two classes was, frankly, night and day—it’s amazing how much easier it is to learn when you start with a simple “Hello, world!” program instead of simulating supernovae and generating solutions to complex systems of differential equations from the get-go. Once I had a little more background and context, I fell in love with writing code. By the time that the summer finished, I’d already decided to pick up a second major: computer science.
During my internship, I was exposed to my first
ActiveRecord. At first, I thought that it was the most wonderful tool that I’d
ever encountered—with a simple
update_attributes, I could update my
data without ever having to write a single
I’ve learned a lot since then. I now know that both Rails and ActiveRecord, while great tools, have enough flaws to warrant their own lengthy blog posts. Happily, I no longer shudder at the sound of the phrase “raw SQL”; in fact, I’ve come to enjoy writing out queries, views and common table expressions manually. When well-written, it tends to be quite readable and straight-forward, and writing it out yourself can sometimes make performance gains easy to come by.
With all that said, I still avoid committing much raw SQL to this day. Why, you ask? There are a few reasons, but I want to concentrate on one in particular: future-proofing.
One of the great advantages of sticking with an ORM is generalization. If you
write raw SQL all over your Postgres-backed application only to discover that
your client needs you to use Oracle a few years down the road, you’re going to
have to search through your entire codebase to figure out if anything needs to
be rewritten to be compatible with Oracle. Meanwhile, if you’d stuck with
ActiveRecord, all you’d need to do is swap out the adapter specified in your
database.yml. Using ActiveRecord also makes it much less painful if you need
to connect to different types of databases in different Rails environments—I’ve
seen it happen—since all ActiveRecord queries will get automatically translated
into the proper dialect before they hit your database.
That said, ActiveRecord isn’t perfect, and it’s unfortunately not as feature-complete as raw SQL when it comes to interacting with your database. Luckily for those of us who tend to hit plenty of use cases too complicated for ActiveRecord to handle—writing software for the world’s leading minds tends to be non-trivial—Rails gives us another option for keeping our database code generalized: Arel.
For those who have never used it before, Arel is the AST manager used by ActiveRecord; basically, it’s the level below ActiveRecord that determines how to construct the actual SQL string that’s sent along to and executed by your database. It also happens to let you write Ruby in a lot of places that ActiveRecord would require a raw SQL string.
The power, flexibility and generalizability behind Arel prompted me to write a short series of posts containing intermediate Arel recipes for the blog over at scimedsolutions.com. You can check the originals out there or read slightly modified versions here on andycandrea.github.io.2 Heck, you can even read both if you so desire, though the content is quite similar.