Blog


Jun

First Impressions of My Craftsmanship Swap With 8th Light


This Saturday, I left a rainy Göteborg at 7 am and I arrived 2 pm to Chicago, where Paul Pagel from 8th Light came and picked me up. Paul showed me around in Chicago. We went to the Millenium park and saw the famous Cloud Gate sculpture. After that we had a couple of beers and went to a barbecue party on a big terrace with a beautiful view over the Chicago skyline. I went home pretty early since I had been up for almost 24 hours. And of course I forgot to tip the taxi driver on the way to the hotel. It's not easy being a Swede and not being used to tip all the time.

On Sunday I took the Architecture River Cruise; there was a fantastic guide telling stories about the buildings. I actually learned one thing on the boat trip: the difference between modern and post modern architecture. Modern architecture follows the rule: "less is more" while post modern let the surroundings effect the form of the building. Therefore a modern building can be placed in any city and still fit in, while a post modern building only has one right place - the current. I can highly recommend that boat trip - it was awesome.

After only two days in Chicago I'm already in love with the town.

8th Light

This Monday morning I took the train from Chicago Union Station to Libertyville. I felt very excited to join all the craftsmen at 8th light. After saying hi to everyone I got to pairprogram with Doug Bradbury. It was a multi language project (C++, Java, Ruby). But fortunately we only programed in Ruby. The application handles reservations of computers in libraries. I learned a lot of new stuff today. The most profound thing I learned or the most extreme thing I did was to pairprogram with Doug when he was on a treadmill - that's extreme programming. I also got to work in IntelliJ for the first time. It's very nice but I'm still a Textmate guy, but since Ruby 1.9 still isn't working properly with all the bundles, I'm thinking about switching editor. IntelliJ might be the one.

NoSQL at Obtiva

In the evening, we went on to the a to Obtiva office's, downtown Chicago, for a NoSQL group meeting. They had a very nice office and served some delicious food. It was an open discussion around a paper (CAP - Consistency, Availability, and Partitioning) that everyone had read beforehand. Interesting but very technical. We had to leave early since we had to catch the train back to Libertyville, a one hour train ride, so we missed the last part of the group meeting.

Thougths

One hard thing coming from Sweden to USA, is to program on an american keyboard. Since we have the letters å, ä, ö, in our alphabet, the important "programmer keys" are positioned differently. So there's some fumbling on the keyboard while trying to find the right keys.

Building

Closing

So far it has been a great experience. I love the town and the people. I'm very glad for having this opportunity to travel from Sweden to Chicago and getting to know the 8th Light guys. Finally a big thank to Micah Martin and CJ Kihlbom for making this a reality. Now it's time get some sleep before a new exciting day at 8th Light.

Feb

Mirror Images with CarrierWave


Inspired by this post on how to create mirror images with Paperclip, I decided to write up how to do the same thing with CarrierWave. It's a nice example of how CarrierWave's Uploader class makes manipulating files very easy.

This assumes you've already generated an uploader and probably mounted it on a model somewhere. If this doesn't make sense to you, check out the CarrierWave documentation.

Add this method to you uploader:

def add_mirror_effect(mirror_length)
  manipulate! do |img|
    mirror_rows = img.rows * mirror_length

    gradient = Magick::GradientFill.new(0, 0, mirror_rows, 0, "#888", "#000")
    gradient = Magick::Image.new(img.columns, mirror_rows, gradient)
    gradient.matte = false

    flipped = img.flip
    flipped.matte = true
    flipped.composite!(gradient, 0, 0, Magick::CopyOpacityCompositeOp)

    new_frame = Magick::Image.new(img.columns, img.rows + mirror_rows)
    new_frame.composite!(img, 0, 0, Magick::OverCompositeOp)
    new_frame.composite!(flipped, 0, img.rows, Magick::OverCompositeOp)
    new_frame
  end
end

This will first create a gradient. It will then flip the image and use that gradient as the alpha channel for the flipped image. Finally it will create a new image, putting the original, and the faded out mirror image together.

Next, add a version to your Uploader, which calls the new add_mirror_effect method:

version :with_mirror do
  process :add_mirror_effect => 0.2
end

That's it! The end result should look something like this:

class AvatarUploader < CarrierWave::Uploader::Base
  include CarrierWave::RMagick

  version :with_mirror do
    process :resize_to_fill => [200, 200]
    process :add_mirror_effect => 0.2
  end

