Running Capybara and RSpec without Rails

Inspired by a recent Railscast on Capybara, I decided to satisfy my holiday coding urges by looking into how Capybara might help us automate more testing at Podio. We are lucky enough to have a full time resource doing quality assurance, and we have often talked about how something like Selenium might help her automate a number of “sanity checks” that we could run before deployments. When I realized how well Capybara work with Selenium’s web driver, I had to investigate a bit more.

Podio is currently a mix of PHP and Rails (talking to a Python-driven API), and these automated tests of course had to work independently of whether a certain page was in PHP or Rails. Also it would be nice if our QA didn’t have to have the sites running locally to run the tests. These things ruled out running Capybara inside the Rails application, so I opted for making a seperate, Ruby-only test-suite for automated QA running against our staging server. There is a ton of challenges in this that I haven’t fully solved yet, most importantly how to manage test data on a separate server. This article only outlines how to get a simple Ruby application (without Rails) up and running that can test a remote site.

First step is to install the bundler gem, create a Gemfile in the root of the application and run the bundle command:

The gotcha here is that the “trunk” version of the Capybara gem on Github should referenced in the gemfile for compatibility with RSpec 2.

Continue reading

Event-driven javascript with jQuery

I’m not exactly a javascript guru, and this article is not exactly rocket science. However, I have done web development for the past 10 years and almost all projects has involved a decent amount of javascript hacking. The past couple of years jQuery has been the obvious choice, but what’s both good and bad about this framework is that it doesn’t enforce any specific style of javascript development. Javascript is an amazingly flexible scripting language, and can used both strictly object-oriented, mind-bendingly function-oriented – and everything in between. I don’t have a very consistent style other than the basic rule of thumb of “namespacing” by wrapping functions within an object to minimize the risk of clashing method definitions.

One of the most advanced javascript-driven pages I have developed is the list page of Lokalebasen.dk (it’s in Danish only, sorry). The page shows a number of locations available for rent in a Danish postal district, and allows you to select more postal districts – adding more locations to the map and the list – and to filter the locations by both size and price, thus limiting the number of shown locations. Furthermore any location can be added to the “shopping cart”, and behind the scenes all changes of postal districts and filters are reported back to the server for tracking purposes.

The initial javascript driving the page was developed interchanging by me and another developer on the fly as more features was added to the page. It is one of the most important pages on the site, so it has been through many iterations in attempts to both improve usability and optimize business goals. After almost 2 years in production, the javascript for the page reached a complexity level where it started to seemingly make its own decisions about when to do what, and older browsers and slow computers started to have problems handling the page as more and more locations was added. We decided to drastically refactor the javascript, and I realized that an event-driven approach was what we needed to handle all the complex interaction between the different components of the page.

Continue reading

AJAX sign in and sign up with Devise

I would never recommend a client to have login and registration in “pop-up” dialogs instead of plain pages, but sometimes clients choose to kindly ignore my well meant advise and ask me implement such things anyway. I’ve just finished version 1 of an upcoming web application implemented with Rails 3 and – of course – Devise for authentication, and this app just happens to have sign in and sign up taking place in dialogs (or overlays) and submitted to the server via AJAX. I expected this use of Devise to be pretty common use case, but the implementation turned out be pretty tricky.

Devise is a pretty amazing authentication system. It’s modular, flexible, highly configurable and lots of extensions have already been built. It does, however, make the assumption that you want to redirect the user to a new page after he has been authenticated. When sign in takes place in a dialog that is submitted via AJAX, a redirect to the frontpage or somewhere else is not of much use. In this case we need to respond with a javascript snippet that either makes a client-side redirect, or – better yet – simply closes the sign in dialog and updates any elements on the page that depends on sign in status.

For this particular web application, the scenario was even more complicated. When an unauthenticated user wanted to comment on something, the sign in box would have to pop up in a dialog. If the user wasn’t registered with the site, he could click a link to get the sign up shown – still in the same dialog. Whether the user registered or just signed in, the dialog should finally display the form for writing a new comment. All this would have to take place through AJAX without the actual page location ever changing, and here is how I implemented it.

Continue reading

Getting started with JRuby on Rails on OS X

I’ve been an independent web developer for over a month now, and I am enjoying every moment of it! If the first step in the liberation of programmers is getting Java- or .NET-free, the second step must be to get employer-free. Of course, being an employee has many benefits and doesn’t hold much risk (especially not if you live in one of these countries where it is practically impossible to fire people, such as Sweden or France), and being independent doesn’t mean – at least not yet for me – that you don’t have to do boring or tedious work.

