Call us at (416) 850-2500 - Visit us at 639 Queen St. W, Suite 502, Toronto, Ontario M5V 2B7
  Posted by todd on February 18th, 2010

TWG Kicks Off 2010 with Scrum!

TWG would like to formally welcome you to 2010 and talk a little bit about something we’ve decided to kick off the new year with: Scrum!

Scrum is an agile framework that allows teams to become self organizing and focus on delivering high business value.

In 2010, TWG is committed to delivering working, high business value, high quality software, faster.  This is something Scrum enables us to do.

Why Change?

While TWG has previously used plenty of agile practices, the time has come to formalize the process so that we can get all the benefits of being an agile organization.

How Is Agile Different?

Many agencies and web development companies typically insist on gathering every single requirement up front, locking them down, forcing the client to sign off, swearing that these requirements will never change.  We now know better.  Requirements will change, we learn as we go, and we will inevitably discover new and more valuable features as the project comes together.  TWG is using Scrum to build partnering relationships with our clients, so that we can see and adapt to requirements as they emerge, and deliver better and more usefule websites and software.

Build Less Software…

So how do you build high value, high quality software, quickly?  Build less, but build it better!

This may seem unusual, but remember, when you start a project, application or a web site, you don’t really know what you or your users want until you get your hands on it and start playing with it.  This is normal.  So instead of trying to plan it all up front, we’re going to be working on building the things you know right now, and get them done, Done, DONE!

Nothing gets feedback better than working software, so why wait until the end of your project to see it?  Once you’ve seen it and learned from it, you can add to it, change it or even scrap it!

At TWG, we’re starting Scrum with 1 week sprints.  These are time boxed working periods where at the end, our goal is to deliver working software, as opposed to things like documents, mock-ups or in-progress features.  This is a tough, aggressive process that we’re working on, but we feel in the end it will enable us to deliver better, more valuable software, faster.

…Get more value (rather than a laundry list).

Many web development companies will work with you to look around at all the sites that are out there, collect a large laundry lists of  possible features that you might want your system to do, and then give a quote on building that.  You sign off, and the work gets started.  You wait potentially months until all the features are built, the schedule might slip two or three times, and when you finally get it, you discover you really didn’t end up with the software you really hoped for or needed.

Not only that, but while the software was being built, the market changed and some features became irrelevant or new features became more critical.  Too late to change now.  I guess you’re stuck.

What if you had your list of features prioritized in order of importance/ROI and what if you got the most important features first each iteration – say every week?  Maybe you’d find out you didn’t need to build those last few features since they weren’t all that valuable anyway, or maybe you’d find you could swap some of those less valuable ones out for new ones.  Who wouldn’t want that kind of flexibility?

What Comes Next?

This transition is a work in progress and we’re going to give you regular updates and insights into our experiences with Scrum.  You’ll get to see some of the nitty-gritty details like our task board, and burn up charts, as well as some of the struggles and discoveries we make as we go down this road.  We hope you’ll keep your eye on our blog and provide us with any feedback or experiences you’ve had.

  Posted by Oleg on December 16th, 2009

Remember Rcov?

Rcov helps to identify code that is not being being hit by your tests (or maybe some functions left behind after refactoring). It’s very easy to get it running as well:

$ sudo gem install rcov

Plug this rake task into /lib/tasks/rcov.rake

require 'rcov/rcovtask'

namespace :rcov do
  desc 'Measures test coverage using rcov'
  Rcov::RcovTask.new(:test) do |rcov|
    rcov.pattern    = %w(test/unit/**/*_test.rb test/functional/**/*_test.rb test/integration/**/*_test.rb)
    rcov.output_dir = 'rcov'
    rcov.verbose    = true
    rcov.rcov_opts << '--exclude "gems/*"'
    rcov.rcov_opts << '--rails'
  end
end

And finally run it:

$ rake rcov:test

It’s so easy you have no excuse not to have it.

  Posted by Scott Tadman on December 8th, 2009

