After poking around with Ruby on Rails and reading every book and following every tutorial I could get my hands on for over 5 months, I decided to get real and sign up for the Big Nerd Ranch Ruby on Rails course being taught by Charles Brian Quinn, consultant for Highgroove Studios and co-founder of Slingshot Hosting.
I hadn’t previously heard of Big Nerd Ranch, so I was a little worried about the quality of the course, but with the Pragmatic Programmers Rails course being only two days, I felt I needed more time to be completely absorbed in the course material. The Big Nerd Ranch approach to removing you from from all distractions in a quiet, comfortable setting with a very small class size seemed to be just what I needed to focus and regroup.
This is a long article, so you can use these links to jump to a post:
I touched down in Atlanta at one o’clock, and walked the mile or so to the baggage carousel, eschewing the express subway. Grand sculptures and prints lined the first hall I went down, I snapped a few photos, and jumped on a movable sidewalk. The peanuts hadn’t done much for me and I still had two hours of waiting to do, so I stopped at a chinese place and grabbed some food, making sure to chew extra slowly while hundreds of travelers passed by. Eventually I met up with the rest of the group that was to ride back to the ranch with me, and after a short trip we were checked in to a farm-style multi-building bed and breakfast called The Inn at Serenbe. I had a private room with its own bathroom in a 3-room cottage, both of the other rooms were booked for other residents in the course. The room had double doors in it that opened up to the back porch.
I took a walk around the grounds after unpacking, and I found dozens of cozy little spots carved out for both activity and inactivity. I came upon a garden, two pools, a small basketball court, a large trampoline built into the ground, and a few barns. Behind the buildings was a farm with sheep, goats and chickens. Squirrels dart all over the grounds. My favorite place is a treehouse with multiple levels, and a drop floor that leads to a corkscrew slide.
I step into the makeshift classroom where Charles Quinn (the course instructor) and Aaron Hillegass (a fellow instructor for Big Nerd Ranch that primarily teaches the Cocoa course) are setting up a row of iMacs with Ubuntu Linux. You are given your choice of OSX or Linux for a development machine, and this time apparently everyone not bringing their own laptop chose Linux. The classroom is small, with three rows of tables, seating about 15 total. Brian has his MacBook Pro hooked up to a projector that covers half the wall. All the tables are graced with a coursebook, quizbook, and a copy of Agile Web Development with Ruby on Rails.
Dinner is served in the main building, and we all gather around a big table and are served the biggest fried chicken thighs I’d ever seen with mashed potatoes, cheese grits, and collard greens. There is a certain something that happens when you put a bunch of computer geeks together. The conversation ramped up quickly as we were all getting to know each other, and when I left the dining room, I felt the exhaustion of a long day of traveling start to weigh on me. I called my family from a spot on the path between my cottage and the dining room where my phone got up to 3 bars, and looked up to see hundreds of stars. Not just the 10 or so you see on a given night in Indianapolis.
After the previous long day, I came back to my room and knocked out at a very early (for me) 10pm and slept soundly until 7:30 the next morning. Over breakfast someone mentioned getting awakened by a rooster’s caw. Afterwards, we filed into the classroom to begin our first day of instruction. The first order of the day was to have everyone introduce themselves and give a brief explanation of why they want to learn Ruby on Rails. Some came because they were tasked with coming up with something very quickly, some came to solidify and reinforce the existing knowledge they have gained, but just about everybody came because they were tired of how much work they had to put into maintaining the spaghetti code of other languages like PHP, Java, and Perl.
After introductions had been made, the instructor went right into a series of slides explaining the basics of Ruby itself.
How everything is an object, class instantiation and inheritance, dynamic typing, string interpolation and math. The students here are pretty sharp, and there were lots of good questions about the material all along the way.
At noon we headed to the dining room for a light lunch of soup, salad and sandwiches. We headed back to the classroom for about an hour and took a break to go out for an afternoon hike around the farmland. Behind the buildings there were several pens with a variety of livestock. First we fed the goats some grapes, then moved along the path to see some chickens, donkeys, llamas, sheep and horses. After about 40 minutes or so we had made a circuit back to the classroom where we started off getting everybody set up with a working development stack of rails and mysql server.
The class makes a point that you can use whatever you feel most comfortable working with, so there were several people running their rails stack on ubuntu using Aptana or Netbeans, there was someone running rails under cygwin for windows, and of course several macs running OSX Tiger or Leopard (which had only been out for 2 weeks). I tried to resist upgrading before coming, but since Leopard ships with a nearly complete Ruby on Rails stack already, I had to try it out. Despite a few small issues, it is a worthy upgrade, and quite good for Rails development work.
After everybody had a working base to start from we spent some time going over some basic documentation sources for Ruby and Rails including:
RailsBrain – Ajax-ified version of api.rubyonrails.org
Ruby-Doc – online version of the Pickaxe book
Ruby.Search – like api.rubyonrails, but includes resources on ruby, rails, edge rails, and rdoc
Following that we went into ActiveRecord with quite a lot of focus on its Object Relational Mapping and using find. Most of the instruction and exercises relied heavily on using irb and script/console for quick testing.
The end of the day came quickly and we headed to dinner for an excellent southern plate of sauteed quail, beets and succotash. After dinner, the students are free head back to their lodgings or do whatever they wish, but a few of us headed back to the classroom to continue work and discussion, and to use the network connection to check email or do a quick chat home. Around 11:00 everyone had left but me, and I headed out a few minutes later.
At breakfast it came up in conversation that over half the class has either been in the military, or works for a military contractor. Strange stuff. After our meal of peaches and pecans over french toast with bacon, we made the short trek to the classroom to begin our second day of instruction.
We started out by going through ActionView and how it interacts with your controllers. Solidifying the VC portions of MVC application structure. Then we talked about redirects, sessions, cookies and the flash. Setting and getting and stuffing values into these structures for later use to maintain a sense of persistence on a stateless HTTP application.
For lunch it was vegetable soup, salad, and sandwiches. When we came back we talked about migrations, and how they make it very easy to keep track of changes made to the database schema, and allowing you to roll back changes made to the database as easily as rolling back code with subversion.
After about an hour, we headed out for the afternoon hike, and like every other break so far, be it for a meal, a hike, or even a bathroom break, people start chatting with each other about what they have just learned, and going over how it applies to their personal projects and goals.
Our hike down the hill and over a river lead us to a clearing where stones have been arranged into a zig-zagging circular path. It was explained to us that this is a kind of labyrinth. A labyrinth is a winding path that strives to make you do the most amount of walking possible to reach a clearing in the center. While walking along the path, you are supposed to meditate, and it is said when you reach the center you will be enlightened. Then you take the same path back out of the labyrinth. I’m not quite sure how much walking I had to do just to reach the center that was 20 feet from the edge, but I would guess it to be over half of a mile. We all skipped over the rocks on the way out back to the classroom.
When we got back, we started talking about model relationships and associations, covering has_one, belongs_to, has_many, has_and_belongs_to_many, and has_many :through. These model identifiers do a bit to describe how tables are related to each other, enabling you to pull out associated records with find.
I’ve so taken to using “haml”:http://haml.hamptoncatlin.com in all my projects, that I started building the app in our exercises using it instead of standard rhtml, I’m pretty sure it won’t come back to bite me later on, but it might.
Then we talked about rake and common rake tasks, and freeze for packaging a certain version of rails with your application to make sure that a program written on 1.2.5 won’t be broken when the deployment server (or your development machine) updates rails to 2.0 or something similar. We went over the standard directory structure to make it clear that in rails there is a place for everything, and everything has its place.
We ended the day’s lesson with some talk and exercises dealing with dynamic and generated scaffolding to get a quick and dirty CRUD interface for interacting with the model to create, read, update, and delete records
After a dinner of mushrooms over steak and mashed potatos, nearly everyone headed back to the classroom to work on their own projects with the newfound knowledge they gained during the day. The combination of things we learned today brings a very nearly complete view of how to actually get started writing an app with Ruby on Rails.
I got some good pointers from Charles on using Single Table Inheritance to extend a model with another model and use STI based on a type field in the database table for the app I’m building on my own.
I stayed in the classroom until I could barely think anymore, and ended up leaving after midnight. I stayed up until about 1:30am writing this before closing the lid of my macbook and calling it a night.
We started the day by altering the scaffolded code, prettying up the rhtml and adding css styling, and changing one of the forms to set info in a separate model. We then talked about validation methods to make sure we only accept data that meets our criteria of validity to the database. We also talked about creating your own validation methods. The validation exercise that followed was very open-ended, and we saw lots of good ways people in the course chose to validate that a date set in the form cannot be in the future, and that the color of a box must be red, white, or blue.
Some people only validated that the color was precisely one of these, and some came up with methods that downcase’d your input and validated against that. Some used regular expressions that matched input in upper, lower, or mixed-case.
We followed that with a short exercise further reinforcing the has_many and belongs_to relationship of boxes to orders, and we added a dropdown select to the order form to choose which box it would get shipped in. We gather data from the boxes model, and display each box as a choice in the order form, when that form is updated it will store the foreign key value of the associated box in the orders table.
I got an IM from someone at the office during the morning session that my help was needed, so I skipped lunch to work out the issue. It ended up taking long enough to resolve that lunch had ended and I was still working on a solution. Charles started talking about creating helpers to keep your view templates clean and logic-free, but I was only half-listening. Luckily, it soon came time for the afternoon hike. There was a weather advisory, and there was a dark clouldline approaching, so the class wanted to get out fast and hurry back. I skipped this too, and it gave me just the time I needed to finish off the office issue and get my head back in the game.
My wife IM’d me telling me that my personal website, unixmonkey.net has been down since at least yesterday. I was a little upset because I had been journaling this trip for the benefit of my local ruby users group Indiana Ruby Users Group (irug), and planned on posting it online after the trip.
Once the group came back, we has a lengthy discussion over some short slides on some of the more advanced rails topics that were outside the scope of the course, but were good to know about, like model aggregations, acts_as methods and plugins, transactions, locks, observer methods, polymorphic associations and single table inheritance.
We started the day with a quick review on helper methods as a way to keep display logic stuff out of the templates to keep them from becoming spaghetti code of case statements. I’m reminded of why I like haml so much, because when I look at my templates and views, I only see the document structure and ruby code without all those ugly <%= %> erb and html tags cluttering the view.
Then we dove into testing. Testing is important for any application bigger than a few pages, and especially for an app that has so much magic going on in the background. The point is to keep the tests small and simple and ideally to do them up front (test-driven development), so that when something breaks or doesn’t behave as expected, you aren’t forced to debug a ton of code. Rails is in a transition phase, where lots of small conventions are changing in anticipation of the 2.0 release that caused a bit of trouble getting out tests going “out of the box”, where generated test fixtures don’t match up with the @first_id in the controller_test files, they were fixed easily enough, and then we had to pass some required fields to get the test models to pass the validations we added yesterday. There was a lot of interest from the class in testing that I don’t think was anticipated, and we were forced to cut it short a bit so we could get so some other topics.
I picked up some neat tips on using some keyboard shortcuts to run a single test file in Textmate by just saving the current file and hitting apple-r, or even a single test with apple-shift-r. There was a lot of interest in using the ZenTest gem to have autotest running continuously in the background, debugging your code each time you save a file in the project and optionally popping up growl notifications when something passes or fails.
We moved on to how rails handles and creates routes to determine how and where to dispatch calls from a browser request. The default route mechanism maps to domain.com/:controller/:action/:id, and how we can define our own custom routes for prettier and more search-engine friendly URLs.
We quickly covered scoping your controllers, and protecting private methods that should not be available to be called by a user by defining them below a line marking the stuff below it as private or protected. Then we talked about before, after, and around filters to do some setup to help you with protecting a controller by running an authentication module, or keeping you from repeating yourself too much by setting up controller-global variables or performing some logging.
We were then tasked with password protecting the new, edit, and delete actions, so unauthorized users can’t just start adding and deleting new orders. Charles took us halfway there, and left us to implement it on our own. It took a bit more fiddling with it than I would like, considering I’ve written one of these before in Perl, and installed acts-as-authenticated previously, but I was quite pleased with myself when it all snapped into place and started working.
Dinner was our choice of scallops or steak. I had the scallops.
After dinner, roughly half of us came back to the classroom to work on our personal projects and chat, and Charles’ wife brought us some coronas to facilitate the creative process.
We all knew the moment would come. It was the last day of the course, and a half day at that. We weren’t going to have time for a class project, and we had a lot of pretty meaty topics we had to blow through before lunch. We started out talking about logging custom events and sanitizing the logs so passwords and such don’t get logged. We talked briefly about printing out debug statements and inserting breakpoints into the code so you can inspect the immediate environment of your app through the console. We then moved to ActionMailer to use rails as a mailer and receiver of email, handy for sending out update notices and password reset forms. We had an exercise on setting up a mail controller and triggering a mail whenever a new widget was added to our application.
Moving on, we talked about outputting valid XML, SOAP, and other web service API’s for accessing our data from something other than a web browser or outside our app, that included a good long talk about REST and the reasons for it being so important to rails developers, though most of the concepts are tough to grasp for beginner rails developers like us. We added an XML RSS feed to our widget app, and quickly touched on optimizing slow SQL calls with eager loading, and speeding up things dramatically with static page caching.
Lastly, we talked about deployment, and how Charles’ preferred method for deployment is Apache+mongrel. We talked about Capistrano and the way it maintains symlinks to the current svn pulldown for versioning and easy rollback. An excellent article on deploying with apache and mongrel is Coda Hale’s Time for a Grown Up Server.
Aaron Hillegass showed up to give us all BigNerdRanch T-Shirts and coffee mugs, and Charles passed out training completion certificates. We headed to the farmhouse for a last meal of soup and sandwiches, then got on the shuttle back to the airport. I had about 5 hours to kill, so I walked up and down half the concourses just taking it all in until boarding my plane back to Indianapolis.
On the flight home, I kept thinking about Rails. All weekend, I kept thinking about Rails. Ideas about how to do this or that in my personal app kept tumbling around in my brain. Rails is awesome, and I still get excited about how much I can do with a few one or two-liners, and a lot of convention, and still retain readability in my code. I’ve gone through the Agile Web Development book twice (1st and 2nd editions), and people think I’m pulling their legs when I tell them I didn’t really learn anything new. I chalk this up as a win for Rails, because it is meant to be short and easy to understand, and well documented in the Agile book. However, I still find the course to be a very valuable asset in my road to rubydom. The focused environment and discussion followed immediately with practical exercise helped pound the rails way of thinking into my head. I gained a much greater and more complete understanding of using rails overall.
One of my classmates said early on that his knowledge of Rails at that point was like a block of swiss cheese. Overall solid, but with gaps missing in a few spots. I felt more like my knowledge of Rails was like a jigsaw puzzle that was all put together, but some of the pieces had been hammered down in the wrong spots to make it fit, and the picture didn’t look quite right. At the end of the course, that puzzle looked less like a Picasso, and more like a DaVinci.
Many thanks to Charles Quinn and the Big Nerd Ranch for giving me the background and confidence to move forward.
Pictures I took during the week can be found here:
Photos taken by my new friend from the course Will Calder can be found here: