RailsSpace
Building a Social Networking Website with Ruby on Rails
by Michael Hartl and Aurelius Prochazka
Chapter 1 - Introduction
RailsSpace teaches you Ruby on Rails by developing a real-world application: RailsSpace, a social networking website aimed at the Rails community itself. We take you step-by-step, from the virtually static front page, through user registration and authentication, up to a highly dynamic site with user profiles, image upload, simple blogs, full-text and geographical search, and a friendship request system. Though certainly not intended as a serious competitor to the social networking heavyweights, RailsSpace is not a toy; it's designed to show how to use Rails to make a web application suitable for deployment into a production environment.
1.1 Why Rails?
Ruby on Rails is a tool for making web applications—and it's freakishly good at it. If you're reading this (which, evidently, you are), you're probably wondering what makes Rails so special. When you ask a programmer who has already fallen in love with Rails, maybe he'll tell you it's "agile", and you'll have to read up on what that means to coders. Or maybe you'll be bombarded by a list of acronyms like ORM, MVC, or DRY. While these are all cool features of Ruby on Rails, the real reason Rails rocks is not about vocabulary; it's about the philosophy of efficient design.There's that word: design. It's a slippery concept, yet unmistakable. Good design is like pornography: you know it when you see it. Rails is like very, very good pornography. What makes the design of Rails so good is difficult to pin down, but we'll do our best. We think the heart of it is free productivity.
1.1.1 Productivity wants to be free
The short, short version of free productivity is that Rails has an eerie ability to anticipate your needs as a web programmer. That's not very concrete, though, so let's get a flavor for the free productivity Rails provides by looking at a list of examples. Not all of these will make sense to you right now, but they should be able to help you develop an intuition for the kinds of things Rails is good at.
- Ruby: Rails applications, as well as Rails itself, are written in Ruby, a dynamic, object-oriented programming language. Ruby comes out of the Perl tradition, and Yukihiro "Matz" Matsumoto, the creator of Ruby, calls it "a better Perl than Perl". In our experience, most programmers with exposure to both languages agree. We'd add that, for web programming, embedded Ruby (ERb) is a better PHP than PHP. Being able to tap into the power and elegance of Ruby is a major advantage of Rails.
- Mapping of database tables to Ruby objects: There are no messy SQL calls in most Rails applications—instead you'll find Ruby objects. Rails does the dirty database work behind the scenes. (If, by some chance, you do want to execute some raw SQL, Rails lets you do that too.)
- Automatic conversion of data models into HTML and back: There's seamless integration between the code for modeling objects in your system and the code to display them to the user. This is nowhere clearer than in data validations; for example, if your data model requires users to put in an email address, but the user submits a form without one, Rails automatically catches the error and puts it in a variable for display back to the user.
- Built-in support for automated testing of data models and web pages: Rails makes it easy to write test suites that verify the integrity of your data model and the correctness of the pages on your site, allowing you to be confident that changes to your code will not break your application.
- Database-independent creation and alteration of database tables: Rails migrations make it easy to create your data models, make changes to them, and roll them back if necessary, all in a way that makes it possible to use the same model for many different databases.
- Everything, everything, everything in pure Ruby: Virtually everything in a typical Rails application is written in Ruby, which means you always have access to a full-strength programming language, and learning something once means you can use it everywhere.
1.1.2 This productivity ain't free
Now that we've given a sense of what free productivity is, it's important to explain what free productivity is not. Many frameworks come with lots of built-in functionality: a slick administrative interface, fancy role-based authentication and authorization, or the ability to write certain applications with virtually no code. Even Rails has this capability; a feature called scaffolding renders certain kinds of form-database interactions trivial—leading, among other things, to the infamous "15-minute blog engine".
That's not free productivity. Built-in authentication or 15-minute blog engines might make for great marketing, but between us friends we can probably agree that any serious software application is going to take more than fifteen minutes, no matter how brilliant the framework. Don't get us wrong; if, by some chance, the application you have in mind is rendered trivial by some existing framework, by all means use it. But if, as is more likely, you want to build something new, you need a framework that will help you when you need it and will get out of your way when you don't. You need a tool that will help you realize your vision; a tool flexible enough to change as your vision changes; a tool which, in the end, mutates into a new framework, one that feels as if it were custom-made to write your exact application.
This is where Rails excels. Rails is great at making custom applications—Rails helps you make the application you want. You don't switch to Rails because of the cool message board or blog software available. You switch because the process of creating your own custom apps is so much easier using Rails.
1.2 Why this book?
There's a tension in any educational book between the two extremes of pure tutorial and pure reference. We land firmly on the tutorial side of this spectrum, which has many advantages. Because our application is real, you get to learn Rails as it is actually used. You'll see for yourself all the great ways that Rails makes writing web applications easier, from its elegant model-view-controller architecture to the brilliance of embedded Ruby. You also get the advantage of artful repetition: you see the most important ideas the most. The result is learning by osmosis.
In the process of building RailsSpace, we'll also see how Rails makes it easy to write automated tests to make sure our application does what we wanted it to do. Because of our tutorial approach, we will be able to develop the tests incrementally in parallel with the application, just as you do (or should do) in real life. As our application evolves, you'll see how great having a test suite is: whenever we modify a feature or add a new one, we can run the tests to make sure that we haven't broken some other part of the application.
Of course, while good for learning, a tutorial approach is not as good for looking things up. As a counterbalance to RailsSpace, we recommend Agile Web Development with Rails (second edition) by Dave Thomas and David Heinemeier Hansson, the original introduction to Rails. AWDwR contains a wealth of reference material documenting most aspects of the Rails framework. For learning Ruby we recommend Programming Ruby by Dave Thomas and The Ruby Way by Hal Fulton.
1.3 Who should read this book?
Since you're reading this, the chances are good that you should read this book.
RailsSpace is an introductory book, so we don't assume any knowledge of the Ruby programming language or of the Rails framework. Of course, any previous exposure to either will be beneficial. Even if you have some prior experience with Rails, we hope you can learn something from our book, especially since we use several features (such as migrations, form generators, and Ajax support) introduced in the more recent releases of Rails.
To get the most out of RailsSpace, you should probably know at least one programming language, and familiarity with object-oriented programming would be especially helpful. Java is probably sufficient background, and it's even better if you are familiar with a dynamically typed language such as Perl, Python, or PHP (or Ruby!). It would be especially good if you've used one of these languages to make dynamic web sites. Some exposure to JavaScript and Cascading Style Sheets (CSS) would also be good. At the very least, you should be familiar with making static web sites using HTML. Finally, we assume a certain level of computer sophistication, so that when we say "Go download MySQL and install it" you're confident that (given enough time and coffee) you can probably do it, even if you've never installed a database before.
All of these supposed prerequisites are really beside the point, though. By far the most important factor is your enthusiasm for learning how to make web applications. If you're excited about putting something cool on the web, this book is for you, no matter what your background is.
1.3.1 How to read this book
RailsSpace is designed to be read from start to finish, and you'll get the most out of it if you code along with us, but we've designed the book to be instructive and interesting even if you're not sitting in front of the computer. Also, it's important to be patient. If you don't get something right away, keep pressing forward, and give the ideas a little time to sink in. You'll be amazed at how something that confuses you at the beginning of a chapter will seem trivial by the end. You're training your personal neural network how to recognize Ruby on Rails patterns, and there's no substitute for practice and perseverance.
1.2.3 How to watch this book
The accompanying website for this book can be found at
http://RailsSpace.com/book
There you'll find errata, sample data, and downloadable source code for RailsSpace. You'll also find links to screencasts for each chapter—narrated movies of the book's source code coming to life.
1.4 A couple of Rails stories
We've given you a bunch of reasons why Rails rocks, but there's no substitute for a couple of good old-fashioned testimonials. These are our personal roads to Rails.
1.4.1 Aure
Way back in 1994 some friends and I in the Graduate Aeronautical Laboratories at Caltech discovered that we had a department webserver that would serve our own content at /~user_name/ URLs. We started out competing with each other for hits and instead of personal sites we put up content about our favorite musicians and airplanes. One of us was the teaching assistant for the lab and had control of the ~ta account. We re-christened the initials to stand for "The Asylum" and instead of competing, we pooled our resources to build a "crazy" place on the web where anyone could log on and contribute content. Some of the apps we created were a public bookmarks repository (precursor to del.icio.us), a public writing forum (precursor to wikis), and a web based Lite-Brite emulator and gallery (sort of a primitive, single-celled ancestor to Flickr!).
We gained a lot of attention for these sites and soon film studios and record companies were calling the lab tracking us down to hire us to build dynamic websites for them. It was certainly awkward to get phone calls from Universal Pictures while your Ph.D. thesis advisor was in the lab so we started a business and opened an office with a phone number of its very own.
We spent a few years building custom websites in Perl/CGI while getting our degrees (which we all managed to do, take that you Yahoo! millionaire Stanford dropouts!). Slowly the stress of building websites from scratch in Perl wore us out and the company disbanded. I looked back at the websites and realized that many of them were very similar, so I began offering standard web components to my clients. Meanwhile, Philip Greenspun was running Photo.net and getting many requests from people wanting the code the site ran on. Philip assembled his friends to beef up the Photo.net code and together we founded ArsDigita and open-sourced our code as ACS (ArsDigita Community System), comprised of standard web components and written mostly in Tcl. We used ACS to get exposure amongst poor developers, which led us to be found by rich companies who wanted customizations to the toolkit. Unfortunately, venture capitalists also eyed ArsDigita and once we accepted their money they also had influence; you can read about what happened after that on fuckedcompany.com.
Even with ArsDigita gone from the landscape, the toolkit lived on as "OpenACS" at openacs.org. But, as an independent contractor, could I really convince my clients that a toolkit started by a defunct company was definitely a long term solution? Also, I was pretty sick and tired of programming in Tcl, so I turned to the prettiest language I knew—Python. That pretty much meant using Zope, and at first Zope was awesome. Indeed, there are still some applications for which Zope is a great choice. But Zope has many annoyances as well, and my clients yearned for standard version control, file system access, and better relational database access.
One of my (favorite) ex-employees was now working for Caltech and one day sent me an email about some emerging frameworks she was considering instead of Zope for the next project. Django and Ruby on Rails were on her list, and after a few hours of research I knew Zope was history. Initially I leaned towards Django because it was in Python, but Ruby on Rails was a bit further along, and it had one thing that Django will never have—David Heinemeier Hansson, the creator of Rails. From my experience with ArsDigita and Philip Greenspun I knew the importance of having a compelling, intelligent, and opinionated central figure representing the framework. David, back then, and through at least the time of this writing, has prescribed the philosophy of what Rails is and what it is not.
While DHH is its "creator", Rails clearly is the product of the evolution of web application development. Here's what struck me about Rails:
- Ruby, mostly
Web application development always requires some mastery of many fields. You're going to have to know at least a little about templating languages, database access, and procedural programming. But, there's no denying it takes energy to constantly switch back and forth between languages, especially when languages mix within one file. Rails minimizes this—templating language: Ruby, database access: Ruby (mostly), procedural programming: Ruby (duh).
- Data modeling, improved
The old way I started a project was to brainstorm everything that might be needed and write a data model in SQL that would hold the final state of the data. Then I would have to write the code to populate the database tables and write the error detection to prevent bad data from going into the database. With Rails migrations, I can now incrementally augment the data model, and with validations I write rules that almost automatically show up in my web application as error reports. Also, migrations are database agnostic, so I don't have to write a new SQL file for the various available databases.
Oh, and there are many more things I have learned about Rails that I love, but frankly, you don't need a long list of great things about Rails to know it's for you. In fact, if you need a long list, then maybe you're not convinced. It's like when I bought my 2001 Nissan Frontier truck: it could carry my dog, it was fast, and it looks like a spaceship—sold!
With Ruby on Rails I can offer a client a site that is completely customized for their needs while still being fun for me to program in. Everyone is happy!
1.4.2 Michael
When I was at Caltech for graduate school, my friend Sumit Daftuar and I ran a local NCAA basketball tournament pool, which initially involved a small but important web component. Sumit used a simple Perl script to generate the results after each round of the tournament, which got posted to a website. Even though it was ridiculously simple, people loved it. In 2001 I decided to take the next step by using PHP to write a full web interface for our pool, complete with bracket entry and scoring reports. I reasoned that this would force me to learn web development, and, several 20-hour days later, it did.
PHP seemed great at first, but as the size of my projects grew PHP became increasingly cumbersome. After graduating, Sumit and I started a company that ran unique weekly fantasy sports games and produced an improved version of our NCAA site called BracketManager. I didn't want to use PHP for the company sites, so I started looking around for something new. I had learned Perl and Python in the course of my Ph.D. research, and I looked at several frameworks in those languages.
I eventually settled on Zope, which is written in Python, even though it wasn't particularly well-suited for our primary purpose—namely, writing a large custom web application. Like many frameworks, Zope uses a watered-down template language to generate HTML, but many web applications (including ours) generate such complicated HTML that they really need a full-strength language under the hood. We ended up writing most of our HTML in pure Python and coupling it to Zope using "external methods", which got the job done but were rather cumbersome. I also found Zope's documentation to be spotty at best, due in large part to Zope's relatively small user base. Finally, Zope has weak support for relational databases; in particular, the Zope MySQL database adapter provided no support for generating the often comically verbose queries required by SQL, forcing me to write a custom MySQL library in Python.
Despite all these problems with Zope, Python is so much better than PHP that it was worth the trouble. Unfortunately, our fantasy games never reached a critical mass, and the final straw came when the NFL Players Association started (and the MLB Players Association threatened) to sue any fantasy sports companies using the players' names without a license. Unable to get licenses, we decided to shut the company down. This was unfortunate, but it did give me a chance finally to abandon my Zope codebase and take a look at a new framework I had been reading about called Ruby on Rails. I had a mental checklist of things I needed in a web development framework, and I was curious to see if Rails might meet those needs.
During all this time, I had kept in touch with Aure Prochazka, a tall, quiet, scruffy-looking guy I had met while singing in the Caltech Glee Club. He seemed to know quite a bit about web development, so back in my PHP days I talked with him a bit about that language. He'd looked at it a little, he said, and it seemed fine. I talked to him maybe a year later, and he told me that he had taken a good look at PHP and decided that it sucked; he had gone with Python and Zope instead. I replied that I had also switched to Zope. After another year or so, I mentioned that I had become dissatisfied with Zope and was looking at Ruby on Rails. He replied that he had recently switched from Zope to Rails, and loved his new framework.
In an effort to jump-start my Rails education, I took a Pragmatic Studio course offered by Dave Thomas and Mike Clark—spending my own hard-earned cash despite Mike's best efforts to convince me not to take the class. I'm glad that Mike was not more persuasive, because I sat in amazement as one item after another on my mental list got checked off:
- An elegant programming language with flexible data structures and powerful abstractions: check
- Good documentation, with a relatively large (and rapidly growing) user base: check
- Mature relational database support, with a good object-relational mapping library: check
- HTML-embedded templates with, for the love of God, a full-strength programming language: check
After working on a few personal projects in Rails, and doing a Rails demo site for a friend's company to show how it could replace their legacy Perl system, I was convinced that Rails was the framework I had been searching for. When Aure asked me if I might be interested in submitting a proposal to write a book on Rails with him, I leapt at the opportunity.
There's no turning back now. And there's no stopping Ruby on Rails.