Harnessing Ruby Enumerable

You’re probably afraid to ask about some of the methods in the Ruby Enumerable mixin. Not only are there a whole bunch of them, 41 in Ruby 1.9 to be exact, but selecting the right one for the problem can be an exercise in frustration. Part of the problem is there’s no easy way to identify what method might suit your requirements. While the names are usually self-explanatory, it can be tricky to remember block arguments or if they return an Array or a particular element.

Any toolbox needs to be organized, so it’s probably best to sort the various Enumerable methods into groups based on the kind of result you want to get. Grouped together like this, the methodology within Ruby becomes more apparent.

Conventions

In this description, “true / false” refers to values that are equivalent to true, or equivalent to false. In practical terms this means that nil and false are both considered false, and everything else is non-false, (or in general terms, true). Note: things that evaluate as true include what might be considered false in other languages such as 0, empty strings, and empty Array or Hash structures.

When describing the blocks, e refers to an element in the set. For an Array, this is simply the element at a particular index. For a Hash this is a key/value pair, so the block semantics should be expanded to { |(k,v)| } or e.first and e.last will need to be used within the block.

Assessment

One of the simplest features of Enumerable is the methods that provide a quick true/false assessment based on the content involved. Often these will be used to decide how to handle an Array or Hash, or if its in a condition that can be utilized.

Method Arguments Block Definition Return
all? { |e| … } => true / false
* Optional
true / false
Runs each element through the given block with and returns true if all of the block results evaluate true, otherwise false. Without a block returns true if all the elements evaluate as true, otherwise false.
any? { |e| … } => true / false
* Optional
true / false
Runs each element through the given block with and returns true if any of the block results evaluate true, otherwise false. Without a block returns true if any the elements evaluate as true, otherwise false.
none? { |e| … } => true / false
* Optional
true / false
Runs each element through the given block with and returns true if none of the block results evaluate true, otherwise false. Without a block returns true if none the elements evaluate as true, otherwise false.
one? { |e| … } => true / false
* Optional
true / false
Runs each element through the given block with and returns true if one of the block results evaluate true, otherwise false. Without a block returns true if one the elements evaluate as true, otherwise false.

Single Element

Often you’ll want to extract a single element from a set. In this case there are many ways to get what you want, each with their particular quirks.

Method Arguments Block Definition Return
detect ifnone = nil { |e| … } => true / false element / nil
Runs each element through the given block with and returns the first element for which the block result is true. If all return false, the result is nil.
find ifnone = nil { |e| … } => true / false element / nil
The same as detect, this runs each element through the given block with and returns the first element for which the block result is true. If all return false, the result is nil.
first element / nil
Returns the first element in the set, of if the set is empty then nil.
max { |a,b| … } => -1 / 0 / 1
* Optional
element / nil
Returns the largest element in the set, of if the set is empty then nil. The result of the optional block should be compatible with Comparable and return -1, 0, or 1.
max_by { |e| … } element / nil
Returns the largest element in the set where comparisons are performed on the result of the block, of if the set is empty then nil. Anything returned by the block must be compatible with Comparable.
min { |a,b| … } => -1 / 0 / 1
* Optional
element / nil
Returns the smallest element in the set, of if the set is empty then nil. The result of the optional block should be compatible with Comparable and return -1, 0, or 1.
min_by { |e| … } element / nil
Returns the smallest element in the set where comparisons are performed on the result of the block, of if the set is empty then nil. Anything returned by the block must be compatible with Comparable.

Filtering

Method Arguments Block Definition Return
grep regexp { |e| … }
* Optional
Array
Matches each element against the supplied regexp and returns all that match in an Array. If a block is supplied, all matching elements are transformed by the block before being inserted into the result Array, which avoids having to chain the result through a map call.
reject { |e| … } => true / false Array
Runs all elements through the supplied block and excludes those from the result array where the block evaluates as true.
select { |e| … } => true / false Array
The inverse of , this runs all elements through the supplied block and includes those from the result array where the block evaluates as true.
select { |e| … } => true / false Array
The inverse of , this runs all elements through the supplied block and includes those from the result array where the block evaluates as true.