But it does mean that any time during work hours where I am not doing work for a customer is my own time, and on my own time I get to decide what to work on. I am building a product during these free hours, and while I’d like to hold the details a bit longer (“don’t tell – show!” someone smart has said), I can say that it is a Ruby on Rails application allowing manipulation of PDF documents. Ruby has some decent PDF libraries, and Prawn holds a great potential, but none of these allow me to manipulate existing PDF documents.

The Java library iText is capable of doing so, and so is the .NET port iTextSharp, but would I really have to build some kind of web service in one of these forsaken frameworks? I was complaining about it to a friend, and promptly asked me: Why don’t you build it in JRuby? The more I thought about it, the more this seemed to be the perfect excuse for trying out JRuby, and so I set out to build my first ever JRuby on Rails application. It also helped that I got a free OpenSolaris/Glassfish VPS from Sun and Layered Technologies.

Continue reading

Keeping git repositories on Dreamhost using SSH

“is bemused/awed by how fast svn became a legacy technology in ruby community/developers” Dr. Nic recently said on Twitter. It is true. Greatly aided by Geoffrey Grosenbach’s screencast on git, I myself is starting to feel comfortable enough with git to start abandoning subversion altogether.

Github is great, but there is really no reason to pay for private git repositories unless you need the added functionality. I have a Dreamhost account that I am happy with, so why not use that for my private git repos? It is easy to do through SSH, now that git is installed on all Dreamhost servers, but it is not that easy, so I thought I’d better document it here for my own future reference.

(This stuff is tested on Mac OSX, and should work fine for *nix users. Windows users will have to do some workarounds, but can use this as a reference point.)

Continue reading

IE on Mac without Parallels/VMWare

IE6 on Mac

Benjamin Quorning gave a great tip at the Copenhagen Ruby Brigade mailing list the other day: How to run (Windows) Internet Explorer on your (Intel-based) Mac without having to boot up Parallels, VMWare, or any other kind of time-consuming PC-emulation software. This is made possible by the IEs 4 Linux project (no, that’s no IE 4 on Linux, it’s IEs for Linux, and IE 4 is not supported, just 6, 5.5 and 5) which provides a simple way to run IE on Linux and, as it turns out, OS X on Intel-based Macs.

While the article on the IEs 4 Linux provides one method for getting this up and running, I tend to like Benjamin’s more as it uses MacPorts, so I’m going to repeat it here for reference. A prerequisite for the tutorial is to have X11 installed, which is part of the optional developer tools that comes with OS X, and you also need MacPorts, which seems to be the best package system for Darwin at the moment.

To install IEs4Linux and its dependencies, execute these commands in your terminal of choice:

sudo port install cabextract wget wine
wget http://www.tatanka.com.br/ies4linux/downloads/ies4linux-latest.tar.gz
tar zxvf ies4linux-latest.tar.gz
cd ies4linux-*
./ies4linux

The first line installs several components required to run IEs4Linux, most importantly Wine, a framework allowing many Windows applications to run on Unix-based systems, including OS X. The other lines download and start the impressively user-friendly installation of IEs4Linux. After completing the installation, Benjamin explains that to run Internet Explorer, you must startup the X11 console (/Applications/Utilities/X11.app) and execute these commands:

export PATH="/opt/local/bin:/opt/local/sbin:$PATH"
~/bin/ie6

That’s a bit too inconvenient for my taste, since want to be able to place a link to IE directly in my Dock, or run it by executing a simple command in Quicksilver. So I have created a shell script in my home directory (you could also place it in the Applications directory if you like that better) called ie6 with the following contents:

#!/bin/sh
open-x11 .ies4linux/bin/ie6

I also need to make it executable by running chmod +x ie6 in the terminal. Now this gives me the ability to execute the shell script from terminal, to call it from Quicksilver (by writing ie6), and to drag it to the right/lower part of the Dock (the part with the trash can in it) with an ugly generic document icon. I want it in my Dock with a nice high quality Internet Explorer icon so I can start just like any other application, and for that purpose I wrapped the shell script as an application:

Download IE6 application

  • Requires IEs4Win to be installed in the default location (~/.ies4win)
  • Must be dragged to the Applications directory in your home directory (create one if you don’t have one), not to the general Applications directory (this is due to my limited shell scripting / X11 abilities, ~ didn’t seem to work as a reference to the home directory in X11).

Inside Rails Engines

Rails Engines are small subsets of an application that can be dropped into any of your Rails applications and handle common parts of the application from scratch. The title might be a bit misleading, since the technical side of this article is really a beginner’s introduction to Rails Engines spiced up with a few tips and tricks. I’m not diving into the inner workings of engines – the “inside” part of the title is more aimed against the fact that I’ve – out of pure curiosity and as a preparation for this article – asked the author of the engine plugin and the first and still most popular engines; James Adam, a few questions about his thoughts behind the engines and which direction he wants them to go in.

What is an engine?
There are two aspects of Rails Engines: There’s the engine plugin, a standard Rails plugin that you need to install as any other plugin. This plugin enables you install the individual actual engines that you want to use – the engines are also seen as standard plugins from Rails’ point of view, but they won’t work without the engine plugin.

An engine works by allowing a large part of the standard Rails application structure (that is; the /app directory in your projects) to exist as a part of the engine. Where a normal plugin only compromises Ruby code (often core extensions and helper classes), an engine are capable of having controllers, views and models that behaves like they are situated in the “real” /app directory.

This allows you to reuse a lot of traditional support functionality such as authentication, authorization and user management, a wiki, a shopping basket, a blog, a CMS and so on. Several engine implementations of some of this functionality already exist, most of which can be found through Rails-Engines.org, and while the wonders of CSS can get you a long way in getting these engines to fit into the design of the rest of your app, you will almost certainly want to change some things. Enter Rails Engine’s biggest advantage: The ability to override individual views and controller actions on a pr. need basis.

Let’s say you want to add some text and images to the login view of the Login engine, because this action effectively will function as your frontpage. All have to do is to copy the view from the /app/views directory of the engine into the corresponding directory in your own views directory – and through the magic of the engine plugin, this view now overrides the view that came with the engine. Often you’ll also need to modify the behavior of various actions supplied by the engine – you do this simply by creating a controller with the same name as the controller in the engine with action you want to override in your own /app/controllers directory, and define the actions in the controller. The engine plugin is able to combine the controllers of the engine with the ones in your app, so you can both override actions already defined by the engine, and you can add actions to a controller defined by the engine.

When should you use an engine?
While it is indeed very convenient to be able to drop all this functionality into your app without writing any code your self, you should be aware that this ability is not the primary goal with the original engine plugin, and that many people sees a lot of potential problems in constructing an application from one or more engines. James Adam explained it like this to me in an email:

Rails and Ruby make developing applications very easy, so there’s very little reason why a competent developer couldn’t write every part of the application that they need, and not rely on any code from outside. Working in this way has significant benefits, because it puts you in a position where you intimately understand exactly how your application works. There are no mysterious black boxes.

So when should you use an engine? James’ original intention with Rails Engines, and the way he continues to use them himself, is by abstracting commonly used application “chunks” so they can be reused in his company’s applications:

Where I work, we are working on a varying collection of fundamentally similar applications, all at the same time. They don’t have widely different requirements in terms of their basic architecture (authentication, importing Excel data, reporting back, loading and storing data and so on…), so it makes sense that we only maintain a single version of each of these shared aspects. “Enterprise DRY”, if you like. This is why engines exists; we wrote the engines plugin to make it possible for use to reuse as much of this shared code as made sense in our situation, in a manner that was easy to maintain where generators aren’t, but easy to override when the situation required it.

As for myself, I gladly use the Login, User, Riki and Substruct engines in several applications, and while I cannot claim that it haven’t taken an effort to integrate the engines into the application, I’d still say that it has saved me a considerable amount of time – especially when I’m reusing an engine that I already know well. I guess the ultimate DRY-proof solution would be to abstract my own versions of these engines – probably not to share with others, but use in my own projects working just the way I want them.

Implementing the Login and User engines in your application
Now to the more tutorial-ish aspects of this article. In this section, I’ll explain how to implement two of the most commonly used engines in your application. I expect you to have a running Rails application with a functional database connection. I also suggest that you setup a Subversion repository so you can add the plugins as externals, but it is not strictly necessary, just DRY’er.

  1. Install the Engine plugin

    1. Setup an SVN external attribute to point vendor/plugins/engines to http://svn.rails-engines.org/engines/tags/rel_1.1.3/ (or just download the files to that directory).
    2. The engine plugin is automatically loaded by Rails, and nothing visible happens until you install some engines. However, if you are running engines on Edge Rails, you should add this to the very top of config/environment.rb:
      # environment.rb
      module Engines
        CONFIG = {:edge => true}
      end
      
  2. Install the Login and User engines
    1. Setup SVN external attributes to point vendor/plugins/login_engine to http://svn.rails-engines.org/login_engine/tags/rel_1.0.2/ and vendor/plugins/user_engine to http://svn.rails-engines.org/user_engine/tags/rel_1.0.1/.
    2. Create two new migrations; login_engine_schema and user_engine_schema, and copy the contents of the migration(s) in the db/migrations of each engine into each of the new migrations. This way, you can still create the entire database structure with the rails migrate, without the need for running specialized engine tasks.
    3. Add the required configuration and startup code to config/environment.rb. The configuration is well documented in the read me files, so I won’t dive into that here, but instead provide a sample of my setup:
      # environment.rb
      
      #####################################################
      # Engine setup
      #####################################################
      
      module LoginEngine
        config :salt, "not_my_real_salt"
        #...
      end
      
      module UserEngine
        config :admin_login, "admin"
        #...
      end
      
      Engines.start :login, :user
      
      UserEngine.check_system_roles
      Permission.sync rescue false # Ignore any errors here
      
    4. Add code to application.rb in order to add user authorization to all actions, and to make the user-logic available to helpers and models:
      # application.rb
      
      require 'login_engine'
      require 'user_engine'
      
      class ApplicationController < ActionController::Base
      
        # Login and User Engines setup
        include LoginEngine
        include UserEngine
        helper :user
        model :user
        before_filter :authorize_action # unless RAILS_ENV == 'test'
      
      end
      

      (Be sure to also include Login- and UserEngine in application_helper.rb to make support available to the views.)

  3. Override views, actions and models as needed
    • A view is overridden by creating a view with the same name in your own app-structure - not by modifying the view directly in the engine. For example; if you want to override the template for the list action of the user controller, simply create the file list.rhtml in /app/views/user/, and this file will be used.
    • An action is overridden by creating the controller the action belongs to, and defining a function with the same name. For example; if you want to override the list action of the UserController to provide additional data to your list view, you should create the user_controller.rb file in /app/controllers/ and define the action:
      # user_controller.rb
      
      def list
        # ...
      end
      
    • Overriding a model is a bit more complicated, since the engine plugin has no clever way of supporting this due to various reasons. However, in the Login- and User engines, it is possible to extend the User-model because it is implemented as a namespaced module, which can be included in your own model-file. So if you want to associate a user with, say, a log entry, you can create the file /app/models/user.rb with this code:
      # user.rb
      
      class User < ActiveRecord::Base
        include LoginEngine::AuthenticatedUser
        include UserEngine::AuthorizedUser
      
        has_many :log_entries
      
      end
      

Tips and tricks
Many people complain that it is hard to test your application with authentication and authorization enabled. The easy solution is to add unless RAILS_ENV == 'test' to the before_filter :authorize_action line in application.rb. The better solution is to actually have a loaded user during the tests, since this is what the application generally expects. One way to solve this is to put this in your test case:

# /test/fixtures/companies_controller.rb

  def setup
    @controller = CompaniesController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
    @request.session[:user] = User.find(1)
  end

Another issue the synchronization of the permissions data for the User engines authorization logic. I'm not entirely happy with the way this work, since the Permission.sync done on system startup tends to fail, which is why I've had to add rescue false to ignore any errors.

Some final thoughts
Should the standard Rails plugins go in the direction of engines? I asked James Adam this very question, and here is what he answered:

