Ruby on Rails

Ideal setup for Ruby on Rails on Windows (Vagrant + Guard + Spring)

If you’re developing Ruby on Rails applications in Windows, you’ve probably found that tests run really slowly in the Windows environment. The only supported system to speed up tests is Spork and this hasn’t been updated in about a year or so. The ideal setup for any Windows developer is to develop in your host machine and test in a virtual machine. Vagrant is ideal for  this purpose.

Note: These instructions were written for a Ruby on Rails 4 application. If you are still developing Ruby on Rails 3 applications, the simplest way to get up and running is RailsInstaller.

Install Virtual Box and Vagrant

  1. Download and install the latest version of VirtualBox (Vagrant depends on VirtualBox)
  2. Download and install the latest version of Vagrant for Windows.

Clone the chef-rails-dev-box repository

  1. Download Git for Windows if you haven’t already.
  2. Clone chef-rails-dev-box using “git clone https://github.com/AppMaintainers/chef-rails-dev-box.git” to a directory on your machine (I like to install it in the root of my C drive).

Get ready to build and start your virtual machine

  1. Download and install the latest version of Ruby 1.9.3.
  2. Download and install the latest version of RubyGems.
  3. Run ‘gem install rubygems-update’.
  4. Download and install the latest DevKit.
  5. Modify your PATH environment variable so that you can run ruby and gem directly from your command line.
  6. Run ‘gem install bundler’.
  7. Build your virtual machine using the instructions from https://github.com/AppMaintainers/chef-rails-dev-box.git.

Set up the database (PostgreSQL)

I like running the development web server on the host machine (for reasons mentioned below). This means that you need to install PostgreSQL on your host machine.

  1. Download and install PostgreSQL.

Once you do so, you need to create the development and test users and database on the virtual machine. This can be quite tricky:

  1. Make sure that PostgreSQL is running with ‘sudo service postgresql restart’.
  2. Before you do anything else, make sure you follow the instructions here in order to make the default encoding of your databases UTF-8.
  3. Run ‘sudo su – postgres’.
  4. Run ‘createuser <name_of_user> -P -d’ to create a user. You will also be asked to immediately set the user’s password as well.
  5. Run ‘psql template1’.
  6. Run ‘CREATE DATABASE “<name_of_database>” OWNER <name_of_user>’ to create the development database.

Edit your pg_hba.conf file to look like this. As you can see I have the development and test databases set up to be authenticated via md5:

local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
host all all 10.0.0.2/24 trust
local indieinfinity-development indieinfinity md5
local indieinfinity-test indieinfinity md5

Set up continuous (and fast) tests

Finally, we are getting to the whole point of this setup: continuous (and fast) tests.

Currently there are three main solutions for running tests continously:

  1. Spork: There has been no development on this project for nearly a year now.
  2. Zeus: Zeus does not seem to currently work with Vagrant on Windows.
  3. Guard + Spring: This is the ideal solution when using Vagrant on Windows.

In order to get started with Guard + Spring:

Add the following code to your Gemfile:

group :development, :test do
  gem 'minitest'
  gem 'rspec', '~&gt; 3.0.0'
  gem 'rspec-rails', '~&gt; 3.0.0'
  gem 'spring'
  gem 'spring-commands-rspec'
end

group :guard do
  gem 'guard'
  gem 'guard-rails'
  gem 'guard-rspec', '~&gt; 4.2.7'
end
  • Run ‘bundle install’ in the root of your project.
  • Run ‘bundle exec spring binstub –all’.
  • Run ‘sudo gem update –system’ and ‘gem pristine –all’ in order to run spring efficiently.
  • Make sure that ‘bin/rspec’ works before you continue further.
  • Run ‘bundle exec guard -p’ in order to start Guard. -p specifies polling which is needed for this setup in order for Guard to detect changes to files.

My Guardfile

# A sample Guardfile
# More info at https://github.com/guard/guard#readme