Transformation

There are a few powerful methods for transforming the content of one set into an Array.

Method Arguments Block Definition Return
collect { |e| … } Array
Runs each element through the provided block and puts each block result in the Array that is returned.
map { |e| … } Array
The same as collect, runs each element through the provided block and puts each block result in the Array that is returned.
inject memo = first { |memo, e| … } last block result / nil
This is perhaps the most understood and under-utilized method in the Enumerable toolkit. In general terms, this method takes a seed “memo” value, and runs that through the block in conjunction with each element. The result of the first block call is supplied to the second, and so on, which leaves the door wide open as to what this method can do. For instance, every other Enumerable method can be expressed as a form of inject.
  Posted by Oleg on November 27th, 2009

Active state for link_to == active_link_to. A solution for building navigation systems in Rails.

I have a question for you. How do you deal with the logic of setting links as active in your navs?

Actually, I don’t want to know. It’s probably awful. I might have a pretty good solution for you. Let’s take a look at a very simple nav. These examples all use HAML:

%ul
  %li= link_to 'Home', home_path
  %li= link_to 'Puppies', puppies_path
  %li= link_to 'Kittens', kittens_path
  %li= link_to 'Froggies', froggies_path

Right, that’s great. But how do I insert logic as to what link gets marked as active? To begin, let’s quickly install this random gem:

sudo gem install active_link_to

And then change our nav a bit:

%ul
  %li= active_link_to 'Home', home_path
  %li= active_link_to 'Puppies', puppies_path
  %li= active_link_to 'Kittens', kittens_path
  %li= active_link_to 'Froggies', froggies_path

And that’s pretty much it.

So, for example, if you navigate to /kittens/1-my-fluffy-kitten navigation link for ‘Kittens’ will have ‘active’ class attached to it. It’s almost like magic.

You probably noticed that ‘Home’ is highlighted as well. It happened because whatever URL you are currently on is a child of the home_path. I guess we want to mark it as active only if we find ourselves on the home page and not anywhere else. We can fix this:

%ul
  %li= active_link_to 'Home', home_path, :active => {:when => :self_only}
  %li= active_link_to 'Puppies', puppies_path
  %li= active_link_to 'Kittens', kittens_path
  %li= active_link_to 'Froggies', froggies_path

Hey, wanna render a sub nav when you find yourself browsing /puppies or any page under that URL? It’s just sooo easy:

%ul
  %li= active_link_to 'Home', home_path, :active => {:when => :self_only}
  %li
    = active_link_to 'Puppies', puppies_path
    - if is_active_link?(puppies_path)
      %ul
        %li= active_link_to 'Big', big_puppies_path
        %li= active_link_to 'Small', small_puppies_path
  %li= active_link_to 'Kittens', kittens_path
  %li= active_link_to 'Froggies', froggies_path

And that’s the skinny of what active_link_to is for.

For more documentation on more functionality checkout project on GitHub: http://github.com/theworkinggroup/active_link_to

  Posted by Vivian on November 3rd, 2009

Making a world of difference with 0.05em

Typographic sensibility can make or break a design, both in print pieces and online. In web design, attention to typography is especially important since the majority of online content is written information. It is often said that the strength of a web designer can be judged through their ability to create an engaging UI with just text.

There are many tools and tricks available to web designers when it comes to styling type: size, colour, alignment, line-height (leading), word-spacing (don’t do it), but an important one I find most often ignored by developers is letter-spacing (tracking). Letter-spacing is literally the space between the letters… and it can make a big difference in terms of legibility and the overall feel of a site.

letter-spacing-importance

“Don’t blame me; you forgot the letter-spacing…”