Yes and no. Some things that I feel should be easier in plugins:

  • Managing stylesheets/javscripts/etc in plugins. The engines plugin makes this trivial, and I'll be working on adapting the implementation of this feature so it seems natural in any plugin.
  • Sharing views in plugins. While you can do that with a plugin (overriding a controller's template_root), that seems like a bit of a kludge. I'd like to see a 'load_path' for views.
  • Controlling whether plugins are loaded or not. This is handy for development, and as a side effect, you get control over the plugin load order.

What shouldn't be a part of the default plugin system:

  • Overriding aspects of controllers, helpers and views automagically. This behavior is significantly different from that way that Rails works in a normal situation. Because of this, users should explicitly 'ask' (by installing/creating engines-based plugins) for this behavior, so they know what to expect. This is really the significant addition that engines add beyond what might seem natural for a plugin anyway.

Thank you for Rails Engines, James, and keep up the good work!

Additional resources

Deploying Rails with Edge and Engines to Dreamhost using Capistrano

It’s not that I’m the first to describe the process of deploying a Rails application, in fact; it’s rather well-documented, also when it comes specifically to Dreamhost. It’s just that I have a strange combination of circumstances that none of these articles cover, and also; I know almost nothing about Unix-based systems – I don’t even have a Mac. I am one the of many Microsoft-developers who are starting to see the light, and because of that, I need to start entirely from scratch when it comes to understanding the whole Linux/Apache/open-source universe.

(Take me straight to the solution, please)

My strange combination of circumstances
The Rails application I’ve had to learn to deploy the hard way has this configuration:

  • Dependent on Rails 1.1.2
  • Uses Login and User Engine.
  • Build for MySQL (so no problem there)
  • Must run with FastCGI, or it’s too slow
  • Developed with RadRails on Windows XP (yes, this makes a difference)
  • Resides in a Subversion repository

If you can live with Rails 1.0.0, if you don’t use Rails Engines, if you don’t need FastCGI and if you know about Linux, you are probably better off using shorter and simpler tutorials, because these where my specific problems, and what I am going to dvelve into here.

Linux basics
Although it is possible to deploy Rails to a Windows server (and presumably not much harder if you can use Apache instead of IIS), Dreamhost, and all other commercial hosts supporting Ruby on Rails, are using Linux servers. You can develop your entire Rails application completely unknowningly about Linux, but when it gets to deployment you have to learn the basics about this strange operating system:

  • You don’t use Remote Desktop, you use SSH. Remember DOS? When you connect with SSH, you get a text prompt simular to that, and you need to know some basic commands. I recommend using PuTTY for SSH.
  • Use pwd to print you current directory.
  • Use ls to print the contents of the current directory.
  • Use cd (e.g. cd /home/user/) to move into a directory.
  • Use vim (e.g. vim environment.rb) to quickly view and edit files directly on the server. Press your INSERT button to enable editing, and press ESCAPE, then write :wq to save and exit the file.

Now, in a perfect world (see below) you actually shouldn’t have to know this, because Capistrano would do all the dirty work for you, but let’s get real: It’s just not that easy.

In a perfect world
Here is a quick recap of what you would be all needed to do, if the world was perfect or you are extremely lucky and everything works as expected

  1. Now, I expect you have already created MySQL database on Dreamhost and entered the connection details into config/database.yml – otherwise; start out with that.
  2. Create a new fully hosted domain in the Dreamhost panel, and make sure it is configured like this:
    Dreamhost Rails setup
    • FastCGI Support enabled
    • The user has shell access of the type /bin/bash/ (configurable from the Manage Users page)
    • The web directory points to [yourdomain.com]/current/public (not just [yourdomain.com]/public, since we want to use Capistrano)
    • (The www option is up to you)
  3. SSH to [yourdomain.com] and remove the current directory (containing the public directory) Dreamhost has automatically created. (Capistrano needs to create this as a symbolic link later.):
    # On your Dreamhost server
    [nimitz]$ pwd
    /home/cape
    [nimitz]$ cd myrailsapp.com/
    [nimitz]$ ls
    current
    [nimitz]$ rm -r current/
    [nimitz]$ ls
    [nimitz]$
    • Start PuTTY, enter [yourdomain.com] as Host Name and click Open.
    • Login with the user you specified when creating the domain
    • Change to the directory of your Rails application (cd [yourdomain.com])
    • Remove the directories (rm -r current)
  4. Download Geoffrey Grosenbach’s Capistrano script, add it to the /config/ directory of your Rails application, and edit it to reflect your setup:
    # In config/deploy.rb
    set :user, 'cape'
    set :application, 'myrailsapp.com'
    set :repository, 'http://svn1.cvsdude.com/...'
    set :svn_username, "casper"
    set(:svn_password) { Capistrano::CLI.password_prompt }
    • :user must match the user you specified when creating the domain
    • :application must be the domain you created
    • :repository must be the url of your Subversion repository for the application, from where Capistrano will grab the code to deploy.
    • :svn_username only have to be present, if your subversion username is different from your Dreamhost shell username.
    • set(:svn_password) { Capistrano::CLI.password_prompt } tells Capistrano to prompt you for your subversion password. This might not be nescessary, if your Dreamhost user is already in a trust relationship with the Subversion server.
  5. Edit public/.htaccess and change the line RewriteRule ^(.*)$ dispatch.cgi [QSA,L] to RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]. This tells Apache which file it should execute when a request comes in.
  6. Edit public/dispatch.fcgi and change the first line from #!c:/ruby/bin/ruby (or something simularly Windowish) to #!/usr/bin/env ruby. This line is called a shebang location and tells Linux where to find the program that are able to execute this file, in our case; this is ruby.
  7. Edit config/enviroment.rb and incomment the line: ENV['RAILS_ENV'] ||= 'production'. Dreamhost says they set this enviroment variable automatically the nice way when using FastCGI – in my experience, they don’t. This means you have to incomment the line every time you release, and outcomment it again the develop in the development environment – in my final deploy.rb I have a much cleaner solution to this problem, so stay tuned.
  8. Open up a Command Window, move into the directory of your Rails Application and run the command rake remote:exec ACTION=setup. (You will need to type your password for the user you specified when creating the domain)
  9. Run rake deploy. If you are really, really lucky, this will actually do the job for you, and you can browse to your application. If you are not, go on …