guard 'rspec', cmd: 'bundle exec spring rspec' do
 watch(%r{^spec/.+_spec\.rb$})
 watch(%r{^lib/(.+)\.rb$}) { |m| &quot;spec/lib/#{m[1]}_spec.rb&quot; }
 watch('spec/spec_helper.rb') { &quot;spec&quot; }

 # Rails example
 watch(%r{^app/(.+)\.rb$}) { |m| &quot;spec/#{m[1]}_spec.rb&quot; }
 watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| &quot;spec/#{m[1]}#{m[2]}_spec.rb&quot; }
 watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| [&quot;spec/routing/#{m[1]}_routing_spec.rb&quot;, &quot;spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb&quot;, &quot;spec/acceptance/#{m[1]}_spec.rb&quot;] }
 watch(%r{^spec/support/(.+)\.rb$}) { &quot;spec&quot; }
 watch('config/routes.rb') { &quot;spec/routing&quot; }
 watch('app/controllers/application_controller.rb') { &quot;spec/controllers&quot; }

 # Capybara request specs
 watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| &quot;spec/requests/#{m[1]}_spec.rb&quot; }

 # Turnip features and steps
 watch(%r{^spec/acceptance/(.+)\.feature$})
 watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join(&quot;**/#{m[1]}.feature&quot;)][0] || 'spec/acceptance' }
end

guard 'rails' do
 watch('Gemfile.lock')
 watch(%r{^(config|lib)/.*})
end

Troubleshooting

  • Update all gems: Make sure that all gems are updated to their latest version (Run ‘bundle update’).
  • Certificate issues: If you get an error like ‘SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (OpenSSL::SSL::SSLError)’, you need to follow these instructions.
  • Git permission issues: If you get an error like ‘Permission denied (publickey)’ or ‘Could not open a connection to your authentication agent.’ when trying to clone the GitHub repository, you need to add your key to ssh-agent. Run eval “$(ssh-agent -s)” and ssh-add ~/.ssh/id_rsa’ in a Git Bash command prompt.
  • Bundle install fails: Run ‘sudo bundle install’ instead.
  • CPU usage is at 100%: Run bundle exec guard -p -l 10 (Change latency to prevent 100% CPU usage). This introduces a latency to how often Guard polls your files to detect changes.
  • RubyMine’s autosave kicks in every time a change is made: http://stackoverflow.com/questions/11996124/is-it-impossible-to-use-guard-with-rubymine
  • Re-associate vagrant with an existing Virtual Machine: https://github.com/mitchellh/vagrant/issues/1755
Ruby on Rails

A guide to using Facebook OAuth on localhost for testing during development

Running your application locally on your development machine is vital for quick feedback and easy testing. If you are are using Facebook’s OAuth as your authentication mechanism, it might get a bit more complicated to set up your application to run locally. Here’s a handy guide to getting Facebook OAuth to work even when running your app on your local development machine:

Create a new App on the Facebook Developers website

  1. Visit the Facebook Developers website and log in
  2. Click on Apps in the main menu bar at the top and then click on “Create New App”
  3. For the App Name give it a descriptive name like “<App Name> – Development”
  4. Click on Settings > Basic in the menu on the left and then under the section “Select how your app integrates with Facebook”, you will see “Website with Facebook login”. Under this section fill in Site URL with “http://localhost:3000&#8221; (or whatever port you use in your setup)
  5. Make sure to Save Changes
  6. At the very top you will see your App ID and App Secret. These will be important for the next step.

Modify the code where you initialize the Facebook App ID and App Secret

Somewhere in your code (probably in an initializer), you’re setting the App ID and App Secret for your Facebook App. Change it to look like what’s given below. I’m using OmniAuth with Devise, but this technique will work with any other Facebook OAuth setup that you are using. Wherever you are setting the App ID and App Secret, change the code to switch out a different Facebook App ID And App Secret for the development machine.

if Rails.env == &amp;amp;amp;amp;amp;quot;development&amp;amp;amp;amp;amp;quot; || Rails.env == &amp;amp;amp;amp;amp;quot;test&amp;amp;amp;amp;amp;quot;
  config.omniauth :facebook, &amp;amp;amp;amp;amp;quot;App_ID (Development Facebook App)&amp;amp;amp;amp;amp;quot;, &amp;amp;amp;amp;amp;quot;App_Secret (Development Facebook App)&amp;amp;amp;amp;amp;quot;
else
  config.omniauth :facebook, &amp;amp;amp;amp;amp;quot;App_ID (Production Facebook App)&amp;amp;amp;amp;amp;quot;, &amp;amp;amp;amp;amp;quot;App_Secret (Production Facebook App)&amp;amp;amp;amp;amp;quot;
end

Troubleshooting

  1. If you get an error like “SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed”
    Macs – http://martinottenwaelter.fr/2010/12/ruby19-and-the-ssl-error/
    Windows – https://gist.github.com/867550
Uncategorized

A guide to getting the hg-git Mercurial plugin to work on a Windows machine

When you’re developing a Ruby on Rails application on Windows, you have to learn to deal with a lot of minor issues. I used Mercurial (Hg) initially as my source control. However when time came to deploy my application, I found out that Git would have been a much better choice. Both Heroku and Engine Yard make Ruby on Rails so easy to deploy that it would be crazy not to use them. However they integrate with Git and Mercurial support seems a long way off.

So I decided to convert my Mercurial repository to Git using the hg-git Mercurial plugin and ran into a lot of issues along the way. Here is a guide to successfully getting the hg-git plugin to work on a Windows machine:

Install TortoiseHg if you haven’t already

If you’re developing on Windows and using Hg, you probably already have TortoiseHg installed. If not, go ahead and download and install TortoiseHg. Make a note of where you install TortoiseHg, since you need to make some modifications in this directory.

Install the prerequisites for the hg-git plugin

We’re going to use the hg-git Mercurial plugin to allow us to pull from and push to any Git repository. This has a dependence on Mercurial (which is handled by installing TortoiseHg in the previous step) and dulwich which is a library that provides an interface to git repos using pure Python code.

However since you most probably don’t have Python installed on your Windows machine, follow these steps to “install” the dulwich library for use by the hg-git plugin:

  1. Download the latest source code for dulwich (version 0.4.0 or above) and unzip it to a temporary directory
  2. IMPORTANT: Read the note at the bottom of the post for troubleshooting. You might need to make a change to a file in the dulwich folder in order for it to work on Windows.
  3. Under the newly unzipped folder, you should see a directory called “dulwich” which contains all the Python code (you should see a bunch of files with the .py extension)
  4. In the installation directory for your TortoiseHg installation, you should see a zip file called library.zip. Copy the dulwich folder into this zip file in the root of the zip file.

Download the source code for the hg-git Mercurial plugin

Clone the repository at http://bitbucket.org/durin42/hg-git/ to a location on your hard drive, say C:\hg\hg-git

Setup .hgrc to use the hg-git plugin

Navigate to the hg repository on your hard drive that you want to convert to Git. Under the .hg directory, edit the hgrc file to contain the following three lines:

[extensions]
hgext.bookmarks =
hggit = C:\hg\hg-git\hggit

You need to point hggit in your hgrc file to point to the subdirectory called “hggit” located in the cloned repository (see step 3 above). This folder usually only contains Python code files (with a .py extension)

Pull and push from a Git repository

That’s it! Provided your current working directory is inside the hg repository that you set up, you should be able to pull from and push to any Git repository.

Troubleshooting

1. If you’re getting a error about a function called build_tree in index.py, you need to add the line  to the very top of the build_tree(path) method as follows. Once you’ve added this line, you can add the dulwich folder to zip file as in step 2:

def build_tree(path)
    path = path.replace (&quot;\\&quot;, &quot;/&quot;)

2. If you’re getting an error like “abort: The system cannot find the file specified”

  • Dulwich most probably cannot find ssh in your PATH. You need to make sure to install Cygwin’s OpenSSH and that you can run “ssh” from the command line.
  • Make sure that you are using the Git Bash shell as you work through this guide (Credit goes to SPR in the comments for this tip)

3. If you get “Permission denied (publickey)”, it just means that the public key required to access and push to the server cannot be found. To get around this we’re going to run the following commands:

ssh-agent
ssh-add &lt;full path to your key file&gt;
Ruby on Rails

Paginating multiple models using will_paginate on the same page

The will_paginate plugin makes pagination for your models in Ruby on Rails ridiculously simple. However sometimes you’ll find yourself wanting to paginate over two or more models on a single page. For instance, you might want to display a list of users and administrators on a single page along with a pager for each model (assuming that users and administrators are stored in separate tables).

Controller code

The code is pretty simple, except that I am specifying the page to show to be equal to params[:user_page] and params[:administrator_page] respectively. Since we are allowing the ability to page over two models, we need two separate parameters to determine which page of users or administrators to show.

@users = User.paginate(:page =&gt; params[:user_page], :per_page =&gt; 10)
@administrators = Administrator.paginate(:page =&gt; params[:administrator_page], :per_page =&gt; 10)

View code

In the view all we need to do is make sure to set the param_value to the correct value to indicate to the plugin that we want to use a different parameter name for the page. The default is simply called ‘page’, but we need to make sure to use ‘user_page’ and ‘administrator_page’ instead for the two different models.

&lt;%= will_paginate @users, :param_name =&gt; 'user_page' %&gt;
&lt;%= will_paginate @administrators, :param_name =&gt; 'administrator_page' %&gt;

That’s it, you should now be able to page through your users and administrators on the same page.

Uncategorized

Sample nginx (with Phusion Passenger) configuration file to enable SSL

Read my earlier post if you want Phusion Passenger to compile nginx with SSL support. If your nginx server already supports SSL, read on.

Phusion Passenger fills up most of the configuration in nginx.conf for you with a nice set of defaults. You just have to do a little more work if you want to modify the nginx configuration file to enable SSL on your site.

The first thing to do is purchase a SSL certificate and install it on your server. If you don’t know how, here’s a great post on installing SSL on Ubuntu with nginx. Once you’ve installed the certificate, you should be good to go.

Let’s say that you’ve got a domain name called mydomain.com and the root for your Ruby on Rails application is located at /home/mydomain/current/public on your server. The following shows a sample of the configuration required to get SSL enabled for your application:

server  {
    	       listen 80;
               server_name mydomain.com;
               root /home/mydomain/current/public;
               passenger_enabled on;
               rails_env production;
        }

# HTTPS server
server  {
               listen 443;
               server_name mydomain.com;
               root /home/mydomain/current/public;
               passenger_enabled on;
               rails_env production;

               ssl on;
               ssl_certificate /etc/ssl/certs/mydomain.com.crt;
               ssl_certificate_key /etc/ssl/private/mydomain.com.key;

               ssl_session_timeout  5m;
        }
Uncategorized

Getting Phusion Passenger to install nginx with SSL support

Phusion Passenger or mod_rails has taken away almost all the pain once associated with deploying Ruby on Rails applications. Phusion Passenger recently added support for the nginx web server.  My application required SSL support, but Phusion Passenger does not by default compile nginx with SSL support. I’m new to System Administration and even newer to Unix, having used Windows Servers all my life, so I decided to document my steps to make it easier for others with the same problem.

Download and unzip the source code for OpenSSL

Make sure to visit OpenSSL to determine the name of the latest source code tarball to download. In my case it was openssl-1.0.0-beta3.tar.gz

cd /tmp
wget http://www.openssl.org/source/openssl-1.0.0-beta3.tar.gz
tar -xvzf openssl-1.0.0-beta3.tar.gz

Download and unzip the source code for nginx

Make sure to visit nginx to determine the name of the latest source code tarball to download. In my case it was nginx-0.8.14.tar.gz

wget http://sysoev.ru/nginx/nginx-0.8.14.tar.gz
tar zxf nginx-0.8.14.tar.gz

Install and run Phusion Passenger

gem install passenger
passenger-install-nginx-module
  • Watch Phusion Passenger do its thing and when it asks you “Automatically download and install Nginx?”, answer 2
  • Specify the directory where you unzipped the nginx source code (/tmp/nginx-0.8.14 in my case)
  • Specify the directory where you want to install nginx to (/opt/nginx in my case)
  • When asked “Extra arguments to pass to configure script:”, reply with:
--with-http_ssl_module --with-openssl=/tmp/openssl-1.0.0-beta3

Keep in mind that if you downloaded the latest version of the source code, your values might be slightly different from mine.

That’s it! I’ve also posted a sample configuration file for nginx to enable SSL.