Jordan Brock

Now on GitHub Pages

Jun 07, 2012

A quick post to mark the fact that I’ve moved this site from a hosted wordpress install to GitHub Pages, using Jekyllto generate the static files for the blog.

It’s a remarkably simple system: Create a repository in github called username.github.com, configure Jekyll, and then commit and push your code to your repository. GitHub then automatically runs Jekyll on your site, generating the static files, and then publishing the site.

No more having your site locked into a database format, or using some blogging engine that can be compromised. And automatic backups!

Here’s my repository so you can copy the config files.

Vagrant + Chef (and OpenPhoto)

Apr 17, 2012

I’ve spent the past couple of days playing with Vagrant , which is an add-on for VirtualBox that allows you to quickly build virtual machines, configured exactly how you want them, on a project by project basis. The advantage of this is that it lets you replicate your production environment (or as close to as is possible), which should hopefully reduce headaches when you deploy your updates.

Vagrant VM’s are portable, which means that all of your team members can have exactly the same development environment, regardless of their own system setups. Once again: less headaches.

Vagrant

How does it work? Well, first of all, you need the latest version of VirtualBox, and the vagrant gem. I installed it into my system gems, but there’s no reason it couldn’t be in your Gemfile if you’re working on a ruby project.

gem install vagrant

Once it’s all setup (read the full instructions for some additional steps), you need to initialise your directory:

vagrant init

This creates a file called “Vagrantfile” which configures your VM’s for each project. The most basic file would look like this:

Vagrant::Config.run do |config|
  config.vm.box = "lucid32"
end

This tells vagrant to start up a VM using an Ubuntu image. It will boot the VM, and then set a port redirect up so that you can SSH into the VM with the following:

vagrant ssh

That’s all very handy, but of course, you’re going to want your machine to have some software configured. Enter Chef, stage left.

Chef

Chef is a framework that lets you create “recipes” to install and configure software on VM’s. Basically, it’s a scripting system for getting a blank VM up and running.

As a good starting point, Opscode have a great repository of “cookbooks” (collections of recipes - natch) on github that you can fork and start using without having to make too many (if any) changes.

To work with Vagrant and Chef, you need a VM configured for Vagrant with a recent build of Ruby installed, as well as the chef. Setting up an Ubuntu 11.10 VM for Vagrant is relatively simple. Just follow steps 1-3 in these instructions.

Once that was complete, you need to install Ruby. Here’s a quick guide to installing Ruby 1.9.3-125 from source on Ubuntu.

Then I installed the chef gem

gem install chef

to get chef-client and chef-solo on the VM. (Note: I’m only dealing with chef-solo in this post. chef-server adds a layer of difficulty that isn’t necessary at this stage.)

Once you have your base VM setup, you need to package it up for Vagrant, so it can load it up in VirtualBox as needed.

mkdir ~/Vagrant && cd ~/Vagrant

vagrant package --base vagrant-oneiric package.box

vagrant box add vagrant-oneiric package.box 

At this point, you should have a base VM ready for configuring with Chef.

Vagrant and Chef, sitting in a tree

Vagrant is built to work with provisioning software such as Chef (and puppet). You add a series of Chef commands to your Vagrantfile that it will run on your VM as it is being configured.

To add recipes to your VM you just add the following to your Vagrantfile:

chef.add_recipe("mysql::server")

Chef allows for configuration settings, such as passwords and installation directories, to be passed through to recipes. Vagrant supports this as well:

config.vm.provision :chef_solo do |chef|
  chef.json = {
    :mysql => {
      :server_root_password => "secretpassword"
    }
  }
  chef.add_recipe("mysql::server")
end

OpenPhoto

OpenPhoto is an open source photo service that allows you to retain control of your photos, rather than store them with some site that may not even exist in 3 years. Your photos are stored on AmazonS3 or on Dropbox, and you can run a server yourself to maintain total control over the whole setup if you wish, or use their hosted service available here: http://openphoto.me.