Finding out what’s wrong
I’m going to assume that the steps above sort of worked for you, such that Capistrano was actually able to setup the server and copy the files to the correct directory, but it probably failed by the end of the rake deploy command, because it didn’t have the permissions to restart the web server. So now when you go to [yourdomain.com] in your browser, you don’t get a “Page not found”, you get a “Rails application failed to start properly” after a looong wait.

Since the “Rails application failed to start” message is not very information, I am going to start out by giving you a few tips about how to diagnose your failing Rails application. You should be able to distinguish between to scenarios:

  1. Your Rails application is not able to run, probably because it can’t connect to the database or can’t locate some files
  2. The application can run, but the FastCGI link doesn’t work, so pages cannot be served

It’s easy to test for the first scenario; just SSH to the server, cd to the directory of your app (cd /home/user/[yourdomain.com]/current/), and run the command ruby script/console production. This attempts to start your Rails app in production mode, and any error messages will be right there on the screen for you.

The second scenario is in fact also pretty easy to test, at least under the assumption that Apache is able to redirect to “dispatch.fgi” (but it wasn’t, you probably wouldn’t get the “Rails application failed to start properly” error). By running ruby public/dispatch.fgi you actually invoke the same file as the web server, which will often give you handy information.

Once you application is running, you can also get useful debugging information from the log files in the logs directory, but if your Rails app is actually writing to these, you probably have something that are pretty close to work.

Fixing deploy.rb
As I have hinted, I had to make a couple of changes to Geoff’s “shovel” deploy.rb in order to make it run smoothly:

  1. To be able to restart the FastCGI-processes in the :restart task, I had to add ruby to the line that restarts, because the reaper-script that restarts is not executable on Dreamhost. So my :restart task now looks like this:
    # In config/deploy.rb
    task :restart, :roles => :app do
      run "ruby #{current_path}/script/process/reaper --dispatcher=dispatch.fcgi"
    end
  2. To make Apache able to actually execute dispatch.fcgi our deploy.rb also needs to run a command makes dispatch.fcgi executable. On Unix-based systems, any file can be marked as executable, and the OS will then read the shebang location when the file is invoked. By inserting the task below, dispatch.fcgi will be made executable each time you make a deployment. By naming the task after_symlink, it will be executed after the symbolic link has been moved to point to your new files – first by then, the current_path variable is available.
    # In config/deploy.rb
    task :after_symlink, :roles => [:web, :app] do
      # Make dispatcher executable
      run "chmod a+x #{current_path}/public/dispatch.fcgi"
    end

Rails in the /vendor directory
It’s supposed to be so easy to use a different version of Rails than the one installed on your host. Just run rake rails:freeze:gems – or even better: Set /vendor/rails to point to http://dev.rubyonrails.org/svn/rails/tags/rel_X-X-X/ (depending on your prefered version) using the svn:externals feature of Subversion. However, strange things can happen to your application, once all the core files of Rails are suddenly supposed to be read from the /vendor/rails directory. I had to make three crucial changes to avoid various “required file not found” or “NoMethodError” messages after I “froze” Rails:

  1. Move the inclusion of files in config/environenment.rb down to the bottom of this file. For instance; I have require 'taggable' in my environment.rb, and before I “froze” Rails it I just had this line at the top without any problems, but after, it suddenly couldn’t find the taggable stuff, and it only worked when I moved that line down after the whole Rails::Initializer.run do |config| chunk.
  2. Force public/dispatch.fcgi (the file that runs the show) to use the “frozen” version of Rails, by replacing the line require 'fcgi_handler' in dispatch.fcgi with this line:
    require File.dirname(__FILE__) + "/../vendor/rails/railties/lib/fcgi_handler"
  3. Unfortunately, we also need to edit a file inside the Rails framework itself, putting in the absolute location of a required file instead of just the name of the file, as described in this post. However, if you use svn:externals like I do, you can’t just alter a file in vendor/rails, since you don’t have any commit rights. Furthermore, the location of the line we need to add is specific to our setup on the host, so it would be baaad to hardcode it. That’s why I came up with a solution letting the deployment script replace this line on the server using the current_path variable available. You could do this with ruby, but I asked one of my hardcore Linux geek friends to write a one-liner that I could just run, and he chose to let Perl make the replace directly in the file for us. This also happens in the after_symlink task:
    # In config/deploy.rb
    task :after_symlink, :roles => [:web, :app] do
      # Ensure Rails in the vendor dir is used by replacing a line in fcgi_handler.rb
      run "perl -i -pe "s/require 'dispatcher'/require '#{current_path.gsub(///, '\/')}\/vendor\/rails\/railties\/lib\/dispatcher'/" #{current_path}/vendor/rails/railties/lib/fcgi_handler.rb"
      ...
    end

