1. The Rails Upgrade Handbook is now available

    The eBook I previously mentioned is now available! It’s only $12 at http://railsupgradehandbook.com.

    Inside you’ll find…

    The website

    Comments
  2. Content from my Rails 3 presentation today, and a note about RailsConf 2010

    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.

    Download the slides

    Rails 3: The Why and How

    Links

    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!

    Comments
  3. Coming very soon: The Rails Upgrade Handbook

    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.

    The cover

    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).

    Comments
  4. Improved validations in Rails 3

    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:

    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:

    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 .

    Comments
  5. The Path to Rails 3: Greenfielding new apps with the Rails 3 beta

    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)

    An aside: Installing the Rails 3 beta

    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!

    Using the new generator

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

    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:

    You're on board!

    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:

    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.

    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.

    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:

    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.

    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!

    Comments
  6. rails-upgrade is now an official plugin

    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!

    Comments
  7. rails-upgrade: Automating a portion of the Rails 3 upgrade process

    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:

    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.

    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:

    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.

    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:

    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.

    Comments
  8. The Path to Rails 3: Approaching the upgrade

    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:

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

    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:

    # 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:

    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:

    # 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.

    Ch-ch-chaaange in the router

    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.

    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.

    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.

    Posts in this series

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

    1. Introduction
    2. Approaching the Upgrade
    Comments
  9. The Path to Rails 3: Introduction

    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:

    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.

    Overview

    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.

    The request chain

    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:

    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 new controller stack

    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.

    Intelligent SQL generation

    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.

    ActiveModel rawks.

    You can use this module to make any object behave like an Active Record object; for example, let’s say you wanted to add some validations to a PORO representing a host on a network:

    class Host
      include ActiveModel::Validations
    
      validates_presence_of :hostname
    
      attr_accessor :ip_address, :hostname, :operating_system
      def initialize(hostname, ip_address, operating_system)
        @hostname, @ip_address, @operating_system = host, ip_address, operating_system
      end
    end
    
    h  = Host.new("skull", "24.44.129.10", "Linux")
    h.valid?    # => true
    h.hostname = nil
    h.valid?    # => false
    

    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:

    # Subscribe to the event...
    ActiveSupport::Notifications.subscribe do |*args|
      @events << ActiveSupport::Notifications::Event.new(*args)
    end
    
    # Fire the event...
    ActiveSupport::Notifications.instrument(:system_mail, :at => Time.now) do
      #SystemMailer.important_email.deliver
      log "Important system mail sent!"
    end
    
    # Do something with it...
    event = @events.first
    event.name        # => :system_mail
    event.payload     # => { :at => Wed Jan 16 00:51:14 -0600 2010 }
    event.duration    # => 0.063
    system_log(event) # => <whatever>
    

    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!

    1. Introduction
    2. Approaching the Upgrade
    Comments

Powered by Tumblr; designed by Adam Lloyd.