I’ve been enjoying you guys’ feedback on my Rails 3 posts. I’ve gotten feedback both good and bad, and it’s been really helpful in the big project I’ve been working on, which I’m really glad to finally be able to talk about it a little bit. Most of the content I’ve posted about Rails 3 has been excerpted from my new eBook: The Rails 3 Upgrade Handbook.

It’s a hair over 100 pages of information on upgrading and improving your Rails 2.x applications with Rails 3. It covers how to upgrade, what new features can improve your existing code, a few case studies of upgrades, and extremely detailed checklists for upgrading and fixing your code.

The release of this project is imminent, so if you’re interested head over to http://railsupgradehandbook.com and sign up to be notified of when it’s released. It will be priced at $12 and kept updated as things shift and change on the path to Rails 3 Final.

Next week’s posts will be more consistent. I plan on discussing upgrading to Rails 3, one of my favorite new features in Rails 3, and my toolchain for writing eBooks (it’ll make hackers happy I think).

Quite sorry about not getting another post up sooner; I’ve been very busy lately with a few different things (some of which shall be revealed very soon!). Today I want to talk about validations. Validations received quite a bit of love in Rails 3, but if you don’t go looking for the new shiny features, you won’t find them. The old API is still around, so nothing will break if you try them, but there is also a variation on that theme:

This new form is excellent since you can compress what would have previously been 4 lines of code into 1, making it dead simple to see all the validations related to a single attribute all in one place. The valid keys/value types for this form are:

:presence => true

:uniqueness => true

:numericality => true

:length => { :minimum => 0, maximum => 2000 }

:format => { :with => /.*/ }

:inclusion => { :in => [1,2,3] }

:exclusion => { :in => [1,2,3] }

:acceptance => true

:confirmation => true

As I mentioned previously, you can still use the old API, but it makes sense to switch to this form since, when scanning your code, you’re rarely looking for what sort of validation it is rather than the attribute that’s being validated.

Another great new validation feature is the ability to have a custom validation class. It’s fairly common for Rails developers to develop their own validation methods that look something like this:

These methods are really useful, especially if you use this validation in a lot of different classes, but they often add a bit of ugly code. Fortunately, in Rails a lot of that nastiness can go away. Those old methods should still work, but you could make them look like this instead:

Basically, create a class that inherits from ActiveModel::EachValidator and implements a validate_each method; inheriting from this class will make it available to all Active Record classes. Not only is the code a bit cleaner, since you can spread it out a bit more if it’s hairy without polluting the model class, it also makes these validations easily testable without much hassle, and you can also integrate them into the short form validations like this:

validate :category_id, :proper_category => true

Note that the key name is taken from the class name (i.e., ProperCategoryValidator becomes :proper_category). A similar new feature is the ability to have validator classes that bundle validations into a single object. If you have a lot of classes that need some very complex validation logic, you can create a class like this:

This pattern is nice for wrapping up a lot of unruly validation code, but a more interesting variation on it will be building class factories (o noez not a factory!) based on parameters that build these validation classes (i.e., a class that generates validation classes). You can find a little more information these and other Active Model validation features in its API documentation at http://api.rails.info/classes/ActiveModel/Validator.html .

Upgrading applications is good sport and all, but everyone knows that greenfielding is where the real fun is. At least, I love greenfielding stuff a lot more than dealing with old ghetto cruft that has 1,900 test failures (and 300 errors), 20,000 line controllers, and code that I’m pretty sure is actually a demon-brand of PHP.

