Category: Rails

  • Introduction to rcov, code coverage for Ruby

    Do you routinely test your code? Are you using rcov to run code coverage reports for your tests? If you aren’t, you should be. rcov is a code coverage tool for Ruby that is available as a Gem or a Rails plugin. It can generate text or HTML reports outlining what percentage of your code base is being exercised by your tests. The HTML reports even allow you to drill down and see exactly which lines in your code are being touched. If you’ve ever used a tool like Cobertura for Java, you’ll know exactly what to expect with rcov.

    Using rcov on a regular basis will enable you to isolate parts of your codebase that aren’t being tested very well (if at all). For example, the first time I ran rcov on one of my projects, it reported that the tests written against my Rails models touched 87% of the code. Not too shabby! However, my Rails controllers only had 45% coverage. Where do you think I concentrated my testing efforts after rcov was kind enough to inform me of these facts?

    Installing and using rcov with an existing Rails project is a cinch. Let’s get started:

    gem install rcov
    

    Now move to the root of your Rails project and type:

    script/plugin install http://svn.codahale.com/rails_rcov
    

    Voila! Installation complete. Don’t you just love Rails? Now let’s fall in love with Rake:

    rake test:units:rcov
    rake test:functionals:rcov
    

    Running these tasks will generate a text-based report of your project’s code coverage. The percentage of each class covered is listed, along with a total for the entire set of tests (unit vs. functional). Rcov also creates a /coverage directory beneath the root of your Rails project. Inside this directory, you’ll find some beautiful HTML-based coverage reports.

    Want to report on just your model classes? What about controllers? Easy enough:

    rake test:units:rcov SHOW_ONLY="app/models"
    rake test:units:rcov SHOW_ONLY="app/controllers"
    

    Delightful. Now I’d be set if only rcov integrated with Zen’s autotest to display a coverage report that automatically updates every time I change some code. One other minor nitpick is that, much as it seems like rake test:rcov should work, it doesn’t. Something else to add to a future release, I suppose.

    Are you in a team environment? Hook rcov up to a continuous integration system and catch Jonny slacking off on his tests… a full half hour before the morning stand-up meeting.

    For the price, you can’t beat what rcov provides. It won’t tell you if your tests are logically correct, but it sure as heck will scream at you if you’re not writing them to begin with.

  • Using protected attributes in your Rails models

    Let’s say we’ve created a simple profile page to allow our users to update their e-mail address, locale, time zone, and various other settings. This profile page exposes only those model attributes that we want the user to be able to update. Other attributes on the model should not be updateable by the user.

    We opt to surface the updateable attributes on the profile page and assume that the user won’t be able to update the remaining attributes since they won’t even appear on the page. But does that really provide enough protection?

    Our model and database schema are defined as follows:

    class User < ActiveRecord::Base
    end
    
    create_table :user |t|
      t.column :username, :string  t.column :password, :string
      t.column :fname, :string
      t.column :lname, :string
      t.column :email, :string
      t.column :permission, :string
    end
    

    Our model can store a username, password, first and last name, e-mail address, and permission level. The permission level is used to determine what the user is allowed to do on the site. A permission level might be "Moderator" or "Admin."

    Our profile form surfaces the attributes that we want to be updateable:

    <%= start_form_tag %>
      <%= text_field :user, :fname %> First Name
    <%= text_field :user, :lname %> Last Name
    <%= text_field :user, :email %> E-mail Address
    <%= submit_tag %> <%= end_form_tag %>

    It's obvious that we only want the user to update his first and last name and e-mail address. Now let's examine the action being called when we submit the profile form:

    def update
      @user = User.find(params[:id])
      if @user.update_attributes(params[:user])
        redirect_to :action => "success"
      end
    end
    

    Our action looks up a user, updates its attributes with the new values passed on the request, and redirects to a new action if the update was successful. Simple enough, yet the code above could allow a malicious user to update the permission level of his account... something we certainly don't want him doing! Assuming the action is not protected against GET requests, we could simply visit the following URL in our browser to give the user a different permission level:

    http://localhost:3000/user/update/1?user[permission]=Admin
    

    Protecting the action against GET requests would prevent the attack from occuring via a URL, but the attacker could easily generate a POST request through other means. Rails provides a way to protect against such attacks: the #attr_protected class method:

    class User < ActiveRecord::Base
      attr_protected :permission
    end
    

    Now if we attempt our attack again, the permission level simply doesn't get updated. The other attributes sent on the request are assigned correctly, but the permission level isn't. Why not?

    It turns out that #attr_protected makes it impossible to update the permission attribute through the #update_attributes method (or any other mass assignment method for that matter). The only way we can update the permission level now is by using single-assignment techniques such as:

    @user.update_attribute(:permission, "Admin")
    

    It's generally a good idea to protect attributes that could cause a security breach in your system. These might include usernames, passwords, software keys, and even product prices. While by no means a silver bullet, #attr_protected is still a good tool to use as you begin locking down sensitive parts of your application.

    #attr_protected accepts multiple attributes so we could rewrite our model again as:

    class User < ActiveRecord::Base
      attr_protected :username, :password, :permission
    end
    

    #attr_protected also has a more conservative cousin, #attr_accessible. It renders all attributes on the model unavailable for mass assignment unless they are specifically named. This differs from #attr_protected which lets you start in an "all-open" state and only restrict attributes as necessary. Both methods are handy to have in your toolbox.

  • What’s the best Rails web host?

    During the Ruby hack fest tonight the topic of Rails web hosts came up again. This seems to be a frequent topic of discussion lately. The usual questions are (1) which host is the best, and (2) which host is the cheapest? I thought I’d post my own recommendations here for those who are interested.

    I’ve hosted my small Rails apps at TextDrive for over a year now. Although I’ve heard from many people who seem to have no end of trouble with them, I’ve experienced nothing but stellar service from them so far. I average maybe an hour of down-time per month, which is perfectly acceptable to me. The control panel used to be slow as mud, but it’s pretty zippy now. With shell access and the flexibility to customize the environment to suit my needs, it’s a nice setup. It’s also $12.95/month for the basic package.

    Other hosts that support Rails include DreamHost and OCS Solutions. You can read more about OCS on Soapadoo. I’ve never used either of these hosts, but I’ve heard good things about them from people who have.

    So, what’s your favorite Rails web host?

  • Teascript opens for beta testing next week

    Teascript is my latest Rails application. It’s scheduled to go live in mid-September. You can read more about it in the original announcement that I posted a few weeks ago.

    Beta testing for Teascript begins next week. I’m looking for a dozen or so people to help sanity check the application before I unleash it on the public. (I already have 8 signed up.) As a beta tester, you would receive full access to the product starting early next week.

    While I’m not requiring anyone who volunteers as a tester to send me feedback, it’s much appreciated! Interested? Shoot me an e-mail at matthew AT teascript DOT com and I’ll add you to the list.

  • Introducing Teascript

    Teascript is a Rails-based web application I’ve been working on for about a month. It’s targeted towards home school parents and students who need to design a high school transcript with minimum fuss.

    Traditionally, this process has been quite involved. My own parents and I designed my transcript using an Excel spreadsheet. It was painstakingly slow! Many home school books have transcript templates in them, but again, the process of photocopying and filling them out is time consuming.

    It is because of this that I decided to create Teascript. The application is still under development, but I have put up a teaser page highlighting some of its features. The page also allows you to sign-up to receive notification when Teascript goes live sometime later this year.

  • I’ve gone independent

    Yes, I’ve left SAS, the world’s largest privately held software company. What would make me do such a thing? There were many factors involved in the decision, of course, but the primary reason was the opportunity to work full-time with Ruby on Rails from home. This will give me more time with my family. I’m also looking forward to doing more writing, speaking, and volunteering during the remainder of the year. Leaving was a difficult decision because I’ve enjoyed my last three years at SAS very much, but I’ve been wanting to get into independent consulting for over a year now. When the opportunity came up last month, I felt led to take it.

    My primary purpose in making this post was not to cast for offers, but I do want folks to know that I’m available now. My specialties are Ruby, Rails, Java, .NET, and PHP. I’m interested in using these technologies to develop world-class applications, especially web-based applications. I also have a passion for testing and continuous integration. I’m interested in helping development teams build and install automated testing frameworks and continuous integration servers. My background in agile development processes makes these interests a good fit.

    I’m not sure what the future holds for me in this area, but the freedom I’ve experienced so far is incredible. I know this is where God wants me right now. I’m looking forward to enhancing my development skills and branching out into new specializations. I’ve always enjoyed learning (due in large part, I think, to my background as a home schooled student) and now I’ve been given the chance to do so on a level I wasn’t able to before. What an adventure!

  • RailsConf draws to a close

    It’s mid-afternoon here in Chicago and RailsConf has just officially ended. There is a huge line of people out front of the hotel waiting to catch the next shuttle to O’Hare. I’ll need a few more days to properly digest the conference and write a more detailed overview of what happened, but overall it was the most positive experience I’ve had at a conference outside of NFJS. Great speakers, late nights of hacking with friends, and geeky conversation. Well worth the time, money, and trouble to come.

  • RailsConf ho!

    Tomorrow I fly to Chicago for the biggest Ruby bash so far this year: RailsConf 2006! Aside from getting to hear some wonderful keynote speakers and hang out with a herd of fellow Rubyists, many of my buddies from the Raleigh area (and elsewhere) will also be in attendance. It’ll be great seeing familiar faces again, and meeting the owners of some new ones. If you’re planning on being at RailsConf too, consider posting a comment here so I’ll know to look for you.

    Chicagoans, brace yourselves. The geeks cometh.

  • Introducing Radiant, a Rails-based CMS

    An old friend from a project I briefly worked on during my days at RoleModel Software just released a Rails-based open source Content Management System called Radiant this week. It looks pretty snappy! Add to that the fact that the Ruby-Lang web site will soon be using it and you’ve got a free package that’s very attractive.

    Check out John’s announcement on his blog for more information about the CMS, including some nice screen captures. It’s quite pretty looking. I’m very tempted to convert one of my existing sites to it just to see how it works.