Learning Ruby on Rails: Why? How? Pitfalls?

Ruby | Rails | jRuby | - May 9, 2013 // Barry

I've always been a proponent of the "right tool for the job" approach to programming. Different languages are well suited for different situations. Over the past 2 years I've spent a great deal of time with Ruby on Rails after coming from a background of PHP, Java and Perl. Here's how I got started and some of the lessons I learned along the way.

I'd been interested in Rails as far back as 2005.  When you're working in a world of unstructured PHP and Java, it's difficult to avoid looking for a better way of doing things.  I tried Struts v1.0 with Java before realizing the error of my ways. Eventually, I came across Rails, it's naming scheme, consistent structure, ActiveRecord, etc and I was enthralled. The problem was that the company I worked for at the time was PHP/Java shop so I ended up going with CakePHP instead as it provided broad support across PHP versions, excellent documentation, and a mimicked Rails very closely.

I dove deep into CakePHP. At Brightball we even built a system as the backbone for all of our projects with it that automated the repetitive parts of our projects by leveraging the naming scheme and introspection. Because of that, when I picked up Rails a lot of the principles were very natural. Almost any experience with MVC architecture will go a long way though.

So, getting straight into the material there are 3 excellent resources that I used to get a complete picture of Ruby on Rails.  When I say "complete" I don't mean to say that I have learned it all or anything close to it, but what I do know from my experience with CakePHP is that you do need to understand how everything fits together to properly utilize the system. Otherwise you'll find yourself wasting time writing code that the framework was already setup to handle for you.

Resource 1 -

This is an interactive web walkthrough of the ruby language that can be completed in about 30 minutes or less. It will help to familiarize you with the syntax. It's important to note that you can actually focus on learning Rails without spending a lot of time on Ruby itself so this ends up being just about all the introduction you need.

Resource 2 - Rails Tutorial

This is an entire book, available for free online.  I've linked to the Rails 4.0 version but there is also a Rails 3.2 version which is what I actually used.  This book covers everything you need to get into Ruby on Rails "the Rails way". It will cover setting up your machine, the technologies involved, what you'll need for a good development workflow, unit testing as you develop, and put all of this together as you continue building one complete application.  

You'll learn to setup Ruby Version Manager (RVM) which allows you to easily manage multiple Ruby installations on your machine and automatically switches to the right one when you cd into it from the command line. The book covers setting up a Rails project, creating a database, managing changes to that database with migrations, running unit tests efficiently, deploying to Heroku, managing versions of outside libraries with the Gemfile and Bundler, and much more. Once you've finished this book, you should actually be perfectly comfortable to start developing with Rails.

Resource 3 - Deploying with jRuby

Wait...jRuby? I thought we were learning Ruby?

We are. After spending the last year and a half managing/repairing a terrible development job from another team on a 65 Dyno Heroku site, I was able to get to know Ruby's strengths and weaknesses intimately. Ruby's biggest strength is that it empowers developers to efficiently develop and manage huge systems with a lot of complexity in a manner that makes sense. This strength comes from the language's flexibility, which I'll get to in a minute. The problem is that in a production environment this flexibility often results in memory leaks, instability and performance issues.

Enter jRuby. I've never made my dislike of Java as a web language a secret. As a language, it's great but the compile/deploy workflow is incredibly inefficient for a developer. The Java world is divided into two parts though: the language and virtual machine (JVM). The JVM is a currently unrivaled work of art and over the last few years numerous existing languages have been ported to run on the JVM while new languages have just been written to run on top of it (such as Groovy, Scala, Clojure, etc).

Running Ruby on the JVM fixes just about every production issue that Ruby has as a language. jRuby can actually analyze your code to see if you're doing any of the things that it would like to turn off to optimize the code and if you're not, it will let you take advantage of the performance gains. Here's a few numbers and examples. Aside from that, the JVM's garbage collector totally removes the memory leak issues providing a stable memory footprint.  Lastly, the JVM's Just-In-Time compiler actually figures out ways to speed up your code the longer it runs. This process is usually referred to as "warming up the JVM."