private

  def add_mirror_effect(mirror_length)
    manipulate! do |img|
      mirror_rows = img.rows * mirror_length

      gradient = Magick::GradientFill.new(0, 0, mirror_rows, 0, "#888", "#000")
      gradient = Magick::Image.new(img.columns, mirror_rows, gradient)
      gradient.matte = false

      flipped = img.flip
      flipped.matte = true
      flipped.composite!(gradient, 0, 0, Magick::CopyOpacityCompositeOp)

      new_frame = Magick::Image.new(img.columns, img.rows + mirror_rows)
      new_frame.composite!(img, 0, 0, Magick::OverCompositeOp)
      new_frame.composite!(flipped, 0, img.rows, Magick::OverCompositeOp)
    end
  end

end

For extra props, put the add_mirror_effect method in a module and include it in your Uploader.

Aug

BizConf Reflections


In my post about the business value of conferences I mentioned that I would attend the conference BizConf, which I now have. This is a short review of my experience there.

It was hard to believe that this was BizConf's first year. The organizers did a great job making sure that everything ran smoothly and everyone had the best experience possible. I certainly had. The setting—the Ritz-Carlton on Amelia Island—was fantastic. While I spent most of the time inside, I managed to find some time to enjoy the beach.

Beach sunrise on Amelia Island

The reason I spent most of my time inside was that the sessions and conversations at the conference were so amazing. Limiting the number of attendees to just 75 people really helped define the conference as a place of great discussions among peers.

Since there were usually four simultaneous sessions the number of attendees in each sessions was very small—sometimes less than 10 people—which made the sessions very intimate and interactive. Some of them were just really fascinating group discussions with incredibly knowledgeable and experienced people like Jerry Weinberg and Johanna Rothman.

I was amazed by the consistent high quality of all the sessions. I was going to try to list some of my favorite sessions, but there were just too many of them! The content ranged from tactical to strategic. A great mix of simple, practical advice and higher level talks about the purpose of running a business.

The small group made everyone seem very approachable. And since the attendees were 75 of the nicest, most brilliant people in the business, the conversations were really great. This was my favorite part of BizConf by far. Having so many peers to discuss the challenges of running a business with was worth the price of admission alone.

Some of the great people at BizConf

One big difference compared to most other conferences I've been to was how few people had their laptops up during the sessions. Lark said it best:

You can tell a great conference... when there's no chance to tweet! #bizconf was rich, full-time intensity!

I realize that I'm rambling a bit here. I apologize. What it comes down to is this: Will I be back next year?

Hell yeah!

Jul

The Business Value of Conferences


In our business—like many others—there are two things that you need more than anything to succeed: the right skills and the right people. The best place I know to get both is at conferences.

The development team here at eLabs—Anders, Jonas and I (CJ)—just got back from the absolutely amazing FutureRuby conference in Toronto. It was hands down the best conference I've ever been to. The presentations were great, the people were great and everything was organized with such an amazing attention to detail by the good folks at Unspace. While the total cost (including the conference fee, hotel rooms, flight and loss of income) probably exceeded US $20,000 for us, here's why I think it was worth it:

The Right Skills

The most obvious benefit is of course the things you learn from the presentations at the conference. Perhaps somewhat counterintuitively, I find that I get more out of the presentations that aren't really trying to teach something. For learning the ins and outs of a technology I prefer a good book or online tutorial. No, the presentations that I think help me the most when it comes to improving my skills are the higher-level, more philosophical ones that make me think in new ways. That's much more important in the long run.

FutureRuby got this right. While there were some presentations that were too focused on some technology, the great presentations by Jon Dahl, Brian Marick, Dr. Nic Williams, Foy Savas, Matthew Knox and others more than made up for it. These talks will inspire us to improve and expand our skill sets for a long time.

The Right People

While getting the right skills is important, getting the right people is much more so. The right people can always acquire the right skills. The inverse is not necessarily true. So how does going to a conference help you get the right people?

First of all, you can of course meet the right people at the conference. If you're looking to hire developers a conference is a great place to be looking (though I think a user group is even better). And even if you're not hiring at the moment you're bound to meet a bunch of great business connections, helpful peers, and friends. We certainly did.

Getting the right people at a conference is also about keeping the right people. Going to a conference as a team is a great way to strengthen your company. Having inspired and motivated colleagues is just as important as being inspired and motivated yourself.

CJ, Anders and Jonas of eLabs enjoying Toronto

So far, I've only been to technology conferences—such as FutureRuby, WWDC, Scotland on Rails and RailsConf Europe—but next month I'll be traveling to Florida for something different altogether:

BizConf is an exclusive conference for entrepreneurs, consultants and people who run web development companies. The presenters they've lined up sound fantastic, but I'm just as excited to meet the other attendees. A couple of people I met at FutureRuby—Dr. Nic Williams of Mocra and Gustin Prudner of Entryway—are going to BizConf too. It was great talking with them at FutureRuby and sharing ideas on running a web development business, and I can't wait to meet them again along with all the other attendees.

BizConf is limited to 75 attendees and the early bird pricing ends today (July 15th) so make sure you register now! I hope to meet you there, or at another conference.

/ CJ

PS. FutureRuby also inspired us to dust off our old dream of NordicRuby again. We'll see what happens.

Jul

Continuous Integration Testing for Ruby on Rails with Integrity


Doing test-driven development usually means you have a lot of tests in a project. While this is almost entirely a good thing, running the thousands of Cucumber features and RSpec examples in a large project takes a couple of minutes. If you run your entire test suite every time you commit this will easily eat up a large chunk of your day. Offloading some of this to a continuous integration server will allow you to save time by running your tests asynchronously, in addition to its other benefits.

At eLabs we usually run our unit tests locally—as well as the Cucumber feature for the story we're currently working on—before checking in. Then we let our CI server run the rest of our Cucumber features and notify us if something goes wrong. Here's the setup we use:

Integrity

At eLabs we've looked at a number of different CI servers, such as CruiseControl.rb and Run Code Run, but our favorite by far is Integrity.

Screenshot of our Integrity site

Integrity suits us perfectly. It fetches our code from our private GitHub repositories, can run any testing command and notify us in a variety of ways such as email and Campfire. It also has a very nice and clean interface. Its one major shortcoming is its complete lack of error reporting. If there's something wrong with your setup it will silently fail, which makes troubleshooting a nightmare. Hopefully the instructions below will help you avoid some of the pitfalls.

Installation

We installed Integrity on a server running Mac OS X and Passenger under Apache. Here's a quick guide.

First we installed the gem:

$ sudo gem install integrity

Then set it up in your chosen directory using the --passenger option:

$ integrity install --passenger /Library/WebServer/Sites/integrity

Next, set up a virtual host in Apache, pointing its DocumentRoot to the public folder in your Integrity installation.

DocumentRoot "/Library/WebServer/Sites/integrity/public"

One absolutely crucial step that we missed at first is to make sure that the system user that runs the Integrity passenger processes has git in its PATH. The simplest way to do this is to set the PATH in the virtual host configuration:

SetEnv PATH /opt/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

After configuring Apache you have to configure Integrity by editing config.yml in the root directory of your Integrity installation. We used SQLite for the database (couldn't get it to work with MySQL). If you want to use a hash password for the admin user, here's a simple way to get the SHA1 of a password:

$ ruby -r 'digest/sha1' -e 'puts Digest::SHA1.hexdigest("password")'

The final step is to create the database:

$ integrity migrate_db

You should now be able to log in to your Integrity site and add your projects.

Setting Up a Project

The most important part of setting up a project for CI is the build command. This is the command that Integrity runs to test your app, and it can be anything that exits with a status of 0 when successful. We use a simple rake task that prepares our project by copying a database.yml file and runs RSpec and Cucumber tests.

namespace :ci do
  task :copy_yml do
    system("cp #{Rails.root}/config/database.yml.ci #{Rails.root}/config/database.yml")
  end

  desc "Prepare for CI and run entire test suite"
  task :build => ['ci:copy_yml', 'db:migrate', 'spec', 'features'] do
  end
end

With that committed to our repository (along with a database.yml.ci file) we add the project to Integrity. The important parts here are the Git repository and Build script settings.

Add a project to Integrity

You must also make sure that the Integrity user can access your repository on GitHub. There are a couple of different ways you can do this, but we created a separate free GitHub account that we add as a collaborator to our projects.

After you add the project you should be able to request a manual build from the Integrity web interface. Note that the build is done synchronously—so you'll have to wait a while—but if the build succeeds you're ready to set up the Post-Receive hook for GitHub to have Integrity run your tests whenever you push your code to GitHub.

GitHub Post-Receive URL settings

Go to your project's page on GitHub and click the Admin link in the top menu, and then Service Hooks in the sub menu. Enter the push URL for your Integrity project as Post-Receive URL. The URL has the following format:

http://username:password@hostname/project-name/push

After you've updated the settings, click the Test Hook link and Integrity should start a new build. If that works, you're all set for having automated builds on every push to GitHub.

Notifiers

While Integrity's interface is nice, you probably don't want to visit your Integrity site after every commit to check the status of your build. The point of asynchronous tests after all is to get notified when somethings goes wrong. Integrity has a bunch of different notifiers you can use. We use the ones for email and Campfire. Find more and installation instructions on the Integrity site.

In addition to Integrity's own notifiers we also use CCMenu, a Mac OS X Menu extra built for showing CruiseControl build status. It works with Integrity as well with the gem integritray.

We also use GitHub's Campfire service hook that posts a message to our Campfire room every time someone pushes new code. This makes it very easy to keep track of what other people in the company are working on.

Campfire screenshot

Not having to wait for our entire test suite to run before each commit saves us a lot of time. But we can still feel confident knowing that Integrity has our backs and will alert us if something goes wrong.