The web is full of redirects. It isn’t that hard to figure out how to follow them using Ruby, but it always helps to have examples when you are learning. Not too long ago I was hacking on some feed auto discovery code and made a little class that, given a url, will find the endpoint and return the response from that endpoint.

I figured in the old spirit of clogging, I would post it here until I have time to package the full feed auto discovery library and release it on Github.

require 'logger'
require 'net/http'

class RedirectFollower
  class TooManyRedirects < StandardError; end

  attr_accessor :url, :body, :redirect_limit, :response

  def initialize(url, limit=5)
    @url, @redirect_limit = url, limit
    logger.level = Logger::INFO

  def logger
    @logger ||=

  def resolve
    raise TooManyRedirects if redirect_limit < 0

    self.response = Net::HTTP.get_response(URI.parse(url)) "redirect limit: #{redirect_limit}" "response code: #{response.code}" 
    logger.debug "response body: #{response.body}" 

    if response.kind_of?(Net::HTTPRedirection)      
      self.url = redirect_url
      self.redirect_limit -= 1 "redirect found, headed to #{url}" 

    self.body = response.body

  def redirect_url
    if response['location'].nil?
      response.body.match(/<a href=\"([^>]+)\">/i)[1]

You can then follow redirects as easily as this:

google ='').resolve
puts google.body

Which when run will output something like this:

I, [2009-03-04T17:16:58.879672 #69272]  INFO -- : redirect limit: 5
I, [2009-03-04T17:16:58.880669 #69272]  INFO -- : redirect found, headed to
I, [2009-03-04T17:16:58.987963 #69272]  INFO -- : redirect limit: 4

Followed by the html from which I did not include. The logger method comes in ridiculously handy when following redirects as sometimes it is kind of hard to figure out what is going on. You can also optionally pass in a limit for how many times you would like to redirect.'', 3).resolve

This would set the number of redirects to follow to 3, instead of the default 5. You always want to put some kind of limit on the number of redirects to follow or you could end up in infinite redirection.

Nothing fancy but it gets the job done. Maybe if I get a chance I’ll post on how to test this by stubbing responses.

Help kill Internet Explorer 6

Tháng Tư 19, 2009


Today Done21 is proud to announce IE6 Update, a great new tool to encourage your Internet Explorer 6 website visitors to update their browser. Check out, and if you end up using IE6 Update, tell us about it on Twitter using the hashtag #ie6update!

Now, some back story…

Internet Explorer 6 is the plague of the Internet. Sure there are other battles, like net neutrality or censorship, but I think it’s safe to say that IE6 has held back innovation more than anything else, because of its slow JavaScript engine, incorrect rendering of web pages, bad security, and more. At the time of this writing, Net Applications says 18% of Internet users still use Internet Explorer 6. Even worse, many sites have a much higher percentage of Internet Explorer 6 visitors.

There have been numerous efforts to put an end to Internet Explorer 6 and we’d like to thank all of them, particularly these:

While we applaud any campaign to put an end to IE6, most efforts we’ve seen are very developer centric. And although there have been many other great sites that politely ask users to update, I think developers have made the bold assumption that your average IE6 user is capable of distinguishing between their web browser and the Internet. It’s kind of a hard thing for us tech types to understand, but just take a look at Microsoft’s marketing for Internet Explorer 8:

IE8 Home Page
IE8’s Homepage

IE8 Upgrade your Internet
Upgrade your Internet

Better Web
IE8 makes your web better… what?

IE8 Banner Advertisement
Download a new Internet!

See what I mean? Microsoft markets its browser as the Internet itself. It’s no wonder its been so hard for developers to explain the situation to their site visitors. We, the web community, have politely asked web surfers to upgrade from IE6. We’ve tried. Everyone has tried. So now it’s time to trick them into upgrading. That’s right, trick IE6 users into moving on. Tricking users is a big taboo, but if we’re talking about tricking users into upgrading from IE6 to a newer browser, we feel that it’s like tricking them into receiving free money.

How can we do this? Well, you know that yellow bar that sometimes appears in Internet Explorer at the top of the browser window? It’s called the Information Bar. It usually displays information about security updates, missing plug-ins, and things of that nature. We decided that the best way to get behind enemy lines would be to fake the Information Bar and offer the user a browser update. Check it out:

IE6 Update

To use IE6 Update, all you have to do is go to this website, and then copy and paste the IE6 Update code into your site. It’s that easy.


This month is a very special month for Phusion. Not only was it one year ago that we posted our ideas on getting Ruby to work on all PHP platforms (RAHP) as an April fools joke, but it was also the month that Hongli and I officially founded Phusion, the Computer Science company at the Dutch chamber of commerce. Needless to say, seeing as this is Phusion’s first year anniversary as a company, we felt strongly inclined to go the extra mile and make this one count. Instead of making yet another April fools joke, we wanted to take the opportunity to announce a long-awaited addition to our Phusion Passenger line-up. In a way, I guess the joke would be that this really isn’t a joke. :-D

We are glad to announce…

Phusion Passenger for Nginx

Ever since the first release of Phusion Passenger for Apache, some people have been asking us to create a Phusion Passenger for platform XYZ. Well, it may come to you as no surprise but we’ve been playing with similar ideas for quite some time. In fact, we’ve architected Phusion Passenger to be as independent from any specific web server as possible to make something like this an option to consider to begin with.

For us however, maintaining a product to live up to the high quality standards that you’ve come to expect of our products requires a lot of time and effort. Maintaining multiple versions of a project won’t exactly lower this amount of required effort and with limited resources in mind, this made us a bit reluctant on doing something like this from the start. Instead, we chose to focus our efforts on polishing up one version before ever deciding to make the jump to another server platform, a choice from which we’d be able to reap the fruits from in tenfold. Not only in terms of experience, but also in terms of having a more robust and solid code base to work from.

Even though we would be able to share a lot of code between different server versions from an architectural point of view, this would only be a small benefit compared to the work that would still be required. Not only would a fair deal of specific code need to be written but also maintained and documented. This process in particular is painful if the server software you’re writing it for doesn’t have any documentation itself, which became all too apparent for us in some particular cases.

Despite being able to successfully create several versions, we weren’t able to infer significant benefits over the Apache version, both from a technical point of view as well as from an ease of use point of view. In fact, in past articles we’ve elaborated on both points quite a deal and had decided not to pursue its release in favor of polishing the core foundations of Phusion Passenger first and foremost. However, reasons like these usually only play a small part in the choice of technology. Company policies and dependencies of other software usually play a bigger part in deciding this, and with this in mind, Apache might not always be an option. In this regard, we’ve always wanted to accommodate the largest denominator and it is for this reason that the initial version of Phusion Passenger and the ones that followed were exclusively for Apache. Until today that is.

A few weeks ago, as you may still remember from the comments in this article, Ezra of Engine Yard contacted us on the possibility of financially sponsoring a first release of Phusion Passenger for Nginx. Even though we had already written the majority of the code for Nginx Passenger quite a few months ago, we didn’t feel it was the right time to release it back then.

By the time of this writing however, Phusion Passenger is almost one year old and as mature as it has ever been thanks to all the contributions people have made during this time. With this in mind, we decided to accept Ezra’s offer.

After spending weeks on further development and intensive testing, we’ve now come to the point wherein we have the distinct honor to announce Phusion Passenger for Nginx as an addition to the Phusion Passenger server line-up.. Our thanks goes out to Engine Yard for financially sponsoring this first release of Phusion Passenger for Nginx, as well as all the people who have in some way donated in the past for making this release possible in the first place.

Great, how do I get started?

Geoffrey Grosenbach of Peepcode fame has kindly created a screencast for us. This screencast covers everything you need to get started with deploying a Rails/Ruby web application on Nginx using Phusion Passenger.

Nginx screencast by Geoffrey Grosenbach

In a nutshell, you first need to install the Phusion Passenger gem:

sudo gem install passenger

(Note: Rubyforge might still be updating their mirrors. If the above command didn’t install 2.2.0 for you and you can’t wait, then download the 2.2.0 gem from Google Code)

Both the Apache and the Nginx version are contained in the same gem, which keeps things nice and simple!

Next, you need to run the passenger-install-nginx-module command, similar to what you’re used to when installing the Apache version:

sudo passenger-install-nginx-module

Nginx doesn’t support loadable modules like Apache does, so it needs to be compiled from scratch. But the installer can do this for you as well! You can of course also choose to compile Nginx manually. Once Nginx has been compiled and installed, the installer will tell you how to configure Nginx and how to deploy a Rails application on Nginx. A typical deploy server bock looks like this:

server {
    listen 80;
    root /webapps/foo/public;   # <--- notice the 'public' part
    passenger_enabled on;       # <--- don't forget this!

We’ve also spent a lot of effort on documenting Phusion Passenger for Nginx. For detailed installation instructions and usage instructions, please refer to the users guide for Nginx.

If you prefer to install Phusion Passenger via the source tarball instead, then that’s also possible. Please read the included README for installation instructions.

Where to report bugs

If you’ve found a bug, please do not post it in a comment, but file an issue on our issue tracker instead.

Other changes

In addition to bringing you an Nginx version of Phusion Passenger, we’ve also made improvements in the Apache version. The most important changes are:

Support for chunked file uploads
Resource-limited HTTP clients, such as mobile devices, often send HTTP file uploads using the “chunked” transfer encoding in order to save resources. Previous versions of Phusion Passenger didn’t support this, but now it does! Please note that chunked file uploads is only supported in the Apache version; the Nginx version doesn’t because doesn’t support chunked file uploads.
Support for Capistrano-style deployments
Whenever you deploy a new release with Capistrano, previous versions of Phusion Passenger will leave the application processes of the last release running until they idle timeout. This includes the old release’s ApplicationSpawner server process. This is caused by the fact that Phusion Passenger uniquely identifies an application based on its canonical path, meaning that any symlinks in the paths are fully resolved. In Capistrano-style deployments, the ‘current’ directory is actually a symlink to a release directory, so every time you deploy a new release, Phusion Passenger thinks that it’s a totally different application. 

This issue has now been fixed, and Phusion Passenger no longer resolves symlinks anymore. So whenever you deploy a new release with Capistrano, Phusion Passenger will properly detect it as being the same application. If you had any hacks in your deploy.rb for killing off old processes, then you can remove them now!

Ability to load application_controller.rb from non-standard directory
In some applications, application_controller.rb is located in the search path, though not in app/controllers. Support for this kind of setup has been fixed.
Worker process event hooks for Rack
The :starting_worker_process and :stopping_worker_process event hooks have been implemented for Rack as well. Thanks to Saimon Moore.

Some final words

We initially planned to announce this release at the coming Railsconf, but the temptation was just too big to announce this on our very first anniversary. Also, if all goes as scheduled, we may have an even bigger announcement at Railsconf, so stay tuned! ;) Follow us on Twitter too to stay in the loop ( @phusion_nl )

This one is pretty good for newbies

Source: is a site offering a series of 17 Basic Ruby tutorials in screencast form. In a way, it’s like Railscasts, but focusing solely on basic Ruby techniques. So far there are 17 tutorials covering basic topics from whitespace and identifiers through to symbols and hashes, but it looks like there’ll be more in future.

These videos probably won’t be of much direct use to the average Ruby Inside reader directly, but if you have developers under you or friends who need to learn Ruby and you want them to get a quick fire, bite by bite introduction to some of the concepts involved, point them to Tekniqal.

The videos so far are:

1. Identifiers
2. Whitespace
3. Dynamic Typing
4. Variables – Scope
5. Methods
6. Conditions
7. Loops
8. String Delimiters
9. Symbols
10. Strings and Mutability
11. Ranges
12. Creating Arrays
13. Accessing Arrays
14. Manipulating Arrays (Part 1)
15. Manipulating Arrays (Part 2)
16. Working with Hashes (Part 1)
17. Working with Hashes (Part 2)


How to write helper libraries for your Cucumber step definitions and how to upgrade your support libraries from Cucumber 0.2 to 0.3 (released today).

In cucumber, each scenario step in a .feature file matches to a GivenWhenThen step definition. The step definitions are normal Ruby code. First class, bonnified, honky-tonk Ruby code. And what’s the one thing we love to do to Ruby code on a rainy Sunday afternoon? Refactor it. Turn messy code into readable “return in 50 years, on the time capsule, and get back to work quickly” code.

In Cucumber we use a special, until-now unknown, magic technique for refactoring step definitions. They are called “Ruby methods”. Oooh, feel the magic. You take some code in a step definition and you refactor it into a method. And you’re done. For example:

When /I fill in the Account form/ do
  fill_in("account_name", "Mocra")
  fill_in("account_abn", "12 345 678 901")

Could be refactored into:

When /I fill in the Account form/ do

def fill_in_account_form
  fill_in("account_name", "Mocra")
  fill_in("account_abn", "12 345 678 901")

Good work. Or is it? No, we’ve done something a little naughty. We’ve polluted the global object space with our method and turns out it just isn’t necessary. There’s a nicer way and a clean idiom for how/where to write helper methods.

Annoyingly, that idiom broke with the release of Cucumber 0.3. So I’ll introduce both so you can fix any bugs that you spot and know how to fix them.

The solution is to understand the existence of the World object and the clean technique for writing features/support/foobar_helpers.rb libraries of helper methods.

Introducing the World object

To ensure that each cucumber scenario starts with a clean slate, your scenarios are run upon a blank object. Or in a Rails project its a new Rails test sessionActionController::IntegrationTest.

These are called World objects (see cucumber wiki). You pass in a specific World object you’d like to use, else it defaults to For a Rails project, you’re for your world object each time, which is a subclass ofActionController::IntegrationTest.

The benefit of a World object starting point for each scenario is that you can add methods to it, that won’t affect the rest of the Ruby world you live in: which will be the Cucumber runner. That is, you cannot accidently blow up Cucumber.

Extending the World object

Step 1, put methods in a module. Step 2, add the module to your World object.

So that we’re all extending Cucumber in the same way, there is a folder for where your helper methods should be stored, and a programming idiomatic way to do it. It has changed slight from Cucumber 0.2 to 0.3 so I’ll show both.

For our helper method fill_in_account_form above:

  1. Create features/support/form_submission_helpers.rb (its automatically loaded)
  2. Wrap the helper method in a module module FormSubmissionHelpers ... end
  3. Tell Cucumber to include the module into each World object for each Scenario

In Cucumber 0.3+ your complete helper file would look like:

module FormSubmissionHelpers
  def fill_in_account_form
    fill_in("account_name", "Mocra")
    fill_in("account_abn", "12 345 678 901")

For Cucumber 0.2 your complete helper file might have looked like:

module FormSubmissionHelpers
  def fill_in_account_form
    fill_in("account_name", "Mocra")
    fill_in("account_abn", "12 345 678 901")
World do |world|
  world.extend FormSubmissionHelpers

Where the difference is the last part of the file. This mechanism is deprecated and results in the following error message after upgrading to Cucumber 0.3:

/Library/Ruby/Gems/1.8/gems/cucumber-0.3.0/bin/../lib/cucumber/step_mother.rb:189:in `World': You can only pass a proc to #World once, but it's happening (Cucumber::MultipleWorld)
in 2 places:

vendor/plugins/cucumber/lib/cucumber/rails/world.rb:72:in `World'
vendor/plugins/email-spec/lib/email_spec/cucumber.rb:18:in `World'


Refactor step definitions. Put it in features/support/…_helpers.rb files, inside modules that are assigned to the World object.




Redcar is a programmer’s text editor for GNOME, written in Ruby and Vala (a curious C# like language for use with GNOME), by Daniel B Lucraft.

Redcar probably isn’t going to be your next editor, at least not yet. It’s still in its early stages with version 0.1 only being released a week ago and you have to get it running from source (no binary distributions yet). Despite all of this, it already boasts compatibly with Textmate highlighting, snippets, and quite a lot of Textmate bundle commands. It’s GPL2 licensed, too. The code is available in a Github repository.

Despite the focus on GNOME, it should be possible to get Redcar running on both Windows and Mac OS X as well as Linux, but I’ve personally found the dependencies for Ruby-GNOME2 to be an absolute beast to install on OS X. Installation instructions are provided, however, for the brave.

Redcar is already a good looking app (on Linux, at least) and even though it’s in its early days, it provides an interesting case study for if you want to build a Ruby GUI app based around Ruby-GNOME2.


The Twitter gem is kind of my baby. It was pretty much the first gem I created and as such I care for it a little more. When I originally created it, I knew nothing. I sucked. Now over time, I suck less and Twitter’s addition of OAuth seemed like the perfect time to completely rewrite it. Yay for rewrites!

The gem is now leaner, meaner and works swell with OAuth. I would imagine as I use OAuth a bit more, I’ll figure out some ways to make it even easier in the twitter gem but it works for now.

The Cuts

One of the biggest headaches and coolest things about the Twitter gem was the command line interface. It allowed for multiple accounts and was SQLite database backed. That was cool and all but it is ridiculous to have main and active record as dependencies for someone who just wanted the API wrapping aspects of the gem.

Knowing this, I have finally killed the CLI. Fear not, CLI fans, it will make a triumphant return, but that return will be in a separate gem that merely relies on the Twitter gem. The Twitter gem itself will be only a wrapper for the REST and Search APIs that Twitter provides. No more extra cruft.


As I said, the main reason for the rewrite was that Twitter now supports OAuth. I thought about it long and hard and decided to not continue support for HTTP Authentication. Twitter has not discontinued support for HTTP Authentication, but they will in the future and I didn’t want to add a bunch of hours to releasing the updated gem simply to support something that is going to be deprecated.

So how does one use the OAuth stuff in the Twitter gem? First off, familiarize yourself with OAuth. Then, you can check out the example below pulled straight from the examples directory included in the gem (or over here on github).

require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
require File.join(File.dirname(__FILE__), 'helpers', 'config_store')
require 'pp'

config ="#{ENV['HOME']}/.twitter")
oauth =['token'], config['secret'])

if config['atoken'] && config['asecret']
  oauth.authorize_from_access(config['atoken'], config['asecret'])
  twitter =
  pp twitter.friends_timeline

elsif config['rtoken'] && config['rsecret']
  oauth.authorize_from_request(config['rtoken'], config['rsecret'])
  twitter =
  pp twitter.friends_timeline

    'atoken'  => oauth.access_token.token,
    'asecret' => oauth.access_token.secret,
  }).delete('rtoken', 'rsecret')
    'rtoken'  => oauth.request_token.token,
    'rsecret' => oauth.request_token.secret,

  # authorize in browser
  %x(open #{oauth.request_token.authorize_url})

The ConfigStore is a simple class that allows me to save the request and access token and secrets as I’m completing the handshakes between the script and Twitter.

As you can see, it is pretty simple. Get a request token, then use that to create an access token. From there, you can reuse the access token to authorize future requests.

An Example App

Now one might think, based on that previous example, “Thanks so much John! I really appreciate you getting the ball rolling for me with a simple example.” Friends do I have news for you. I didn’t stop there. I whipped together a little sample app, that I have been using for a few days now. Eventually, it will become a full Twitter client, but for now it is pretty basic and dirty.

It uses Clearance for authentication and automatically sends you to Twitter to authorize after firing it up (if you haven’t previously). I used Rails rescue_from to automatically send you to Twitter if any of the authorization stuff gets messed up at a later point to.

rescue_from Twitter::Unauthorized, :with => :twitter_unauthorized
  def twitter_unauthorized(exception)
    redirect_to new_authorization_url

Anytime the Twitter gem throws the Twitter::Unauthorized exception, you are redirected to new_authorization_url, which is powered by the AuthorizationsController, which looks like this.

class AuthorizationsController < ApplicationController
  def new
    oauth = current_user.oauth
    session['rtoken'] = oauth.request_token.token
    session['rsecret'] = oauth.request_token.secret
    redirect_to oauth.request_token.authorize_url

  def show
    oauth = current_user.oauth
    oauth.authorize_from_request(session['rtoken'], session['rsecret'])

    session['rtoken'] = nil
    session['rsecret'] = nil

      :atoken => oauth.access_token.token,
      :asecret => oauth.access_token.secret,

    redirect_to root_path

The new action stores the request token and secret and then redirects you to Twitter to authorize the app. Over at Twitter, I have registered an application and set the redirect url to go to /authorization in the app, which as you can see above, obtains the access token and secret and stores them with the current user.

You’ll probably notice that I am calling current_user.oauth and current_user.client throughout the app. These are helper methods I added to the user model to shorten up what was happening in the controller.

class User < ActiveRecord::Base
  include Clearance::App::Models::User

  attr_accessible :atoken, :asecret

  def authorized?
    !atoken.blank? && !asecret.blank?

  def oauth
    @oauth ||=['token'], ConsumerConfig['secret'])

  def client
    @client ||= begin
      oauth.authorize_from_access(atoken, asecret)

I could shorten up the controllers even more (and will at some point) by delegating several methods on user to user.client. I’ll post more on that later when I get around to it. Also, at some point, I’m going to remove the atoken and asecret from the user and allow support for multiple Twitter accounts for one user in the app. This should be pretty easy, but I wanted to get something working first before I complicated things.


From a user standpoint, OAuth is really nice. I love not having to put in my username and password. From a developer standpoint, OAuth is also pretty nice. Basically, you register your application with Twitter, provide the consumer token and key in a config file and this example app is ready to go.

As with any rewrite there are bound to be bugs. I have fixed one already that someone caught. If you catch any weird bugs using the rewritten Twitter gem, there is group and ticket information on the Twitter gem website.


rabbitmq.png When it comes to developing large systems with many interdependent parts, it’s common nowadays to use “queues.” A queue is, for the most part, just a list that you can add items to and remove items from. Apps can use queues to despatch jobs / tasks to other apps or to shuttle logs and status information around.

RabbitMQ is a fast, reliable, open source queueing option. It’s not developed in Ruby, though, but in Erlang, a functional language with a reputation for distributed, high availability, fault tolerant apps. It presents itself as a separate daemon – much as Apache, Passenger, memcached, or MySQL aren’t written in Ruby. Using it from Ruby isn’t difficult, and, of course, you can use it from a multitude of languages so if you want to push in items from Ruby and pull them out to be processed with something else (or vice versa) it’s ideal. RabbitMQ can be used as a hub for communication between all of your processes.

On RabbitMQ, Rany Keddo, the developer of Workling, said:

If you’re doing high volume messaging and need a high degree of reliability, you should definitely consider using RabbitMQ over Starling.

(And since I started to draft this article, this point has perhaps been proven even more with Twitter’s ditching of Starling for a new, Scala-based system.)

So RabbitMQ has the power and reputation and if you want to do some serious queueing, you should be checking it out. With that in mind, Alexis Richardson (from the RabbitMQ team) and I have put together a few resources that will be useful to you (as a Rubyist) if/when you decide to check RabbitMQ out:

Official RabbitMQ Homepage – Homepage with general feature information, links to documentation, downloads and examples.

Installing RabbitMQ on OS X – A guide to installing RabbitMQ on Mac OS X by Rany Keddo. With the installation of Erlang, it’s not quite the quickest process, but it’s worth the wait.

AMQP “driver” for Ruby/EventMachine – A Ruby library by Aman Gupta that provides an event driven AMQP implementation for Rubyists, built around EventMachine. Works on Ruby 1.8, 1.9, and JRuby and tested directly against RabbitMQ.

Riding the Rabbit – A blog post by Dan Sinclair that demonstrates the setup of a RabbitMQ instance, and the use of the aforementioned AMQP Ruby/EventMachine library.

OH HAI RabbitMQ! Screencast – A great screencast by British Rubyist Jonathan Conway that demonstrates how to set up RabbitMQ and perform some basic operations.

Warren – A wrapper for AMQP – A library for pushing messages on to RabbitMQ queues (and receiving them at the other end) by the Brightbox crew. Authentication and filtering features can be added through custom classes.

RabbitMQ and Ruby presentation – Ben Hood (one of RabbitMQ’s developers) gives a 40 minute presentation on RabbitMQ and Ruby. He looks at the background of RabbitMQ, the motivations behind using something like RabbitMQ, the approaches that have been taken in the past, AMQP, and, yes, a lot more.



Five months ago JetBrains (the company behind Java IDE IntellJ IDEA) released a “public preview” of RubyMine, a new Ruby and Rails IDE. Now, they’ve released the beta of version 1.0, the precursor for a final 1.0 launch later this month. You can download it right away – it came in at about a 75MB download for OS X, but Windows and Linux versions are also available.

When I posted about the preview of RubyMine five months ago, several people raved about how great they thought JetBrains’ IntellIJ IDEA IDE was (which RubyMine is built upon). I don’t have any personal experience with IntellIJ so you’ll need to make your own mind up, but in casual testing RubyMine worked well. There were a few rough edges (project file list didn’t always update with new files quickly; some minor interface snafus; had to add db:migrate Rake task manually) and there’s the downside that it takes several minutes to start your first project as it wants to scour through all of your Ruby libraries. On the plus side, it felt more intuitive to put together a basic Rails app than in the other IDEs I’ve tried so far.

Ruby Inside will feature a complete review once the final release drops.

The Feature Set

rubymineide.pngOn the surface, RubyMine offers all of the features you’d expect from a high-end IDE:

  • Code completion
  • Code snippet support
  • Refactoring tools
  • Project file management / navigation
  • HTML, CSS, and JavaScript editing (including Erb support)
  • RSpec and Test::Unit support (with GUI-based test runner)
  • Built-in Rails console
  • Ruby debugger (with full support for Rails apps)

JetBrains’ RubyMine blog is a good source for info about these features as most of them have been added over time.

It’s Commercial – But Only $99 (or $49, if you want)

RubyMine is available as a free, 90 day trial, but is ultimately a piece of commercial software that will retail for $99. JetBrains have a sign up form where you can get a 50% off coupon for the final version of RubyMine 1.0, however, so that should take the sting out of the tail and bring the price down to $49.

I was a bit worried when I first mentioned RubyMine that it was going to be a $200+ app that people would be reluctant to buy, but if you can get the coupon to get it down to $49, it’s a great deal. Even at $99, it’s not bad, although, naturally, there are plenty of open source options if it’s not to your taste.


I mentioned a multi-step/multi-project solution to doing JavaScript Unit Testing for Rails, including an autotest script to make TDD life easier for the autotest-addicted.

It was too many steps, too many different projects, and too much dependence on prototypejs. So let’s fix this via the spanky new newjs (introduced here):

Instead of several steps, there is now two steps:

cd myrailsapp                # rails 2.0 app
sudo gem install newjs       # v1.3.1+
script/generate javascript_test application
    create  vendor/plugins/javascript_unittest/lib
    create  vendor/plugins/javascript_unittest/tasks
    create  test/javascript/assets/jsunittest.js
    create  test/javascript/assets/unittest.css
    create  config/javascript_test_autotest.yml.sample
    create  vendor/plugins/javascript_unittest/lib/jstest.rb
    create  vendor/plugins/javascript_unittest/tasks/runner.rake
    create  vendor/plugins/javascript_unittest/tasks/autotest.rake
    create  vendor/plugins/javascript_unittest/README
    create  test/javascript/application_test.html
    create  script/rstakeout
    create  script/js_autotest

It installs all assets, gives you a rake test:javascripts task, gives you script/js_autotest, and finally (and most importantly), creates the application_test.html test stub.

As always, you can also run a single test file by loading it into a browser.

Prototype independence

Previously, the test suite – unittest.js – had a dependency on prototypejs. This was wonderful if you’re developing in prototypejs, but could cause some grief if you weren’t.

newjs now comes packed with an identical test suite – jsunittest – but it is built without a dependency on prototypejs.

Merb et al support

I wrote a rails generator because I used Rails. If a merb/other framework (Ruby or non-Ruby) wants a similar generator, just ask. Its pretty simple – I copy over the rails_generators folder into a merb_generators folder in newjs and change some things based on your frameworks’ structure.

Alternate test suite support

If you like another test suite, and want it included in the generators, this might require some additional effort on your part. It probably has different mechanisms for launching runners etc; whereas I was able to steal the rake tests + support libraries from prototypejs. But, it can be done.


These tools will be discussed in animated detail in the forth coming Peepcode “JavaScript Unit Testing”.