The added benefit of running jRuby, if all that wasn't enough already, is that also allows you to include and use Java libraries directly in your code. Considering the breadth and scope of the Java world...that's huge and it dramatically expands your available tool belt. Now you can not only deploy wherever Java can be deployed, but you can play with their toys too.  There are Rubyized versions of nearly every existing Java Application Server too. 

Back to the book, this book covers the major app servers like Trindad (aka - Tomcat) and Torquebox (aka - JBoss). It's similar to the Rails Tutorial online in that it will help you get everything on your machine setup, walk you through converting a Ruby application to a jRuby application while then covering deployment and monitoring with the available tools/servers. 

The machine setup coverage in this book is very interesting because it goes in depth on a very powerful development setup: Vagrant with Puppet (but you can also use Chef). Vagrant is basically a tool that let's you use a virtual machine from the command line, SSH into it, configure it with Puppet/Chef, and deploy your code to it. This setup allows development teams to easily mirror the production environment locally regardless of their local operating system, while keeping that production configuration in version control with the rest of the code.

Getting back to Ruby on Rails

Now, those are the resources I'd recommend most highly. Certainly, you'll run into other great material out there, not the least of which are the Rails docs themselves, but these were the most comprehensive and useful materials that I've come across.

Ruby as a language is an interesting animal. I alluded to it's flexibility earlier and this flexibility largely derives from two things: everything is an object and objects can be monkey patched. Monkey patching is the process of modifying existing classes.

For example, in Ruby if you wanted to create a function to tell if a String was a palindrome you could monkey patch the palindrome function onto the root String object, allowing you to do this anywhere in your code:

"this is not a palindrome".palindrome?

That is powerful. It's also incredibly dangerous, which is one of the reasons that unit testing is so important in Ruby as opposed to other languages. It's always possible that a 3rd party library could inject a monkey patch that changes an existing function.  If so and this causes anything to break, unit tests will catch it (assuming you've written them well).

One other perk to monkey patching is that it makes testing significantly simpler because once you've tested a function, the testing libraries like rspec make it simple to leverage monkey patching via "stubs" to fake functions and their return values on actual classes rather than having to mock the entire thing. Makes testing a lot more enjoyable.

The key thing to remember about monkey patching is that it allows for the ruby language to be altered to better meet the needs of the task at hand. That's what Domain Specific Languages (DSLs) are for and that's exactly why so many DSLs are written in Ruby (Puppet and Chef for example).

Rails itself isn't just a framework, it's a DSL for the web.

That inherent flexibility creates very powerful 3rd party libraries. Between the existing libraries, the mature package management, ability to segregate and manage multiple language/gemsets easily on a single machine, use Foreman to start and observe all of the pieces of your complex application simultaneously in development and then switch out different parts of the framework to suit your needs...well that is a powerful development stack.

And the thing that I've found the longer I've been using Rails is this: if there is anything in any of these moving parts that would make it too complicated for one person to manage the whole thing...somebody built a way for one person to manage the whole thing. If you ever have to do something more than once, somebody built a way to fix it. If there is pain in the development process, somebody built pain relief. The Ruby/Rails community has been nothing short of amazing in my experience thus far.

When it comes to the database side of life, I'm a big fan of the implementation of Active Record.  Specifically because you can use it to eliminate the repetitiveness of generic SQL but it also makes it possible to take advantage of many features that you could only use by writing native SQL, thanks to "scopes". A scope is basically a piece of a query. You can combine as many pieces as you like and none of it is executed until you actually retrieve a value. That allows the use of native full text search logic that can be easily combined with other query parameters, just as an example. By default Rails stores a copy of your database schema in database independent code, but if you're taking advantage of any of the powerful features in your database you can set it to store the schema as raw SQL instead. I strongly recommend that.

Lastly comes the rails console. Ruby and many other languages provide an interactive console from the command line, but the rails console allows you to start your entire web application from the command line. From there you can test just about anything in your code, using anything in your code, without having to bother with all the setup time. There is even a tool called Pry that will provide more robust output as well as the ability to pause your code and give you back the command prompt so you can figure out exactly what was going on in a particular situation.

You combine development efficiency, robust tools, a mature deployment stack and a language that has a way of making complex tasks a lot simpler but without removing your ability to dive into the details when needed.