Hi, I'm Jeremy McAnally. I work at Intridea and tweet at @jm and get my open source on at http://github.com/jm and write run-on sentences.

In celebration of the release of Rails 3 stable, I’m running a sale on my upgrade handbook. Be sure to get it soon because the sale ends today.
Click here to get you some sweet, sweet discounted eBook action!
Maybe one of these I’ll actually, seriously regularly blog. I had a few entries almost finished for Rails 3, but they now require some revision, so I’ll try to polish those up soon. I also have a few in the hopper related to tech writing, which should prove fun and interesting for all parties involved (OK, they’ll at least be informative!).
But my lack of blogging isn’t the reason that I am, in fact, blogging today. No, my friends, today I am announcing that Ruby Hoedown MMX (that’s 2010 for those of you who don’t follow Roman Numerals™ very closely or may still be running on a Pentium II) is open for registration and talk submission.

We’re holding the conference in Nashville at the Downtown Hilton on September 3-4, 2010, and the price will be a wallet-shredding, budget-busting, GDP-increasing, third-world-country-enriching $0 (that’s right, FREE). We had so much fun last year going free, we decided to go ahead and do it again this year. But we’re not just throwing old hat around this year; you’ll have to keep your eyes and ears tuned for some new things we’re adding and some old things that are coming back!
So why not mosy on over to the conference website and register up or submit a talk? The CFP closes on July 2, 2010, and talk selections will (probably) be made that weekend! And if you register now (and get one of the next few slots), you’ll be able to have your say about the talks that we select (more on that soon).
The eBook I previously mentioned is now available! It’s only $12 at http://railsupgradehandbook.com.
Inside you’ll find…
Some people asked for the links and slides to be placed on my blog from my presentation upgrading to Rails 3, so here they are.
They’re also posting the slides and eventually audio over on the conference website; if you missed it, they’ve also posted some information on RailsConf 2010, including a little something about the tutorial I’ll be giving on advanced Rails 3 features!
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:
validates :login, :presence => true, :length => {:minimum => 4},
:uniqueness => true, :format => { :with => /[A-Za-z0-9]+/ }
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 => trueAs 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:
def validates_has_proper_category
validates_each :category_id do |record, attr, value|
unless record.user.category_ids.include?(value)
record.errors.add attr, 'has bad category.'
end
end
end
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:
class ProperCategoryValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless record.user.category_ids.include?(value)
record.errors.add attribute, 'has bad category.'
end
end
end
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:
class ReallyComplexValidator < ActiveModel::Validator
def validate(record)
record.errors[:base] << "This check failed!" unless thing(record)
record.errors[:base] << "This failed!" unless other(record)
record.errors[:base] << "FAIL!" unless fail(record)
end
private
def thing(record)
# Complex validation here...
end
def other(record)
# Complex validation here...
end
def fail(record)
# Complex validation here...
end
end
The API is basically to inherit from ActiveModel::Validator and implement a validate method that takes a record as its only argument. Then in your model classes, use it like so:
class NewsPost < ActiveRecord::Base
validates_with ReallyComplexValidator
end
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)
Installing the Rails 3 beta can be sort of tricky since there are dependencies, it’s a prerelease gem, and RubyGems basically poops the bed when those two scenarios collide. Hopefully that’ll be fixed soon, but the mean time, install Rails’ dependencies like so:
gem install rails3b
gem install arel --pre
# or if that gives you hassle...
gem install i18n tzinfo builder memcache-client rack \
rack-test rack-mount erubis mail text-format thor bundler
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!
The application generator is basically the same with two key differences:
~code/my_application rather than just my_application) and it will create the application there.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).So, let’s generate a blog application (really original, I know, right?):
rails rails3_blog -d mysql
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.
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:
config.generators do |g|
g.orm :active_record
g.template_engine :erb
g.test_framework :test_unit, :fixture => true
end
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.
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.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:
# Edit this Gemfile to bundle your application's dependencies.
source 'http://gemcutter.org'
gem "rails", "3.0.0.beta"
## Bundle edge rails:
# gem "rails", :git => "git://github.com/rails/rails.git"
gem "mysql"
## Bundle the gems you use:
# gem "bj"
# gem "hpricot", "0.6"
# gem "sqlite3-ruby", :require => "sqlite3"
# gem "aws-s3", :require => "aws/s3"
## Bundle gems used only in certain environments:
# gem "rspec", :group => :test
# group :test do
# gem "webrat"
# end
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:
group :test do
gem "mocha"
end
Now this gem will only be added in when testing. This will also be useful for production only gems related to caching and what not. [598652fa49634eaa9d23ab8df652faf73dfd07f4]
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.
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:
rails generate scaffold post title:string body:text
invoke active_record
create db/migrate/20100202054755_create_posts.rb
create app/models/post.rb
invoke test_unit
create test/unit/post_test.rb
create test/fixtures/posts.yml
route resources :posts
invoke scaffold_controller
create app/controllers/posts_controller.rb
invoke erb
create app/views/posts
create app/views/posts/index.html.erb
create app/views/posts/edit.html.erb
create app/views/posts/show.html.erb
create app/views/posts/new.html.erb
create app/views/posts/_form.html.erb
create app/views/layouts/posts.html.erb
invoke test_unit
create test/functional/posts_controller_test.rb
invoke helper
create app/helpers/posts_helper.rb
invoke test_unit
create test/unit/helpers/posts_helper_test.rb
invoke stylesheets
create public/stylesheets/scaffold.css
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:
def show
@post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @post }
end
end
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:
class PostsController < ApplicationController
respond_to :html, :xml
.
.
.
end
So your show action goes from the above to this:
def show
@post = Post.find(params[:id])
respond_with(@post)
end
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:
Rails3Blog::Application.routes.draw do |map|
resources :posts
root :to => "posts#index"
end
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:
<% @posts.each do |post| %>
<h2><%= link_to post.title, post %></h2>
<p>posted at <%= post.created_at.strftime('%D') %></p>
<p><%= post.body %></p>
<% end %>
<%= link_to 'New post', new_post_path %>
You can see what other design edits I made in this commit [03b2c39d65331f7dfeb4ada89cf65604f7130e2d].
Now we need to add the Markdown functionality to the Post model. First, let’s generate a migration [2cbb0b04411ac1712a4f5039ed93bdad0cb6e76e]:
rails generate migration AddRenderedBodyToPosts rendered_body:text
Migrate your database, and now we’re ready to move on to testing. Write a simple test to make sure it renders the body after a save [af83a5a2e85a1679896e989f6828d1f5ee4aa7d3]:
require 'test_helper'
class PostTest < ActiveSupport::TestCase
test "renders Markdown after save" do
post = Post.create(:title => "This post rocks.", :body => "Now *this* is an awesome post.")
assert_equal "<p>Now <em>this</em> is an awesome post.</p>", post.rendered_body.chomp
end
end
If you rake now, that test should fail. So, let’s make it pass:
class Post < ActiveRecord::Base
before_save :render_body
def render_body
self.rendered_body = RDiscount.new(self.body).to_html
end
end
You should be all green [4730cd4e8601c74a05b9763d307b462f76e44b26]! Now we’ll need to go back and change the instances of body to rendered_body on the index and show views.
That’s pretty standard Rails stuff, so let’s do something Rails 3-specific now. First, let’s add some validations; we’ll want to make sure that every post has a title and a body.
test "requires title" do
post = Post.create(:body => "Now *this* is an awesome post.")
assert !post.valid?
assert post.errors[:title]
end
test "requires body" do
post = Post.create(:title => "This post rocks.")
assert !post.valid?
assert post.errors[:body]
end
Note the new API for Active Record errors (i.e., [] rather then on) [930e8868b0e4d8904d6f5090f6b445b0c428f71f]. Now, of course, we have to make them pass…
class Post < ActiveRecord::Base
before_save :render_body
validates :title, :presence => true
validates :body, :presence => true
def render_body
self.rendered_body = RDiscount.new(self.body).to_html
end
end
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.
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.
My little gem rails-upgrade is now rails_upgrade, an officially blessed upgrade tool that will be maintained by myself and the Rails team. You can get it from here: http://github.com/rails/rails_upgrade.
To use it now, simply install the plugin:
script/plugin install git://github.com/rails/rails_upgrade.git
The plugin adds the following tasks:
rake rails:upgrade:check # Runs a battery of checks on your Rails 2.x app
# and generates a report on required upgrades for Rails 3
rake rails:upgrade:gems # Generates a Gemfile for your Rails 3 app out of your config.gem directives
rake rails:upgrade:routes # Create a new, upgraded route file from your current routes.rb
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…
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:
rails-upgrade check
It checks over some things, then generates a report like this:
named_scope is now just scope
The named_scope method has been renamed to just scope.
More information: http://github.com/rails/rails/commit/d60bb0a9e4be2ac0a9de9a69041a4ddc2e0cc914
The culprits:
- app/models/group.rb
- app/models/post.rb
Deprecated ActionMailer API
You're using the old ActionMailer API to send e-mails in a controller, model, or observer.
More information: http://lindsaar.net/2010/1/26/new-actionmailer-api-in-rails-3
The culprits:
- app/controllers/application.rb
- app/controllers/feedback_controller.rb
Old ActionMailer class API
You're using the old API in a mailer class.
More information: http://lindsaar.net/2010/1/26/new-actionmailer-api-in-rails-3
The culprits:
- app/models/post.rb
- app/models/user.rb
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.
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:
ActionController::Routing::Routes.draw do |map|
map.resources :posts, :collection => {:drafts => :get, :published => :get}
map.resources(
:users,
:groups,
:pictures
)
map.login '/login', :controller => 'sessions', :action => 'new'
map.logout '/logout', :controller => 'sessions', :action => 'destroy'
map.connect '/about', :controller => 'static', :action => 'about'
map.connect ':controller/:action/:id.:format'
map.connect ':controller/:action/:id'
end
And makes a new one like this:
YourApp::Application.routes do
resources :posts do
collection do
get :drafts
get :published
end
end
resources :users
resources :groups
resources :pictures
match '/login' => 'sessions#new', :as => :login
match '/logout' => 'sessions#destroy', :as => :logout
match '/about' => 'static#about'
match '/:controller(/:action(/:id))'
end
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.
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:
rails-upgrade gems
That will take an environment.rb with these config.gem calls:
config.gem "bj"
config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net"
config.gem "sqlite3-ruby", :lib => "sqlite3"
config.gem "aws-s3", :lib => "aws/s3"
And generate this Gemfile:
# Edit this Gemfile to bundle your application's dependencies.
# This preamble is the current preamble for Rails 3 apps; edit as needed.
directory "/path/to/rails", :glob => "{*/,}*.gemspec"
git "git://github.com/rails/arel.git"
git "git://github.com/rails/rack.git"
gem "rails", "3.0.pre"
gem 'bj',
source 'http://code.whytheluckystiff.net'
gem 'hpricot', '0.6'
gem 'sqlite3-ruby', :require_as=>"sqlite3"
gem 'aws-s3', :require_as=>"aws/s3"
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:
RakefileREADMEconfig/boot.rbpublic/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.rbconfig/routes.rbconfig/environment.rbconfig/environments/* (unless you haven’t touched these as many people don’t)config/database.ymldoc/README_FOR_APP (you do write this, don’t you?)test/test_helper.rbOf 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:
# This gem requirement...
config.gem "aws-s3", :version => "0.5.1",
:lib => "aws/s3", :source => "http://gems.omgbloglol.com"
# ...becomes:
source "http://gems.omgbloglol.com"
gem "aws-s3", "0.5.1", :require_as => "aws/s3"
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:
config object:lib key becomes the :require_as key:version key becomes a second, optional string argument:source arguments to a source call to add it to the sourcesOnce 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!
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:
# Load the rails application
require File.expand_path('../application', __FILE__)
# Initialize the rails application
YourApp::Application.initialize!
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:
module TestDevApp
class Application < Rails::Application
# ...Insert lots of example comments here...
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters << :password
end
end
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:
# Rails 2.x
config.cache_classes = false
config.action_controller.perform_caching = true
# Rails 3.x
YourApp::Application.configure do
config.cache_classes = false
config.action_controller.perform_caching = true
end
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.
You’ve probably heard a lot of talk about Rails and routes and new implementations 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)…
Upgrading a basic route looks like this:
# Old style
map.connect '/posts/mine', :controller => 'posts', :action => 'index'
# New style
match '/posts/mine', :to => 'posts#index'
A named route upgrade would look like:
# Old style
map.login '/login', :controller => 'sessions', :action => 'new'
# New style
match '/login', :to => 'sessions#new', :as => 'login'
Upgrading a resource route looks like this:
# Old style
map.resources :users, :member => {:ban => :post} do |users|
users.resources :comments
end
# New style
resources :users do
member do
post :ban
end
resources :comments
end
And upgrading things like the root path and so on looks like this:
# Old style
map.root :controller => 'home', :action => 'index'
map.connect ':controller/:action/:id.:format'
map.connect ':controller/:action/:id'
# New style
root :to => 'home#index'
match '/:controller(/:action(/:id))'
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.
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.
Interesting note: Remember that YourApp::Application class you created earlier in application.rb? That’s your Rack endpoint; that’s why your config.ru looks like this:
# 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.
I’m posting a whole series on Rails 3; be sure to catch these other posts!
Powered by Tumblr; designed by Adam Lloyd.