As a designer, it feels like I am often getting flack from developers for type that is “too small”. Ninety-nine percent of the time after I hand off an Illustrator file or PSD of a design, the coded page comes back to me without any letter-spacing included in the CSS. Letter-spacing is like air: you don’t really notice it, but it makes a difference whether it is there or not.

It’s easy, just do it.

I’m really bad at math, but the other day it dawned on me how to figure out the CSS letter-spacing measurement from my AI (or PSD) file. Tracking in Adobe programs is measured in 1/1000em so when the design file specifies “50″ or “100″ in the tracking character palette, it is 100/1000 = 0.1em. That 0.1em can take a 10px all caps style from “too small” to “completely awesome”. See below:

EXAMPLE WITHOUT ANY LETTER-SPACING, OMG SO TIGHT, NOT IN A GOOD/SEXY WAY.

ADDED 0.1EM OF LETTER-SPACING. LOOK HOW AMAZING IT IS NOW.

2PX OF LETTER-SPACING? CRAZYTOWN! GET THE EFF OUT OF HERE!

Of course there are issues…

Like in many cases, basically Firefox is the only browser that does letter-spacing right. Depending on your product/audience, this may not be an issue, but it is definitely something to keep in mind when specifying sub-pixel measurements that may be rounded up or down in browsers other than Firefox.

Negative letter-spacing: it’s just a fad, right?

This is so tight, yo! I can’t even read it!

Over the last couple years a big web typography trend has been the bold sans type with negative letter-spacing, “all the cool kids are doing it.” While I can see the appeal (in that it speaks to the whole web 2.0 design aesthetic), I expect that this trend will soon remedy itself. Letter-spacing is meant to be applied with a gentle touch, and when heavy-handed negative (or positive) tracking occurs, it can definitely affect the legibility, as some of those examples clearly show.

The bottom line

Always use letter-spacing to your advantage and not to your own detriment, just because it’s “in”. Yell at developers when they omit it from the CSS and then decide to blame you, the designer. And if that doesn’t work, do what I had to do: get the keys to the site or app, then tweak to your heart’s content.

  Posted by Georges on October 16th, 2009

geeks + beer + friday = ?

Every so often a text editor war will flare up in the office. We all have our favourites, but no one likes vi the way Scott likes vi.

Here’s the first in Dr. Tadman’s twelve part lecture series on how vi will make your life better:

TWGtadman-viforbeginners_thumb

Click For Full-Size Image

  Posted by Jack on September 24th, 2009

Rails mass mailing – it shouldn’t be this complicated

The requests we get from our clients for “social networking” type tools and features has grown exponentially over the past two years. To make a user experience relevant, easy, secure, means that an application will need to send email notifications to that user (to register, to tell them of friend’s messages, to send them newsletters or updates, to send tickets, calendar bookings .. the list goes on).

Why is this a problem?
Because sending an email is not an instantaneous action. The more emails you try to send, the longer you may have to wait as the application sends them. Imagine an app that lets you invite 300 friends to an event. Multiply this with 300 people sending the same invite to their friends.

While Rails was kind enough to provide a simple way to send emails, it left out one important detail. You can only send one at a time!

If you find yourself in the unfortunate position where you need to mass mail then you’re on your own. So what do you do? You Google around of course. Someone is bound to have figured this one out.

It looks like there are 3 ways to solve this:

1. Use existing email marketing services

You can go with this option. There are plenty out there: Mail Chimp, Constant Contact, Thin Data, Campaign Monitor, Campaigner and others. All you need to do is generate some kind of mailing list and import it into one of these systems and then keep it up to date. But that’s not always practical. Not if you want your users to be able to initiate the mass mailing by themselves.  Don’t get me wrong, these services are great at what they do, but what we really want to do is to send mass emails from our own app.

2. Use existing code