Rails Engines
Rails Engines is a brilliant way of creating “super-plugins” that acts like small sub-applications inside your application, but where everything can be extended or overriden – even views! If you don’t use engines, this small section is irrelevant for you, but I’d recommend you taking a look a them – I love them.

There is really only one thing you need to be aware of when you deploy a Rails application to Dreamhost that uses engines and has Rails in the vendor directory, and that is to put this code at the very top of your environment.rb:

# In config/environment.rb
module Engines
  CONFIG = {:edge => true}
end

One other thing, not really related to deployment: As I am writing this, the LoginEngine has a problem loading two files in its init_engine.rb, so if you get errors in this file, try replacing the two original require statements with this:

# In vendor/plugins/login_engine/init_engine.rb
require 'login_engine/authenticated_user'
require 'login_engine/authenticated_system'


Wrapping it up: The complete solution
Today, I am able to run rake deploy and it actually works. My deployment script for Capistrano, based on Geoff’s shovel, can be downloaded here. Notice that this script, besides the tasks described above, also automatically replaces #ENV['RAILS_ENV'] ||= 'production' with ENV['RAILS_ENV'] ||= 'production' (incomments it) in config/environment.rb to force production environment on the Dreamhost server.

Here is a complete list of files I’ve uploaded for your reference:

I had to rename some of the files in order to let them be downloadable, but the link listed above has the correct name and the directory the file belongs to.

Please note: You can’t just dump these four files into your own Rails application and expect things to work. You have to carefully extract the pieces from each file you think you need in order to get your application up and running.

Good luck!


Recommended ressources

Getting started using Subversion on Windows

Subversion is a brilliant piece of open-source software for version control. It is the heir of the renowned CVS and suprior to the infamous SourceSafe in every way. This tutorial is not about running a Subversion server – although it is easy and free – but about using Subversion for easy collaboration and version control in Windows.

What is version control?

Version control is basically about storing different versions of the same files, which enables you to go back previous versions in case you mess something up. Since the files are usually stored on a central server – often, but not necessarily, accessible from the internet – a nice side effect of version control is that it enables several people to work with the same set of files simultaneously, by letting everyone syncronize their files with the server.

What is a repository?

Remember the central server running Subversion? This is where the repositories is located. Each repository is a unique and seperate collection of files with a forthrunning version number. You usually create a new repository for each new project you choose to version control, but in case you can’t just create new repositories, there is no problem in grouping several projects in the same repository.

I assume that you already know two things: The url of the Subversion repository you want to work with, and the username and password to use with it. If not, feel free to expirement with (but not abuse) a test repository I have setup for this tutorial:

TortoiseSVN – making Subversion easy

Downloading TortoiseSVN

Your first step is to install TortoiseSVN; a free open-source client for working with Subversion in Windows, which integrates seamlessly with Windows Explorer. Go on; download and install the latest version right now! (Select the TortoiseSVN-X.X.X.XXXX-svn- X.X.X.msi file.)

Once installed; start Windows Explorer or open My Computer from your desktop and create a folder a place where you would like to place your first repository – I usually keep mine in “C:Projects”. Right-click on the folder (or in the “white space” inside it) to discover two new items in your context menu: “SVN Checkout” and “TortoiseSVN”. Select to “SVN Checkout” to make the folder your local working folder for the files in the repository. Enter the url of the repository you want to use, or use “http://svn.casperfabricius.com/sandbox/”. Enter your username and password (both are case-sensitive) or use test as both if you are checking out my test repository. I recommend that you check the “Save authentication” box, unless you are not using your own computer. I might encounter the message saying “Error validating server certificate …” during the process, if the repository is using SSL. It’s not a problem at all, just select “Accept Permantly” and go on with the tutorial. TortoiseSVN will now download any files in the repository to the folder, and add several new items to the context-menu, enabling you to syncronize with the Subversion repository. Your are ready to start using the repository!