Being open source, anyone can contribute to the system, and as with most open source projects, they need as much help as they can get. So, I’ve started tinkering with it, and I thought it was a good candidate to run with Vagrant and Chef to setup test servers quickly and painlessly.

So, if you want to do the same, here’s my Vagrantfile for my OpenPhoto directory, which is a git clone of my fork of the OpenPhoto repository on github. It should hopefully allow you to get up and running if you’ve done everything outlined above.

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant::Config.run do |config|
  config.vm.box = "vagrant-oneiric"

  config.vm.provision :chef_solo do |chef|
    chef.binary_path = "/path/to/chef/binary/"
    chef.cookbooks_path = "/path/to/chef/cookbooks"

    chef.json = {
      :mysql => {
        :server_root_password => "secretpassword"
      }
    }

    chef.add_recipe("mysql")
    chef.add_recipe("mysql::server")
    chef.add_recipe("apache2")
    chef.add_recipe("imagemagick")
    chef.add_recipe("php")
    chef.add_recipe("php::module_curl")
    chef.add_recipe("php::module_mysql")
    chef.add_recipe("php::module_apc")
    chef.add_recipe("php::module_dev")
    chef.add_recipe("php::module_imagick")
    chef.add_recipe("php::module_mcrypt")
    chef.add_recipe("php::module_gd")
    chef.add_recipe("apache2::mod_rewrite")
    chef.add_recipe("apache2::mod_deflate")
    chef.add_recipe("apache2::mod_headers")
    chef.add_recipe("apache2::mod_expires")
    chef.add_recipe("apache2::mod_php5")
    chef.add_recipe("git")
  end

  config.vm.share_folder "openphoto", "/var/www/openphoto", "/path/to/openphoto/frontend", :owner => "www-data", :group => "vagrant"

  config.vm.forward_port 80, 8080
end

Run

vagrant up

and that will build your new VM using the base image, and then configure all of the required software. It might take a little while :)

One of the great things about Vagrant is that you can quickly share folders with your VM, which means I can edit files in my repository on my Mac, which are shared onto the VM. This is accomplished with this line:

config.vm.share_folder "openphoto", "/var/www/openphoto", "/path/to/openphoto/frontend", :owner => "www-data", :group => "vagrant"

Apache

You’ll also need to configure Apache to use this directory. Here’s my config file:

<VirtualHost *:80>
  DocumentRoot /var/www/openphoto/src/html

  <Directory "/var/www/openphoto/src/html">
    Order deny,allow
    Allow from all

    RewriteEngine on
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)\?*$ index.php?__route__=/$1 [L,QSA]

    # 403 Forbidden for ini files
    RewriteRule \.ini$ - [F,NC]

    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE application/x-javascript
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html 
  </Directory>

  # 404 Not Found for ini files
  #AliasMatch \.ini$    /404

  ExpiresActive On
  ExpiresByType text/javascript "A31536000"
  ExpiresByType application/x-javascript "A31536000"
  ExpiresByType text/css "A31536000"
  ExpiresByType image/x-icon "A31536000"
  ExpiresByType image/gif "A604800"
  ExpiresByType image/jpg "A604800"
  ExpiresByType image/jpeg "A604800"
  ExpiresByType image/png "A604800"
  
  Header set Cache-Control "must-revalidate"
  FileETag MTime Size
</VirtualHost>

You can then add a port forwarding rule to provide easy access to the Apache server running on the VM, like so:

config.vm.forward_port 80, 8080

Then, fire up “http://localhost:8080” in your browser, and you should be looking at your OpenPhoto install!

Selenium "ElementNotDisplayedError"

Jun 23, 2011

If you do integration/request testing of an AJAXified web application using Rspec, Capybara and Selenium there is a pretty good chance that you might have run into this error:

Selenium::WebDriver::Error::ElementNotDisplayedError:
Element is not currently visible and so may not be interacted with