If you really want your Rails app to be able to send mass mails at a click of a button you can try using Eric Hodel’s ar_mailer which is on version 1.4.0 as of June 2009. This has the advantage of letting you use the email addresses that you already have on your system (no exporting and importing to a different system) but before you get to that you still have to integrate it with whatever version of Rails you happen to be using.  Assuming you get it working properly, now you have a brand new background process to take care of.

Ar_mailer is great but leaves you half way there.

* The queue is not smart enough to prioritize emails. If one user sends 5000 invitations and after that another user wants to recover his password, he’ll have to wait until all 5000 emails are sent before he gets his password back. The users receiving the invitation won’t notice if  it takes a bit longer to reach them, but the guy that is trying to recover his password will be upset if he doesn’t get it right away. This is obviously not good enough.
* How do you monitor if an email has been sent or failed?
* If you have an email template and your client wants to change it all the time, what do you do?

3. Build it all from scratch

Even if you decide to do it yourself from scratch you’ll still need a queue to store the emails that will be sent at some time in the near future by another process running in the background. From there on, it depends on what you really need. Be prepared to put aside some extra time because it ain’t simple.

So what would be the perfect solution? Simply put: I don’t want to have to worry about it. I want to be able to say: “Here’s my email, here’s the list of people I want it sent to. Go and do it … please”.

Wouldn’t that be great? Sure it would! We’ve encountered this problem enough times to make us want to solve it for good.

And so we’ve set out to build it and this is what we think a mass mailing solution:

  1. I want to be able to use it independently of the language I’m coding in – it needs to have an API
  2. I want to be able to use the same code I have right now (layouts, email templates, etc.) – it needs to integrate easily
  3. I want to know if a specific email was sent, failed or if it hasn’t been sent yet and I want to know why – it needs reporting
  4. If a client complains that the emails aren’t rendering correctly I want to be able to see what they are receiving – it needs to let me look at the emails sent
  5. I want to be able to easily resend any email – it needs to let me act on it
  6. I want to create and manage email templates so that my client can edit them without asking me every time and without forcing me to change the code and to deploy my app all over again – it needs an optional template management system.
  7. I want the queue system to be smart enough to distinguish between a single email and a batch of 5000 emails and prioritize them accordingly – it needs a smart queue system.
  8. And most importantly, how can all of this be done with minimal effort to set it up each time I create a new app. – it needs a plugin.

Postage App!

Mass mailing app

We are currently developing this system which will help us build better apps. We’re building it according to our needs and we think that these might also be the needs of other developers out there. Check it out and sign up for an update on the developer free release!

  Posted by Vivian on September 8th, 2009

4 Fears of @font-face

The future of web typography seems to be almost here with Firefox 3.5 supporting @font-face, making web-safe fonts a thing of the past. Through CSS3’s linking/embedding of any font file, @font-face opens the floodgates to the millions of font options available to designers. The design possibilities are extremely exciting, but in the coming @font-face infancy, we can likely expect a dark period of uglification.

  1. Bad typography is too easy
  2. Illegible and annoying sites
  3. @font-face + CSS3 effects = disaster
  4. Pirates and the shipwrecked

The quality of typefaces in existence pie chart

Bad typography is too easy

A lot of bad or amateur-looking print design is victim of poor type decisions paired with improper typographic finesse. With all the choice out there, why pick Papyrus or Hobo for a menu or brochure? It happens far too often in print and now it can happen easily online with @font-face. For every beautifully crafted typeface, there are probably 10 mediocre ones, and 25 really fugly ones; the odds are stacked against us, but hopefully designers will exercise restraint and common sense.

Illegible and annoying sites

@font-face has the potential to marry beautiful typography with usable, accessible, and indexable content, but there are also foreseeable legibility disasters in this free-for-all. One of the best things about web-safe fonts, such as Verdana and Georgia, is that they are fairly cross-platform reliable, and have proven legibility. With its large x-height, giant counters, and distinctly varied characters, Verdana was designed to be read easily on-screen at small sizes. However when used in print, it sometimes falls comically flat – look at how IKEA just screwed their print branding by using this traditionally web typeface.