Building a totally new app in Rails 3 is relatively simple (especially if you’ve done it in previous Rails versions), but there a few changes that can trip you up. In the interest of not missing a step someone may need, this post is a simple walkthrough of building a new app with Rails 3. I would have simply posted about the Rails 3 version of the Getting Started guide, but it’s actually a bit out of date now. I’ve committed each step in its own commit on Github so you can step through it (the repository is here: http://github.com/jm/rails3_blog)

Once all those lovely gems are installed (add --no-ri and --no-rdoc if you want to skip those/speed up your install), then install the prerelease version of Rails:

gem install rails --pre

Now you’re ready to roll on with the Rails beta!

Using the new generator

The application generator is basically the same with two key differences:

The parameter that was formerly the app name is now the app path. You can still give it a “name,” and it will create the folder like normal. But you can also give it a full path (e.g., ~code/my_application rather than just my_application) and it will create the application there.

All parameters for the generator must go after the app path. So, previously one could do rails -d mysql test_app, but now that has to be rails test_app -d mysql. This change is largely due to the major refactoring of the Rails generators, so even though it’s somewhat of a temporary annoyance, it’s definitely worth it for the flexibility and power that the new generators bring (more on that soon).

If you get an error like “no value provided for required arguments ‘app_path’”, then you’ve gotten your parameters out of order. If you’d like to use another database driver, you can provide postgresql or sqlite (or nothing, since sqlite is the default). You’ll see a lot of text scroll by, and now we have a nice, fresh Rails 3 application to play with [4b6b763ac9378c6cde95b0815d2a4c2619a0e403].

Let’s crank up the server (note that it’s different now!)…

rails server

Rails went the “Merb way” and has consolidated its many script/* commands into the rails binscript. So things like generate, server, plugin, etc. are now rails generate and so on. Once the server’s booted, navigate over to http://localhost:3000 and you should see a familiar friend:

Click on “About your application’s environment” to see more information about the app you’ve generated.

Configuring an app

Now comes the task of configuration. Again, not a whole ton of changes from previous versions, but navigating them can trip up the novice and journey(wo)man alike. First, setup all your database settings in database.yml; it’s just like previous versions of Rails, so no surprises there (and plenty of information abounds if you’re new to it).

Next, pop open config/application.rb. This is where much of the configuration information that once lived in config/environment.rb now lives. The portion you probably want to pay attention to most when making a new application is the block that defines your options for ORM, template engine, etc. Here’s the default:

I’m going to stick with the defaults, but you could substitute in something like :datamapper or :sequel for :active_record, :haml for :erb, or :rspec for :test_unit (once they get it working with Rails 3). Doing so will set the generators for models, views, etc. to use your tool of choice (remember that whole technology agnosticism thing?); I don’t know if all these generators are available yet, but there are some available here.

The config/application.rb file also houses some configuration for other things.

If you need to configure internationalization, it’s been moved to application.rb. Rails 3 comes equipped with a really powerful i18n toolkit; if you haven’t seen it, you can learn a little more about it here. The defaults that Rails sets up will work for most people (default locale is en and all translations in the default directory are automatically imported), so you may not need to touch anything, but if you need to customize, this is the place to do it.

You may want to set a default timezone. I usually stick with UTC since it’s easy to convert on a per-user basis to their desired timezone, but you might want to set it your timezone or the server’s timezone.

Your favorite old haunts from config/environment.rb such as config.plugins, config.load_paths, etc. are still there (even though config.gems is not).

Other configuration bits like custom inflections, mime types, and so on have been moved out into their own initializers that you can find under config/initializers. [b613cef6f92ff7d3304da84dba530196ba51371d]

The last big piece of configuration you’ll need to add is a Gemfile for bundler (get more information on Gemfiles and bundler here and here). We already have a basic Gemfile that has the following:

Notice that it has added mysql as a dependency since that’s what we set as the database (or whatever driver you selected, for example, pg or sqlite). Since I want to write blog entries in Markdown, I’m going to add rdiscount as a dependency. To do so, I simply have to add this:

gem "rdiscount"

As I’ve said before, bundler is much more powerful than config.gem, and one of the great features it adds is the concept of a gem “group.” For example, let’s say I want to use mocha, but only when testing (obviously). You would add this to your Gemfile:

Next, run bundle pack if you want to vendor everything or bundle install to install the gems to system gems. After you’ve combed through this stuff and set whatever you need, you’re done configuring your application. Now on to actually building something.

Building it out

So, we’re going to build a very simple blog (and expand it later). First, let’s generate a scaffold for posts, since that’ll generate a lot of boilerplate code that we’ll go back and tweak:

Next, run rake db:migrate to create the database table for Post. Now if you go to http://localhost:3000/posts, you should see the standard scaffold interface. [8f27fe53282de70343afadaedd583ecc279d535d]

Let’s a take a look at the controller code; you’ll see a lot of actions that look sort of like this:

That’s some clean code, but in Rails 3, we can compress down even further with the Responder. This class wraps very common rendering logic up into some really clean helpers. To use it, you’ll need to add what formats your actions respond with to the class:

Now the action will automatically look at the state of the object, the format requested, and respond accordingly. So, for example, if you successfully create an object in create, it will redirect to show; if it fails, it will render new (this is assuming, of course, you’re requesting HTML). Of course, if you need custom logic, you’ll want to do something else, but these helpers make already clean, RESTful code even easier and cleaner. Make sure to rake to make sure you refactored it right! [53846f92393e10146fbf2d9b43b530a244d0137e]

Next, open up config/routes.rb. It should look something like this (with oodles of extra commented out routes):

Rails3Blog::Application.routes.draw do |map|
resources :posts
end

To set PostController’s index action to the root, we need to do two things. First, remove public/index.html otherwise it’ll always overtake any root route you set. Next, add a root route to config/routes.rb like this:

Now going to http://localhost:3000 should show the posts index page. [120c377c8ec1c138d600f9b9bc39bedf1d43afd4] OK, so now that most of the functionality is in place, let’s make it look presentable; here’s my version of the index template:

As you probably noticed, the API for Active Record validations I’ve used here is different (the validations shown are equivalent to a validates_presence_of validation, which are still around) [178bb06839bb44978f42c922c9348bfe783da8b1]. You can read a little more about the new style of validations here. So, now if you try to create a post without a title or body, it’ll reject it.

More later…

I realize this introduction is extremely simple, but I’ll expand on it very soon (including authentication, commenting, post drafts, an API, spam protection, feeds, caching, etc. with a separate entry after it on deployment). I’ll get to that sort of stuff very soon, but my next post is going to be a walkthrough of upgrading an app step by step (very similar to this entry). Look for it in a few days!

I apologize for not getting another Rails 3 upgrade post up this weekend, but I spent this weekend working on a few things. First, I contributed a few little pieces to the Rails 3 release notes, which should be showing up on the Rails blog soon (edit: or view them here right now), but most of my time was devoted to a bigger project.

Simply run those tasks in the same way you ran the commands with the rails-upgrade gem. In the near future, I plan on expanding the checks for deprecated pieces to handle some of the less obvious changes, adding some generators for other changes (like config/application.rb), and adding some extra tools (ideas/suggestions certainly welcome).

Anyhow, I’m really looking forward to seeing this project become a dependable upgrade tool. If you have any ideas or find any bugs, please contact me via e-mail or Twitter or, even better, fork it and handle it yourself!

If you’re looking for more info on upgrading, don’t miss out on my other posts on Rails 3 starting here.

NOTE: This is now an official, blessed plugin, so use that rather than this gem. More info here.

I’ve been playing with upgrading some apps to Rails 3 (some open-source, some not), and I’ve sort of gotten some of the process down to a science. So what does a developer do when something is down to a process? Automate!

I’ve created a (pretty hacky) gem named rails-upgrade (installable by a simple gem install rails-upgrade) to automate some of the more annoying parts of the upgrade from Rails 2.x to Rails 3. So far, it has three parts…

Find out what parts need to be upgraded

I’ve assembled a battery of checks to run on your app for obvious things that need to be upgraded. To get a report, simply run this in a Rails root:

It shows and explains the issue, where to get more information on it, and which files the issue was found in. It checks a lot more than that report shows (e.g., looks for old generators, busted plugins, environment.rb conversion requirements, old style routes, etc.). It doesn’t cover everything 100% probably, but I’ve found it’s great for quickly identifying some low hanging fruit in upgrading.

Upgrading routes

The gem will also upgrade your routes as best it can. To generate a new routes file, simply run this inside of a Rails application:

rails-upgrade routes

I’ve tested it on some quite complicated routes files and it did fine, but it does have some minor quirks (i.e., it flattens with_options blocks currently…that might change if I feel like putting the effort into it…or if one of you patches it :). It takes a routes file like:

The formatting isn’t quite this nice when it comes straight out of the script (I’m working on that), but you get the idea. I’m still tweaking/adding things to this script, but as far as I know it supports every feature of the Rails 2.x router. Fixing the formatting bugs are my first priority, simply because they’re really annoying.

Creating Gemfiles

The last piece is a Gemfile generator; it takes your config.gem directives and generates a nice Gemfile (even including the required Rails stuff). To run it, simply execute:

Then it’s just as simple as gem bundle. Again, I’ve tested this on some fairly complex sets of gem requirements, so it should stand up to most sets.

If you find a bug or want to expand the checks and upgrade scripts or, like, add some tests (please do!), then hit it up on Github, fork it, and send me a message. If you want to simply install the gem and run it, then just run gem install rails-upgrade then rails-upgrade <whatever> inside the Rails application directory.

NOTE: This is now an official, blessed plugin, so use that rather than this gem. More info here.

If you’re looking for more info on upgrading, don’t miss out on my other posts on Rails 3 starting here.

Now that we’ve looked at some of the core architecture, I’d like to shift my focus first to upgrading an application. Originally I had planned on writing about upgrading plugins first, but apparently that API isn’t quite stable. So, I figured rather than write a blog post that will be deprecated in 2 weeks, I’d rather write one that will be deprecated in 3-6 months instead. So, this post will focus on getting your app bootable, and it will be followed by a succession of articles that contain tips and scripts to help you upgrade the various components (i.e., routes, models, etc. are topics I’m working on right now).

The first step towards an upgraded app you need to take is to actually get Rails 3. As noted in the previous post, you can follow Yehuda’s directions or use Bryan Goines’s great little script. Once you’ve got it up and running, I suggest you “generate a new app” on top of your current one (i.e., run the generator and point the app path to your current Rails 2.x app’s path). Running the generator again will actually update the files you need to update, generate the new ones, and so on.

ruby /path/to/rails/railties/bin/rails ~/code/my_rails2_app/

Note that the argument is a path, not a name as in previous Rails versions. If you got an error about your Ruby version, upgrade it! If you use rvm it’ll be totally painless. Now, be careful which files you let Rails replace since a lot of them can be edited much more simply (I’ll show you how here) than they can be reconstructed (unless you really like digging around in git diff and previous revisions), but do take note of what they are since you will likely need to change something in them. As a general list, it’s probably safe to let it update these files:

Rakefile

README

config/boot.rb

public/404.html (unless you’ve customized it)

public/500.html (unless you’ve customized it)

public/javascripts/* (if you don’t have a lot of version dependent custom JavaScript)

script/* (they probably wouldn’t work with the new Rails 3 stuff in their old form anyhow)

And, you probably don’t want to let it update these files since you’ve likely made modifications:

.gitignore (unless you don’t really care; the new standard one is pretty good)

app/helpers/application_helper.rb

config/routes.rb

config/environment.rb

config/environments/* (unless you haven’t touched these as many people don’t)

config/database.yml

doc/README_FOR_APP (you do write this, don’t you?)

test/test_helper.rb

Of course, these lists won’t apply in every situation, but in general I think that’s how it’ll break down. Now, on to the things you’ll need to change…

config.gem is dead, long live bundler

Everyone and their brother complained about Rails’ handling of vendored/bundled gems since config.gem was added sometime ago (just search for “config.gem sucks” or “config.gem issues OR problems” and you’ll see). Between issues with requiring the gems properly to problems with the gem detection (I can’t tell you how many times I nixed a gem from the list because it kept telling me to install it even though it was already installed), Rails seriously needed a replacement for such a vital piece of infrastructure. These days we have Yehuda Katz’s excellent bundler, which will be the standard way to do things in Rails 3.

Essentially, bundler works off of Gemfiles (kind of like Rakefiles in concept) that contain a description of what gems to get and how to get them. Moving your gem requirements to a Gemfile isn’t as simple as copying them over, but it’s not terribly difficult:

As you can see, it’s not too hard. It’s basically just removing the config object and moving some keys around. Here’s a specific list of changes:

Remove the config object

:lib key becomes the :require_as key

The :version key becomes a second, optional string argument

Move :source arguments to a source call to add it to the sources

Once you create a Gemfile, you simply have to run bundle pack and you’re done!

The bundler is much more powerful than config.gem, and it helps you do more advanced tasks (e.g., bundle directly from a Git repository, specify granular paths, etc.). So, once you move your config.gem calls over, you may want to look into the new features; they may be something you had wished config.gem had but didn’t!

Note: I’ve noticed some activity in Yehuda/Carl’s Githubs to do with a bundler replacement called gemfile; I’ll watch that closely to make sure there are no major breaking changes in the API/operation. If there are, I’ll definitely post here!

Move to Rails::Application

In all previous Rails version, most configuration and initialization happened in config/environment.rb, but in Rails 3, most of this logic is moved to config/application.rb and a host of special initializers in config/initializers. The config/environment.rb file basically looks like this now:

Simple: the application.rb file is required and then the Application is initialized. The YourApp constant is generated based on the folder name for your app (i.e., rails ~/code/my_super_app would make it MySuperApp), so name it wisely! It doesn’t have any special relationship to the folder the app lives in so you can rename it at will (so long as you do it everywhere it’s used), but you’ll be using this constant in a few places so make it something useful.

Now you need an application.rb; if you generated the files using the Rails 3 generator, you should have one that looks something like this:

For the most part, your config.* calls should transfer straight over: just copy and paste them inside the class body. There are a few new ones that I’ll be covering later on in this series that you might want to take advantage of. If you run into a config.* method that doesn’t work (other than config.gem which obviously won’t work), then please post in the comments, and I’ll add it into a list here.

You’ll also notice that many things that were once in environment.rb have been moved out into new initializers (such as custom inflections). You’ll probably want to/have to move these things out of application.rb and into the proper initializer. If you opted to keep any custom initializers or specialized environment file during the generation process, you’ll probably need to go in there and update the syntax. Many of these (especially the environment files) now requires a new block syntax:

All configuration happens inside the Application object for your Rails app, so these, too, need to be executed inside of it. As I said previously, most things in there should still work fine once wrapped in the block, but if they don’t please comment so I can post about it/figure out the issue.

Ch-ch-chaaange in the router

You’ve probably heard a lot of talk about Rails and routes and newimplementations and this and that. Let me tell you: the new router is pretty awesome. The problem is that it’s not exactly easy to migrate existing routes over to the new hotness. Fortunately (for now, at least) they have a legacy route mapper so your routes won’t break any time soon. Of course, you should always try to update things like to this to keep up with the version you’re running (i.e., never depend on the benevolence of the maintainers to keep your ghetto legacy code going while using a new version for everything else).

But don’t worry. Upgrading your routes is fairly simple so long as you haven’t done anything complex; it’s just not as easy as copying and pasting. Here are a few quick run-throughs (a detailed guide is coming later)…

I’ll be writing another entry later on about the router’s new DSL and looking at some common patterns from Rails 2 apps and how they can work in Rails 3. Some of the new methods add some very interesting possibilities.

Some minor changes

There are a few minor changes that shouldn’t really mess with too much (except perhaps the first one here…).

Constants are out, module methods are in Ah, nostalgia. Remember when RAILS_ROOT and friends were cool? Well, now they’re lame and are going away in a flare of fire and despair. The new sexy way to do it: Rails.root and its module method pals. So, remember. Old and busted: RAILS_ROOT and its depraved, constant brethren. New hotness: Rails.root and its ilk.

Rack is Serious Business™ You might have noticed that the Rails 3 generator gives you a config.ru in your application root. Rails 3 is going gung ho on Rack, everyone’s favorite web server interface, and as such, a config.ru is now required in your application to tell Rack how to mount it. Like I said, the Rails 3 generator will spit one out for you, but if you’re doing a manual upgrade for some reason, then you’ll need to add one yourself.

# This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__)
run YourApp::Application.instance

Neat, eh? That’s why I suggested you pick a meaningful name for that class: its touch runs quite deep in the stack.

.gitignore to the rescue Rails also now automatically generates a .gitignore file for you (you can tell it not to by providing the --skit-git option to the generator). It’s fairly simple, but covers the 95% case for most Rails developers, and it’s certainly a welcome addition to the toolbox. It was always annoying having to create one every time and either dig up a previous one to copy or try to remember the syntax of how to make it ignore the same stuff.

After upgrading this stuff, you probably have a booting application. Of course, these are a lot of moving parts that could derail this plan: old and busted plugins, gem stupidity, weirdness in your config files, lib code that’s problematic, application code that needs upgrading (I can almost guarantee that), and so on. In any event, these are a few steps in the right direction; subsequent posts will show you the rest.

Posts in this series

I’m posting a whole series on Rails 3; be sure to catch these other posts!

Wow, over half a year with no blog post. That may be a new record for blog laziness for me, but fear not! This bout of sloth shall not last, and the dearth of blog entries shall come to and end! This cure should come partially because I’ve switched to Tumblr and can now compose my entries in Markdown, and partially because that’s part of my whole Get a Better Life New Year’s Resolution Package 2.0™ (coming to a burned out programmer near you in 2011!). Let’s hope this pans out, or, at least, I don’t end up strung out in the gutter tapping out entries into Textmate. Anyhow, to catch you up, here’s what’s happened since my last post:

The Ruby Hoedown 2009 was a smashing success. The whole free conference thing went off without a hitch, and I think everyone had a great time (at least I did).

I’ve left entp and now work at Intridea, which has been fabulous thus far. I get to dabble in a few different technologies, and our office (which I don’t work out of but wish I did) is about 2 blocks north of the White House. Epic win.

But that’s not what this post is about. This post is kicking off a series that I’m doing about moving your skills and migrating your code to Rails 3. I’ll be sharing some practical insights and covering some pretty in-depth topics as we go along (I’ve got some notes for entries about upgrading plugins, taking advantage of new features like the agnosticism, migrating applications, and so on), but before I go into a lot of specifics, I thought it might be useful to go over some of the high-level philosophical and architectural changes that have gone on in the Rails code between versions 2 and 3.

The Big Picture

When the Merb/Rails merge was announced, I was worried that we were going to end up in some weird tangle of Merbilicity and Railsishness when the final product came around. I don’t think anyone wants some Brangelina of the web framework world all up in their business. Fortunately, the gents on the Rails core team are smart and classy and have navigated the waters of cooperation and compromise extremely well. We’re getting the best of both world here, folks: the ease of use and packaging of Rails with the juicy technical bits of Merb. Who can argue with that?

But to make that Epic Code Merge of Awesome™ happen, of course there had to be some changes. These big picture changes have concentrated on a few key areas:

In order to hit these objectives, DHH, Yehuda, Josh, and the rest of the Rails team have extracted things into some new components, expanded others, and removed others to allow for agnosticism.

The general movement seems to be from a monolithic, one-stop shop approach to a looser ecosystem of code that works together with a straightforward set of sensible defaults. You’re no longer “locked in” to ActiveRecord or made to use code injection and hacks and such to get your testing framework integrated. Instead, there are hooks all over the place to cover this sort of stuff (which I will cover later on in the series!) that let generators generate things for the various options or helpers include different modules. It’s a great way to support an ecosystem with an established API.

Lifecycle changes

One of the biggest movements in the codebase has been a shift towards using simple, composed components and a lot of Rack in the request chain rather than specialized, one-off classes. This has affected a lot of things, but one of the major changes has been the addition of Action Dispatch.

Action Dispatch is a “new” component in Action Pack (extracted and expanded from the previous logic) that handles a number of things related to requests and responses:

Request handling and parameter parsing

Sessions, Rails’ flash, and cookie storage

File uploads

Routing, URL matching, and rescuing errors

HTTP conditional GETs

Client response and HTTP status code

Breaking this functionality out into its own component and decoupling much of it creates a much more flexible call stack for requests, meaning you can jack into the process easier with your own logic or improve the existing functionality. I’m sure we’ll see a lot of plugins taking advantage of this to create interesting middleware hacks, improve callbacks and lifecycle methods, hack in their own middlewares to handle specialized logic, or even plug in improved or application-specific routers. This is one of the more interesting pieces I’m interested in seeing develop, since it opens a lot of possibilities that were previously much more difficult to reach.

Making controllers flexible

As a result of the changes in the request chain, the controller stack has also seen a significant overhaul. Previously, every controller inherited from ActionController::Base (either directly or by inheriting from ApplicationController) and slimming down the call stack was accomplished by either (a) previous to Rails 2.3, building a smaller app with Sinatra or Rack to sit next to your main Rails application or (b) post-Rails 2.3, using Rack Metal/middlewares.

In Rails 3.0, this concept of middleware plays an even more central role to how the controller hierarchy is arranged.

The bottom of the stack is AbstractController, a very low level “controller.” Rails uses this class to abstract away essentials like rendering, layouts, managing template paths, and so on, while leaving more concrete implementation details to its subclasses. AbstractController exists only to provide these facilities to subclasses. That is, you should not use this class directly; if you want something super-slim, create a subclass and implement render and a few other pieces).

Each subsequent jump up the hierarchy is actually a class that inherits from the previous, each including modules to compose its behavior. So, if you want to create something slim without implementing a lot of plumbing, use the next rung on the compositional ladder: ActionController::Metal. Metal essentially exposes super simple Rack endpoints that you can then include extra modules into to add more ActionController functionality (check out an example here). These little classes are excellent for replacing those Rack/Sinatra apps for file uploads or what have you while still having the power to easily build out to rather rich controller objects.

Finally, if you need the full monty (i.e., like a controller in Rails 2), then you’ll need to inherit from ActionController::Base. This class inherits from ActionController::Metal and includes a slew of modules to handle things like redirecting the user, handling implicit rendering, and a number of helpers for other stuff like caching.

The advantage of taking this approach is that you can take one of the base classes like Metal and include your own modules to create specialized controllers. I foresee someone using this to create a simple way to serve up resources (e.g., PostsController < ResourcesController(:posts) or something like that) much like people have done previously (José Valim’s inherited_resources jumps to mind) or using it as a way to quickly build API backends. This is the other piece of the major refactor that excites me, since we’re looking at a new way to construct reusable code and assemble it into usable applications.

Where models are concerned

Though the public API for models is generally the same (with a few additions and changes that I’ll cover in a subsequent post), Active Record is now powered by the brain-melting Active Relation, a powerful relational algebra layer.

What does that mean for you? Well, basically it means that Active Record will be smarter and more powerful. Rather than fairly naïve SQL generation, it uses some fancy mathemagical approach that should generate smarter queries. Frankly, I haven’t had a lot of time to research these features for myself, but when I do, I’ll be sure to post (or if you’ve posted about this stuff somewhere, then by all means let me know).

The second big change in Model Land is the extraction of much of the rich logic in Active Record objects like callbacks, validations, serialization, and so on into the Active Model module.

To get this functionality, simply include ActiveModel::Validations and start implementing the methods. It’s possible to exercise fine-grained control over how the validations operate, how the validator gets the object’s attributes, and so on. To get the other functionality like observing or callbacks, just include the relevant module (e.g., ActiveModel::Observing) and implement the required methods. It’s fantastically clever.

Other pieces

ActionMailer is also getting some love in Rails 3. A new API pointed out by DHH in this gist is looking especially delicious; it’s much more like a controller with some excellent helpers mixed in just for mailing.

Rails is also getting a rather robust instrumentation framework. In essence, an instrumentation framework lets you subscribe to events inside of a system and respond to them in meaningful ways (e.g., an action renders and the logger logs its result). Internally the framework is used for things like logging and debugging, but you could easily repurpose the code for other things. For example, let’s say you want to log to the system logger when a particular e-mail is sent out:

Of course, this is arbitrary, but it adds a really powerful way to respond to certain events in your application. For example, someone could probably rewrite exception_notification to use the instrumentation framework to handle and send error e-mails.

Getting started

So, how does one get a piece of this sweet, sweet Rails 3 action? You can install the old pre-release gems, but they’re pretty out of date. To get rolling on edge, I’ve found two ways that work well. First, you can use Yehuda’s directions; these worked great for me and they’re not a lot of hassle (and how awesome is the bundler?). If that seems a bit much or you want to automate it, Bryan Goines has made a pretty awesome script to handle installing and bundling all you need to make it work.

So, go ahead, install Rails 3, get setup, and I’ll meet you on the other side. I’ll be dropping another post this week about how to get started upgrading an existing application/plugin to Rails 3.

Posts in this series

I’m posting a whole series on Rails 3; be sure to catch these other posts!