Start a hosting plan from $3.92/mo and get a free year on Tuts+ (normally $180)
Your choice, when learning a new framework, is an incredibly important one. It takes countless hours and effort to become proficient and learn all the best practices - even for experienced developers.
That's why it's necessary to understand the peculiarities of a framework as early as possible, in order to determine if it's the right solution for the problem that you're trying to solve. In this article, I'll cover many of the key areas of the Ruby on Rails framework, and why I feel that it's an excellent choice for web developers.
Ruby on Rails was extracted from the project management application, Basecamp.
It's based on the Ruby programming language, and the current stable release is 3.2 - with 4.0 just around the corner!
RoR is a full web application stack; starting with version 3.1, it also includes facilities and libraries to manage frontend code, supporting Sass and CoffeeScript out of the box, with no need for external tool to manage the compile process. Opinionated workflow is the name of the game with Rails.
For development, it embeds its own web server, so that you don't need to install extra software apart from a working Ruby installation.
Why Learn It?
There are countless reasons for learning Rails, ranging from technical to business and productivity. We'll tackle each one by one.
Ruby has been designed to be a "joy to use".
As its name implies, Rails is based on the Ruby language. Invented in 1993 and released for the first time in 1995 by Yukihiro Matsumoto (widely known simply as "Matz"), Ruby is an object-oriented interpreted language that features a syntax heavily inspired by Perl and Lisp. Since its inception, Ruby has been designed to be a "joy to use" - meaning a strong focus on readability and elegance.
Being a higher level language, Ruby is extremely powerful and versatile, while maintaining a good balance of clarity and performance (bearing in mind that it's still an interpreted, dynamic language).
The original Ruby interpreter (Matz's Ruby Interpreter, shortened as MRI) is written in C, but it's not the only one available nowadays (a couple of notable alternatives are JRuby, running on top of the JVM, and Rubinius).
Ruby features several libraries shipped with its core, including a very powerful unit testing one, called Minitest (prior to Ruby 1.9, Ruby used TestUnit).
Rails is a popular way to get involved with Ruby, so it's not rare nowadays to find people (including myself) whose first introduction to Ruby was through Rails.
Learn the fundamentals of Ruby with Tuts+ Premium.
Rails is strongly opinionated, when it comes to architectural decisions
Rails is a database-agnostic MVC framework that chooses convention over configuration, which means that it's strongly opinionated, when it comes to architectural decisions, naming conventions, paths and patterns.
In more detail:
MVC means that it follows the Model-View-Controller paradigm, so that you can clearly separate concerns when developing an application. This allows your core business logic to be in a single place, avoiding duplication and assisting with maintenance.
It follows a RESTful, resource-oriented approach, meaning that it encourages you to think about your business logic from the data standpoint, exposing resources to endpoints that perform CRUD actions. For example, logging into a site can be seen as 'creating a session'; logging out as 'destroying a session'. This approach takes some getting used to, but once you've adopted that mindset, it helps in keeping your interfaces consistent and predictable by other developers. Rails applications tend to revolve around models, which manages data persistence.
It uses Bundler as a dependency management tool, leveraging the power of the Rubygems community. This ensures a consistent approach for adding third party functionality to an application, with an explicit format that details which libraries we need, and which versions, including resolving nested dependencies.
It can support a wide range of databases, with SQLite as a default (good for development) and MysQL and PostgreSQL as first choices for production. MongoDB can also be integrated with minimal effort.
Convention means that naming, paths and patterns are usually predictable and shared among fellow Rails developers. This ensures an easier learning curve, focused on the business logic for the app, easier maintenance and less documentation.
A Rails application can be easily deployed to cloud infrastructures, like Heroku, or straight to private servers (it runs great on Ubuntu Linux, for example).
Here's a basic rundown of what Rails can do out of the box, along with some code examples. Please note that, even if you've never worked with Rails before or even don't know Ruby, this should not prevent you from understanding them, as they are quite readable.
Support for data model definition through migrations, i.e. repeatable and reversible database agnostic instructions, which manipulate the database structure. Consider the following migration:
class CreateEvents < ActiveRecord::Migration def change create_table :events do |t| t.string :title t.date :start_date t.date :end_date t.boolean :live, :default => false t.timestamps end end end
This migration creates an
eventstable, with some basic data, like a
title, and uses specific data types that are mapped to specific column types in the underlying database. For example, by default,
VARCHAR(255)column, if using MySQL. This migration can be written manually from scratch, or generated from the command line and then edited before being run.
Database agnostic model interface for CRUD actions. Here's a few examples, given a
news = News.new(title: 'Sample news') # => returns a news instance, not saved to the database news.save # => runs an insert query and updates the instance with the returned id from the database news.title = 'Updated sample news' # => sets the title to the new value, without saving to the database news.save # => runs an update query for that item news.destroy # => runs a delete query for that item
In addition, Rails provides a simple interface to perform selection queries, including joins between models.
News.where(published: true).order('created_at DESC').limit(5) # => produces 'SELECT * from news where published = 1 order by created_at DESC limit 5'
Support for validations; an
Eventmodel may always require the presence of a unique title. In that case, it's possible to clearly express these requirements in the
class Event < ActiveRecord::Base validates :title, :presence => true, :uniqueness => true end
This functionality ensures that no invalid record is saved to the database, and also provides all the bindings needed to display validation errors to the user (for example in a form).
Session and cookies with simple helpers to set values, get and delete them, with transparent signature.
Protection against form forgery, so that any form you generate through Rails is automatically signed with a token that guarantees its genuinely.
Aggressive XSS protection policy enabled by default, so that any form element you use is protected by default, unless you explicitly whitelist it (careful when doing that!).
Simple management for
POSTdata, accessible through a simple hash available in every controller action.
Simple bindings to connect controllers, models and views, with clear and conventional rules that simplify file management and code. For example, consider the following controller that is responsible for rendering a news list page at
class NewsController < ApplicationController def index end end
Even without writing any code to define what
indexdoes, Rails provides a default behaviour, which is to render the
app/views/news/index.html.erbview. This reduces the need for boilerplate code, as, most of the time, it's just necessary to override behavior, when unconventional.
Integration with external services; Rails offers a rich ecosystem of applications that you can use to monitor, maintain and improve your application (some of them work with other frameworks as well). New Relic helps in monitoring performance, Airbrake Bug Tracker collects exceptions to notify the development team, Code Climate analyzes your codebase for quality, complexity and duplication, Tddium and TravisCI can run your test suite remotely against different Ruby versions.
As noted previously, Rails also offers an integrated environment to work with Coffeescript and Sass, with transparent compilation in development and preprocessing and cache busting for deployment, so that your production app will serve single, minified files with a signature in the filename. This way, you can be absolutely sure that any browser will always load and cache the latest version of the file.
Have you ever wondered why Rails is the first choice of many web startups? There are two primary reasons:
It lets you work on features with minimal boilerplate, removing a lot of non-business related work from the development process. This translates into increased velocity in developing and deploying new features, which is key to understanding if the product is solid.
Rails' structure makes it easy to accommodate change. This is certainly true for many MVC frameworks, though Rails is particularly good at restructuring your application flow, reusing components in a simple way.
It's important to remember that, frequently, development time is more costly than an extra server.
There's always an ongoing conversation about Rails performance, and how it can become a bottleneck when you get thousands of hits a minute. The problem is that getting to that level of traffic requires a huge effort. The truth is: 9 times out of 10, scalability is a problem that many companies never need to face. To them, the ability to make changes, easy maintainability and predictability are far more valuable.
In addition, it's important to remember that, frequently, development time is more costly than an extra server. A framework like Rails is often preferred, because, even if it may need more powerful hardware, it's still cost effective in other areas.
This doesn't mean that you shouldn't care about the performance of your code or worry about topics, such as caching and query optimization. Instead, it means taking into account the full spectrum of hardware and software changes you can make; sometimes, it's sensible to pospone a performance focused chunk of work and temporarily have more powerful hardware to continue working on important features.
Extending the Framework
Rails can easily be extended with a wide variety of external libraries, distributed through Rubygems. Most of the times, any feature that you need to build is already offered through a gem. Now, this doesn't mean that adding gems is the perfect solution; every third party dependency that you add to an application becomes a risk factor.
Sometimes, it's preferable to roll your own version with custom code.
That said, you shouldn't reinvent the wheel. Many Rails applications use the same gems to provide specific features; this can be seen as an advantage. Remember: wide usage translates to wide testing, so it's considered a safe practice to use certain well known gems to accomplish key tasks. Here are a few examples:
- Devise, for user signup, login and management
- Simple form, for easy and customisable form markup generation
- Kaminari, for pagination
- ActiveAdmin, for rapid admin pages
This list could easily go on, but the point is that Rails leverages the modularity of a Rubygems-based approach and can greatly speed up development, by placing focus on building features that matter for the product you're working on, instead of boilerplate.
Why I Enjoy Working With Rails
I can focus on what matters for clients without compromising on good code quality.
Roughly two years ago, I was working in a marketing/product management role (doing web development as a hobby); that meant focusing on product features, their business value and the cost associated with their development. When I decided to switch careers, Rails 3.0 had just been released. I spent an afternoon watching videos and reading tutorials. I quickly decided that Rails was what I wanted to focus my efforts on.
The reason - and this somewhat overlaps with what we've already discussed - is that I could see a practical approach in the framemork, a clear goal to be productive and focus on the product and its development. I could get things done in a short amount of time. After a few months of intensive self-training through various web tutorials and some sample applications, I applied for my current job as a Rails developer at New Bamboo.
I enjoy working with Rails every day, because I can focus on what matters for clients without compromising on good code quality. To me, it's the perfect starting point for most web-based applications.
It doesn't solve all the problems you'll encounter, when building large web applications. There are times when you clearly see that Rails isn't fit for a specific kind of service, but that's the time to split the architecture into smaller applications.
Rails is a powerful framework that can help you become more productive and confident, when working on complex projects. This is possible, thanks to its strong conventions and solid structure. Large companies, such as 37 Signals, Pivotal Labs, Groupon (or even Twitter in the old days) have chosen Rails as the base architecture for their core applications. There's a reason why!
Ready to start Riding Ruby on Rails?