Techniques like Cufón and sIFR are technologically hefty, often limiting use just to headline text. Since @font-face is lightweight enough to use throughout an entire site, paragraph text styled poorly in an awkward font can easily impede legibility and annoy users. It’s not worth sacrificing access to the content just to make something look nicer.

Text-shadow, Hobo, hideousness

CSS3 effects + @font-face = the internet circa 1995

Pair a little cheesy text-shadowing with a “funky” typeface and the internet has been set back 15 years. There is probably never an online situation that calls for drop-shadowed, glowing, or flaming type; we’re talking web design, not cereal boxes. Like crappy flash intros, just because it exists, doesn’t mean it should be used. Let’s hope that clients don’t get a whiff of this one and start requesting it for home page headlines.

Pirates and the shipwrecked

Though it can be argued that pirates will always find a way to get what they want for free, why make it any easier to steal fonts? If used incorrectly, @font-face can offer up copyrighted font files for free. Solutions like Typekit are taking steps in the right direction, but there are bound to be inexperienced slip-ups at first. Browser compatibility issues with @font-face may also end up leaving users on older browsers behind, viewing (in theory) less typographically rich content. It will be fun watching the online typographic revolution unfold once copyright issues are resolved, and cross-browser support is ready. Hopefully @font-face will make the internet a more beautiful place, and not like a bunch of designers got drunk on the punch and barfed typefaces everywhere.

  Posted by Georges on September 2nd, 2009

Livin’ on the edge: Ruby, Rails, and Snow Leopard

Snow Leopard is out and I like having the latest and greatest, so I bought a new hard drive and clean installed Snow Leopard on it. This meant that I had the opportunity to reinstall my development environment with the benefit of a few years of experience and the advice of my fellow TWG’ers.

Here’s how I got my newly installed Snow Leopard up to speed for Rails development.

Ruby on Rails on Snow Leopard

Ruby 1.9.1

First, I got Ruby up to date. Snow Leopard comes with Ruby 1.8.7 by default. There are many benefits to going with Ruby 1.9.1, so I went with that.

I wasn’t 100% ready to commit to Ruby 1.9.1, so I used rvm to manage my Ruby interpreters. Many gems aren’t ready for 1.9 prime-time, so I wanted the ability to drop back to Ruby 1.8 if this blew up in my face. For an overview of what is working under Ruby 1.9, check out isitruby19.com.

I installed rvm with:

sudo gem install rvm
rvm-install

Check out the rvm site for more information. There’s some great documentation there.

Next, I ran

rvm list

to see all my installed Ruby interpreters. When you do this, you’ll see that the only Ruby installed is the system Ruby 1.8.7.

I ran ruby -v to see which Ruby was being used by default. I saw that I was using Ruby 1.8.7:

ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0]

rvm will happily install and activate any version of Ruby you want.
I got it to install Ruby 1.9.1 with the following:

rvm use ruby -v 1.9.1

rvm will check to see if 1.9.1 is installed and, if it isn’t, it will download and install it for you. Once that is done, I ran rvm list again and now saw Ruby 1.9.1 listed as well as Snow Leopard system Ruby.

After that was complete, I ran rvm 1.9.1, and then ruby -v and saw that it worked:

ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-darwin10.0.0]

But, I wanted Ruby 1.9.1 to be the default on my system. I got rvm to set that default by executing:

rvm 1.9.1 --default

Now, the system is set to use Ruby 1.9.1 by default.

Side note: one of the neat features of rvm is that it can change your Ruby interpreter on-the-fly for you. This change isn’t permanent and only lasts for as long your Terminal session is open. For example, you can open one Terminal, execute ‘rvm system’, and have that Terminal use the Snow Leopard Ruby 1.8.7 while another one is running Ruby 1.9.1. This is very handy for compatibility testing.

MySQL

The next piece of the puzzle was MySQL. I have found that the best way to install packages like MySQL is via MacPorts.

If you haven’t done it yet, install MacPorts from here. There’s a package for Snow Leopard, so be sure to select that one.

The MacPorts MySQL package is called mysql5-server-devel, so I installed that:

sudo port install mysql5-server-devel

MacPorts will handle all the dependencies and then install MySQL. I followed all the post-install steps that the installer recommended – start-up items, etc. The MySQL it installed is 64-bit, as it should be.

I then had to connect Ruby with MySQL and I needed the gem for that. To properly install the gem, I had to specify the architecture and the location of the mysql_config5 utility. The arch setting ensured that I got a 64-bit gem to go along with my new 64-bit MySQL installation.

env ARCHFLAGS="-arch x86_64" sudo gem install mysql -- --with-mysql-config=/opt/local/bin/mysql_config5

Ruby Gems

I then ran gem list to see what gems I had installed. If you do this, you’ll see what I saw: not much. This makes a lot of sense because gems are installed relative to the version of Ruby they were installed with. So, all the gems that Snow Leopard had installed for Ruby 1.8.7 are no longer around for use. It was at this point that I was happy I used rvm. I dropped back to 1.8.7, got the list of installed gems and proceeded to re-install them under Ruby 1.9. But, dear reader, you don’t need to do this! Here’s how to get back to the default Snow Leopard gems under Ruby 1.9:

sudo gem install actionmailer actionpack actionwebservice activerecord activeresource activesupport acts_as_ferret builder capistrano cgi_multipart_eof_fix chronic daemons dnssd fastthread gem_plugin haml highline hoe hpricot javan-whenever libxml-ruby mdalessio-dryopteris needle net-scp net-sftp net-ssh net-ssh-gateway nokogiri pauldix-feedzirra pauldix-sax-machine rack rails rake RedCloth ruby-openid ruby-yadis rubyforge rubygems-update rubynode rvm taf-curb

This’ll take a while. Go grab a coffee. Run around the block. Do something fun.

If any of these fail for you, check out isitruby19.com for tips on how to get it working.

Passenger

The next piece I needed was Passenger aka mod_rails. I needed version 2.2.5 (newest as of writing) for this to all work together. I installed it with:

sudo gem install passenger

This retrieved and compiled Passenger 2.2.5 for me. It might get a newer version for you. Once that completed, I ran:

sudo passenger-install-apache2-module

The Passenger module depends on your current Ruby version, so you have to re-compile Passenger if you change your Ruby version. It is important that the Passenger compilation properly links with the Ruby interpreter you want to use. In this case, that’s Ruby 1.9.1.

When you do this the Passenger installation, double-check the paths that the Passenger compilation process outputs and ensure that it is properly finding the Ruby 1.9.1 installed in your .rvm directory. If you see paths that don’t go to .rvm in your home directory, then it is doing it wrong. If this happens, ensure that rvm is set to use 1.9.1 by default and try again.

Next, I edited my httpd.conf just as the Passenger installer recommended. I opened it up with open /etc/apache2/httpd.conf and pasted in the Passenger lines.

The Passenger Preference Pane makes everything easier, so definitely wanted that.
I got lucky and found that it had just been updated to support Snow Leopard, so make sure you get version 1.3 or greater.

Taa daa!

That’s it!
Set up a Rails project in the Passenger Preference Pane and try it out! You should see your fully functional Rails app running.

  Posted by Andrés on June 3rd, 2009

Agile web development like teen sex??

According to Daniel Markham, these are the reasons why Agile Project Management is like teenage sex:

  • You always exaggerate how much of it you’re getting;
  • Everybody else seems to be having more than you;
  • When somebody tells you about their experiences, you’re quick to point out that they’re not doing it right;
  • You spend a lot of time reading and thinking about it;
  • It’s very awkward trying to make happen;
  • You can’t wait until you finally get the real deal;
  • Nobody is really doing that much of it anyway.

Check out Dom’s presentation slides on “Selling Agile” from this year’s MeshU.