After spending way too long to try and solve this problem (“THE ELEMENT IS VISIBLE DAMN YOU!!!!”) I found a few little tweaks to my setup that help remove and/or mitigate the error.

The key to this error is that Capybara is trying to find and/or interact with an element and it’s not quite ready on the page yet because some JavaScript hasn’t executed yet, or there’s a delay with the test web server.

jQuery Effects

If you’re running tests, there’s a pretty good chance you don’t care about any jQuery effects. You’re just interested in the result. If that’s the case, then add this line to your page layout:

= javascript_tag '$.fx.off = true;' if Rails.env.test?

That will turn jQuery effects off in the Rails test environment.

Capybara “wait_for”

This is a particularly helpful method that, like its name implies, causes Capybara to take a chill pill, and wait for a particular condition to be met. Call it like this:

wait_for(15) {page.should have_content "Some text."}
wait_for(30) {page.should have_button "Button Text"}

This just gives the page a little time to catch up before Capybara blows up on you.

capybara-webkit

A new Selenium driver from the fine folks at Thoughtbot, this is a headless (this just means it doesn’t open a visible window) browser that Capybara can interact with. Ideally it should be faster than opening up a browser window for each test. I managed to get it working, mostly. It’s still kind of new, so there are a few things missing, but it might be a good idea to watch the github project.

Or is it just because people don't like your new stuff?

May 20, 2011

A quote from John Butler on the Music Industry Piracy Investigations site:

“We sell about 40 per cent less albums than we did three or four years ago because of [illegal] downloading” - John Butler

Of course, it’s got nothing to do with the quality of the stuff they’re putting out now. No. It’s all because of the computers. Because computers weren’t around three or four years ago.

I found this site because they’d just sent a takedown notice to Cameron Adams over his brilliant Definitive Daft Punk mashup, which has got to do more to promote sales of Daft Punk than any threat of legal action will ever accomplish.

CoffeeScript, bistro_car, homebrew, and passenger gotcha

Apr 08, 2010

File under “Things for me to remember when reinstalling stuff”

For me, one of the best things about using Ruby/Rails/Sinatra for web development is HAML/SASS, which allow me to quickly write and maintain HTML/CSS without having to worry about all the pointless stuff, like brackets etc. A by-product of using HAML/SASS is that when you have to write in something else, it causes me grief. JavaScript is a case in point.

Coffeescript (and to a lesser extent) bistro_car solve this. It brings the beauty of a ruby-like language to writing JavaScript, so that once again you don’t have to worry about all the crap that goes along with it.

However, I ran into a slight problem when following Dr Nic’s setup tutorial today. CoffeeScript worked, bistro_car worked within the console, but it didn’t work when accessing the page through the browser. But some path re-working, and a kind word or two from @sutto, and we’re good to go.

For future reference, here’s what I did. I’m using the homebrew package manager. Mainly because it’s awesome, and I use MacOS X, which is also awesome.

So, I installed node.js, coffeescript and bistro_car like so:

brew install node
brew install coffee-script
gem install bistro_car

Then, add the following to your environment.rb file:

config.gem 'bistro_car'

Create an ‘app/scripts’ directory in your Rails app, which is where you can store all your .coffee files (application.coffee etc).

You then get bistro_car to include those script files by putting this in your layout/template/page/whatever:

coffee_script_bundle

Then, you load the page, and bistro_car automagically uses coffee-script to convert your .coffee files to javascript. Except, of course, when it doesn’t work because something is screwed somewhere.

As with almost every problem on a *nix computer, the problem is a path one, and thankfully solved with some simple symlinks. It seems passenger operates in it’s own little world when it comes to paths, and it just didn’t want to play nice with my environment. So, I tricked it as follows:

sudo ln -s /usr/local/bin/coffee /usr/bin/coffee
sudo ln -s /usr/local/bin/node /usr/bin/node

And that, my friend, is how you skin the unix path cat.