1.
Checkout step 1
2.
Checkout step 2
3.
Checkout step 3

Commit and update – your two basic commands

Basically, the point with Subversion is all about sharing your changes with others, and in turn getting their changes reflected in your local working copy of the repository. When you upload you files to the repository on the central server, you are in fact – in Subversion slang – commiting your changes. Every time some one commits a change, the Subversion server creates a new version of the repository. Not that it copies every single file in the repository each time a change is commited, but it creates change sets which enables the server to produce an exact copy of the repository in any given version. Even deleted files still exists in previous versions, so once you have commited something, you can always get it back later, no matter what changes other people make.

So how do you actually commit files? You right on the folder or inside the folder with the files you want to commit, and select “SVN Commit” from the context menu. This brings up an overview of all the files you have changed and new files that has not yet been added to the repository. You must actively check the box for new (non-versioned) files to get added and committed to the repository. You don’t have to add all files in the folder to the repository, actually; you should make sure that generated files – such as dll-files genereated from code files – are not added to the repository.

1.
Commit step 1
2.
Commit step 2
3.
Commit step 3

Updating – as you have probably guessed by now – is simply a matter of selecting “SVN Update” in the context menu and letting magic happen.

Merging and conflicts – two people; one file

But what happens if two people make changes to the same file? The scenario goes like this:

  1. Bob and Alice both change helloworld.txt
  2. Alice commits her version of the file, unknowingly that Bob has also made changes
  3. Now Bob commits his version of file, but get’s an error message; his file is out of date
  4. Bob fixes this by updating his local working copy, and most likely; Subversion is able to merge his changes automatically with Alice’s changes.
  5. If Subversion cannot merge the changes; a conflict occurs.
  6. Bob now needs to navigate to the conflicted file, select “TortoiseSVN > Edit conflicts” and the context menu for the file, manually merge the two files using the build-in program, and mark the conflict as resolved.
  7. Bob are now able to commit his version of the file, which contains both his and Alice’s changes.
  8. The next time Alice update, she gets Bob’s merged file and everyone is happy
1.
Conflict step 1
2.
Conflict step 2
3.
Conflict step 3

Why does it work like this? Why aren’t the files “locked” so only one person can edit a file at the time? Well, for one thing; this way everyone in a team can work unbothered and even offline on the same set of files, and Subversion will (mostly) be able to merge the changes. If you are used to SourceSafe, it will probably take you a bit of time to get used to the idea, but it is – in my opinion – by the best way to work. Embrace merging and even conflicts – they are always easily resolved. If you can’t; Subversion also supports locking, but that’s another story.

One last thing: Subversion can’t (by default) merge binary files. It’s not a problem storing Word-documents, Visio-diagrams, Photoshop-images etc. in a Subversion repository, but once a conflict occurs; you are on your own.

Rearranging – renaming, moving and deleting files.

In time; your repositories grow big and ugly, and you’ll want to rearrange or clean up the mess. When doing this; it’s important to be aware that you can’t just rename, move and delete as you usually do it in “My Computer” or Windows Explorer. Well, you can, but Subversion won’t know it, and will consider a renamed or moved a new file, while restoring the file with the old name in it’s old location on your next update.

For this reason, you should always use the “Rename” and “Delete” commands in the “TortoiseSVN” sub menu in the context menu. This also applies to folders. Also, if you want to move a file to another folder in the repository, you should drag it with right mouse-button and drop it on the folder you want to move it to. This will open a context menu, and when you select “SVN Move versioned files here”, TortoiseSVN will make all the dirty work for you, moving the file to it’s new location.

Rename and delete
Moving a file

The result of sticking to using the rename, delete and move command is that the files will automatically renamed, deleted and moved in other peoples local working copies once they update.

How do I get my own Subversion repository?

If you know me personally, I can probably be persuaded to create a repository for you. If you have our own server, or access to one, you can install Subversion following the instructions on http://subversion.tigris.org/.

Otherwise, there are plenty of companies that offers to fullfill all your Subversion needs. I can recommend these two, since I use them my selve:

Conclusion

I could go on for long about other features of Subversion and TortoiseSVN, but with this; the most basic and important commands and functionality are covered. Happy versioning!

Read more: