Latest Entries

What is Fashion?

I love fashion. I especially love tailored suiting. There’s something special about a suit that’s all your own.

I recently saw these two photos. Notice the tucked tie. Neat! (Credit to The Sartorialist and The Sartorially Inclined.)

So what? Nothing really, except this: My first thought of “too much of a pose” has now turned to “hmm, I might actually like this.”

Fashion is fluid. It changes as you change. I wouldn’t have taken to this look but it’s growing on me. What does that say about me?

My favorite jacket is a toirtoise green, Costume National leather biker jacket. But I didn’t wear it for a full year after I bought it. Why? Because I actually thought it was “too cool” for me. I couldn’t genuinely wear it, so I never did. But I love it now. Its only when I appropriately saw it as something that spoke to me at a real level that I took to it. Like the jacket, the tucked tie is in that early stage.

“Real level?” Sounds like horseshit, right? Fashion is surface. Fashion is superficial. Right?

Something changed in me the moment I put on a suit for the first time in my life. It made me feel powerful. It made me feel important. It made me feel good about myself. But most importantly, it made me feel something. And that something was emotional.

I never knew before then that clothing could do that. That clothing, at a certain level, could create an emotional experience. And if you haven’t had that experience with clothing, it’s hard to see the emotional landscape that exists beneath the surface, and therefore to appreciate it.

But that landscape exists all around us. That shirt you wore when you were 15 that represents all that was true and dramatic the summer you wore it and how it all comes back to you when you put it on again. How choosing what you wear every morning is a form of self-expression. How the handmade dress your mom gave you creates a link back to her past. Or the silk scarf your dad always wore that you wear now–the dad that’s not here in this world anymore.

Yes, yes, you don’t need fashion and clothing and all these things in the way you need air or water or your friends and family. This is true. But as I see it, you are born and then you die, and if you’re lucky, you can say during the time in-between, Hey I felt something that time and it spoke to me. I believe there’s value in human experience, and in that experience alone.

I hope one day to meld my interests in technology and fashion. I’d love to give others the chance to feel those things, too.

Meetup.com, Steve Jobs and The Meaning Of Innovation

On April 18th, Sprouter organized their monthly Sprout Up event at The Courthouse. It’s a useful event for those interested in hearing about new startups in Toronto.

April’s keynote was from Matt Meeker, one of the founders of Meetup.com. Matt talked about the inside story of Meetup, how they got started and their journey. The best part of the evening.

Interestingly enough, as Matt was talking, I was reminded of my favorite Steve Jobs talk. It was a talk Jobs gave at age 26, before the Macintosh,  at the Academy of Achievement. In the talk, Jobs defines innovation as “connecting two experiences together” and that true innovation could only be done by people who “go out into the world and get experiences outside the normal course of events.” I always loved this because it speaks directly to things I care about: Human experience over theory; courage; discovering a path that’s truly your own.

Matt talked about two transformative experiences: 9/11 and reading Bowling Alone by Robert Putnam. In “Alone,” Putnam describes the disappearance of community in post-industrial America. Where once Americans participated in at least one social event a week is now reduced to once per month. At the same time, Matt spoke of his first-hand experience of spontaneous community building that sprang immediately after 9/11. About strangers reaching out to others offering help right there on the street. So while America was moving further apart, there was still a craving for meaninful belonging.

As such, Meeker and his cofounders created Meetup to solve this problem. Meetup offered a platform for others to connect in a community again. In other words, Meetup was about connecting two experiences together.

Innovation is a funny word. We often think of it as a Eureka moment, a brief moment of brilliance, a falling apple–an apple with a mind and existence of its own. Matt Meeker’s story taught me again the importance of your own experience.

Sometimes the best ideas are not ahead of you, but right beside you.

The Instagram Sale and What This Tells Us About Design

As we all know, Instagram this week sold to Facebook for a cool $1 billion. Not bad for a 22 person company! Much has been written about the sale. But among all the copy, I thought Om Malik’s article was the most insightful.

Om is right: Facebook bought Instagram partly out of fear and partly to find large scale traction on mobile. Paying $1 billion to fend of a serious competitor by a company valued at close to $100 billion may make sense in the long term. More meaningfully, however, is what Om rightly pointed out as well: People like Facebook, but love Instagram.

How did they do this? After all, Instagram is just a community of photo-takers. My answer: They created a real emotional attachment to the product itself. Beautiful photos for all. Great design. It’s the only app on my iPhone that I love and makes me feel…well, like I can actually take good pictures. It makes me feel good about myself. How many apps on your phone do that?

Square is another company that is showing the world that something as mundane as payment transactions can, with thoughtful design, have a seamless, even beautiful feel to the whole process. Everything from the website, the iPhone app, even the receipts you get, are thoughtfully constructed. I love that. It shows someone cares. It makes you want to use the product and talk about it with others. By making it beautiful, a halo-effect transforms an ordinary experience into an emotional one.

Instagram drove home for me that sometimes mundane sounding tasks can oftentimes become much more  through thoughtful design.

How We Built a HackTO Winning App

HackTO with Team Blu Trumpet

Yesterday, I took part along with my awesome teamates Scott Hyndman and Victor Mota, in HackTO’s April 2012 hackathon as part of the Canada-wide HackDays. We had a great time thinking through the problems and the day was a lot of fun. To boot, our entry LastResort ended up placing first! We all agreed before the winners were announced that the day was a success regardless, but it was a nice icing on the cake. There were a lot of great apps.

After talking with the judges and our own observations about our approach and seeing the other 22 demos, our team brainstormed possible reasons why we placed higher than expected. Here’s what we came up with.

Do your homework

In a hackathon, it’s all about execution. You don’t have time. Non-demoable apps do not make the final cut, so it was crucial we knew what we were getting into before the event.

That’s why the week prior our team sat down to scope possible ideas. We familiarized ourselves with the APIs to get a feel for their range and capabilities. We even played with some of the APIs, making calls and playing with sandbox tokens. You don’t want to waste your time with mundane issues like OAuth that slow you down.

Choose your problem carefully

As mentioned, incomplete apps don’t demo. We made sure we had a problem that was interesting and could be done in seven hours. A completed, less glamorous app is better than an unfinished, ambitious project.

After much discussion, we settled on the following problem: A tool that monitors your existing email stream for critical issues and calls the appropriate support people by phone who can fix them.

The problem had several benefits: it scratched our own itch, so we knew it was useful (utility brownie points); it could be completed in seven hours; we double-checked the APIs were capable of doing what we wanted; and it had the bonus of using more than one of the sponsored APIs (ContextIO for email mining and Twilio for phone calls, both awesome APIs)–which we learned afterward one of the judges appreciated.

Scope the day’s work

Once we had a problem, we scoped out an MVP (Minimum Viable Product) the day before. What is the absolute minimum, demonstratable demo? We decided it was phoning a list of contacts in sequence when a specified email was sent.  That’s it. On the actual day, we hardcoded the contact list and the email was triggered by a manual send during the demo. There was no special phone call behaviour. (You can easily see how features can be added, but again the goal is brevity and speed of execution to the demo.)

We built a mantra on the team: “Build to the MVP.” Anything that sidetracked us was thrown out. It gave our team focus. We knew what the goal was.

We also wrote out the actual tasks we would need to build: github setup, necessary API keys, etc. Then we assigned a team member to each task or component. Again, we made sure items contributed to the MVP. We also made a list of “nice-to-haves” of additional features that we could add on but weren’t critical to the MVP. In the end, we didn’t implement anything off this latter list.

Why did this work? Because everyone on the team knew exactly what they were doing, why they were doing it, and how it all contributed to the end goal. Most importantly, each of us knew what we didn’t need to do, and many times we found ourselves rejecting tasks before getting sucked into time wasting.

Choose a good team

This goes without saying. Scott and I work together at Blu Trumpet and Victor was one of our previous interns. We all like and respect each other and know our strengths and weaknesses. We also have the added benefit of being candid and critical and there was plenty of healthy discussions throughout the day. We were constantly talking with each other, pair programming at times, pitching to help whenever. “Hey, what do you guys think of this? How does this look?” was a common phrase. We were constantly checking in on each other.

We were especially vocal during our presentation prep. We constantly asked ourselves “Is this clear? Can we make this shorter? Can we make this more impactful?” We were quick to point out when one of us was using too many words or when key points were lost. It helped a ton.

It’s next to impossible to churn something out with random people you met that day. What’s true in business is true at hackathons.

Present as if you are pitching to VCs

We made sure we completed at least one hour before the 5pm deadline. Why? We knew a compelling pitch was critical so we left time for it. How you present your product is really, really important. How people perceive your product is the product. Good impressions go a long way.

We put together a three slide Keynote presentation that made sure we (1) defined the problem and explained why it was important to solve it (server downtime is bad bad bad); (2) which audience or “customer segment” our solution served (bootstrapped startups); (3) what our value-adds were (free, developer-friendly).

We spent the final hour going over and over our presentation, timing each time. We couldn’t afford to not finish. This saved the presentation, as a final decision to shorten the demo allowed us to finish exactly in three minutes, without a second to spare (literally).

We also added humour and that never hurts! It was truly a team presentation as Victor and I did the actual presenting while Scott worked the slides and executed the demo.

One final note…

Writing this now everything seems “obvious.” But believe me, we were very close to not finishing. A server failure or API hangup would have cost us and put the whole thing into doubt. My heart was pounding during the presentation and thank goodness everything went as planned. Afterward, we were all surprised how nicely it all came together, as in software this rarely happens!

It’s amazing what you can accomplish in one day. Obviously, you can’t work at this speed everyday. But it was fun participating in a “mini-startup” from end-to-end. And for those thinking of working in the startup world, I highly recommend it.

Fun Tip: How To Crash Parties

It’s a dubious skill, but one nonetheless: I’m pretty good at crashing parties. Some of the highlights include meeting Ron Jeremy in the VIP of Filmore’s; Rosedale pool party with Shawn Hewson of Project Runway; a Bay Street law firm Christmas party, complete with free wine and live band. My latest was crashing a Fashion Week shindig at the One King West Hotel two months ago after leaving work late one night.

I don’t go looking to crash parties (mostly), but rather find them serendipitously. But when I do find something worth checking out, I do like the challenge of it.

So here’s my tips on how to make your evening a memorable one:

Rule #1: Assume you’re already invited. This is key. You can’t appear nervous or that you don’t belong or seem unsure. Just walk in, confident, like you’re part of the crowd. Don’t peak your head in or anything like you’re trying to get a look. People who are invited don’t do that. So just do the same and 90% you are good to go.

Rule #2: Start a conversation with the nearest person you see. I always try and do this. This is a corollary of Rule #1. It’s about blending in so spark up a conversation. Don’t just stand around. Talking with someone also gives you information about the party itself; in the case a bouncer or enforcer asks you what you are doing you can answer. Once this happened and I replied “I’m with Mike!” i.e., Mike the guy I was talking to. They left me alone after that.

Rule #3: Try and find a crowd. Sometimes you won’t get in the first time and getting in with another group can work. I find this less successful, but if you’re personable enough it can work.

Rule #4: If all else fails, find the back door. I almost never have to resort to this, but occasionally there’s a back entrance. At the One West the doorman wouldn’t let me in so I had to go around the hotel to the private elevator entrance (entering with an actual, unsuspecting guest) and just followed the music and walked in. I had to go up a few floors, but the music was loud enough that I knew which floor to get off of.

Happy crashing!

Beginner’s Mind: My First Months Meditating

For the longest time I associated meditation with hippies and strange “spiritualists” and all that, and if you asked me two years ago about meditation I would have dismissed it immediately.

But like all things in life, if you dig deep enough you’ll discover a richness not visible from the surface. Meditation is no different.

“Beginner’s Mind” refers to the state of mind when, starting something new, you see everything for the first time, fresh. Over time you lose this freshness as new models occupy your mind as you evolve your understanding about a discipline. So for posterity’s sake and my own dismal memory, I’ve collected my first impressions here before I forget.

How I Started Meditating

I started meditation on a regular basis in October 2011. I tried meditation in early 2011, but it was a complete failure. I hated it. I quit after a week. My restlesness got the better of me and I found it almost impossible to concentrate.

But like a good restaurant, I kept hearing good things about it. By chance in July of 2011 I moved into an awesome house in Kensington Market. One of my roomates, Jeff Warren, had the idea to turn our house into a kind of community salon, with movie nights, special events and kick-ass parties. Out of this came the Conciousness Explorers Club, a Monday group meditation in our living room.

We’ve been lucky enough to have as many as 30 people in our house and have such masters as Shinzen Young give a guided meditation. We even had a giant 40-inch gong as part of a sound meditation one time (thanks Adam!). That was pretty cool.

Things just kind of snowballed with the house and soon enough I was meditating regularly and with a new purpose.

What is Meditation?

At its lowest level, meditation is taking the skill of concentration and applying it inward. That’s what people do when they meditate. The object of concentration may vary between sounds, visuals, emotions, physical body-sensations or other things, but the basic premise is unchanged.

What is so amazing is that this simple insight can lead you down a path of infinite exploration. You can take it as a way to improve concentration power–but also as a way to springboard yourself into the very nature of the universe. If you’re really ambitious, as a way to reach Enlightenment itself. This sounds nebulous, I know, but I’ll explain below.

My Practice

I average four to five 20 to 30 minute meditation sessions a week. They’re done in the mornings when I wake up. I use Insight Timer on my iPhone for timing and note taking.

My training is in a tradition called “Vipasana” as taught by Shinzen Young or “mindfulness” to use a laymen’s term. Shinzen’s practice appeals to me because it’s direct, clear and mixes science into a framework I can understand. I love frameworks and systems. (I’m a computer programmer by profession.)

Currently all my techniques are “noting” techniques: focussed concentration on visual, auditory or bodily/emotional sensations. The goal of these techniques is to raise my baseline competence in three areas: concentration power, sensory clarity and equanimity.

As an example, I might practice “See In.” This involves closing my eyes and noting images that I “see” inside my head. I will mentally say to myself “see in” every time I see an image. In the absense of images I say “see rest.” I also try to note the vanishing of an image by saying “gone.” The noting improves concentration. Sensory clarity is boosted by practicing the very act of “seeing.” The more I practice seeing, the clearer the mental images become. You can see how this technique can be applied to other sensory experiences.

The equanimity part is the hardest for me. Equanimity is practiced by using a calm, leveled voice when I say “see in.” More importantly, it’s done by slowly and calmy bringing my attention back to the noting whenever a “random” image or thought suddently enters my mind. This is where it gets challenging because this happens a lot. More than you think. In fact, my mind is constantly being pulled away from my meditation to mundane thinks like work, groceries, pain, hunger, why I’m feeling sad or tired, movie times, sports scores, how I am doing in my fantasy pool, etc. Pretty chaotic!

What I’ve Learned

The first thing I’ve learned is how much I’m not in control. I’m amazed how my mind veers from random thought to random thought. Or how easily bored it becomes.

My mind, I discovered, is obsessed with the future. I don’t think much of the past but I do agonize about things I “need” to do. Or things I’m not doing enough of. Almost always about work or personal projects. Interestingly enough, my “feel in” technique helped me link the emotion of anxiety with this preoccupation. This is something I’ll be working on.

For a long time I saw the world in one way: A world broken up as processes that just needed to be identified to be understood. Analytical. Like sticking a pin in a butterfly.

I really didn’t have any experience to think otherwise. It served me, and continues to serve me, well. I love systems. But…there’s another way of seeing. Another way of knowing.

And that is there’s a whole swash of human experience that’s not based on any system but rather is a kind of patient waiting. You have to believe, somehow, somewhere, in your gut, that it’s all going to come together for you.  Waiting in grace.

Love, compassion…these things don’t have roadmaps. You just have to have faith that if you water the lawn some flowers will grow. Meditation is a kind of watering of the lawn, so to speak.

Why I Do It

My original intent was to improve my concentration so I could be better at my job. It was becoming harder to concentrate at work so I hoped meditation would help.

The overarching reason, however, is that I hate the idea of my mind settling into any kind of pattern that doesn’t serve me. I like the challenge of blowing away something I might have believed to be true. If you can let go of old habits and make way for better ones, why wouldn’t you? I never want to stop learning. Consistency is the most overrated virtue.

Nudges, Defaults and the Success of Rails

Humans are lazy. You didn’t need me to tell you that. Status quo bias and inertia constantly work against our better judgement to learn and improve.

In Richard Thaler and Cass Sunstein’s fascinating book Nudge: Improving Decisions About Health, Wealth, and Happiness the two researchers explore how certain psychological triggers and observations can be used to design choices to persuade and “nudge” people to desirable behaviours. One of those observations is the use of defaults.

Default choices are a powerful but simple way to nudge behaviour. Opt-out defaults for magazine subscriptions work wonderfully, as Thaler and Sunstein point out: people continue to pay even when they stop reading. More dramatically, opt-out 401(k) company plans have more than double the savings rates than opt-in plans. When given the choice to do nothing, most will.

As a software developer, this got me thinking: What kind of defaults can I design that will nudge my users to behaviours I find desirable?

It hit me that the influence of defaults went beyond asking the question. Defaults in fact are a big reason that my professional life is easier and more enjoyable than it was before. And I have Rails to thank for that.

Rails is filled with defaults. This is one of the main reason for its success. Someone, somewhere decided that 80% of things developers deliberate on don’t matter. How to structure an application, how to setup a database, which server to test against—there are defaults for all of these and they work out-of-the box for most developers. There’s even a phrase for this: Convention over configuration.

David Heinemeier Hansson, the creator of Rails, had this to say at RailsConf 2008:

One of the points I keep coming back to with Ruby on Rails, is that we confess commonality. That we confess that we’re not as special as we like to believe. We confess that we’re not the only ones climbing the same mountain…I think the conclusion—the conclusion that we’re not as special and unique as we like to believe—is the fact that the flexibility we think we need, we want—we really don’t.

By designing defaults intelligently, Rails was able to hit that sweet spot of doing as much work for you, while enabling it to get out of the way when needed. I’ve had experienced Rails developers echo this very thing. It goes to show that as something as influential as Rails, defaults can have a big impact.

Digging Into RubyGems

Every developer has experienced an episode of painful dependency management. Missing libs, “dll hell,” and hours of wasted effort. Been there. It’s painful.

Luckily for those working in the Ruby ecosystem, there is a nice tool that helps with dependency management: RubyGems.

In this post we’ll dive a little deeper into how RubyGems works with your Ruby code to properly load and manage gems. Understanding the load process will better prepare you when things go wrong (and things will, won’t they?) It will also give you insights into how to hook and innovate outside the normal RubyGems’s behaviour if you so choose.

Ruby’s $LOAD_PATH or Where’s my library?!

When you load a dependency via Ruby’s require or load, where does Ruby go to fetch that library? Answer: $LOAD_PATH.

Ruby’s $LOAD_PATH is an array of directories that Ruby will search in to find and load dependencies.

This is what my Mac OS X system Ruby’s $LOAD_PATH looks like (Ruby 1.8.7):

$ irb
irb> $LOAD_PATH
=> ["/opt/local/lib/ruby/site_ruby/1.8", "/opt/local/lib/ruby/site_ruby/1.8/i686-darwin10",
"/opt/local/lib/ruby/site_ruby", "/opt/local/lib/ruby/vendor_ruby/1.8", "/opt/local/lib/ruby/vendor_ruby/1.8/i686-darwin10", "/opt/local/lib/ruby/vendor_ruby", "/opt/local/lib/ruby/1.8", "/opt/local/lib/ruby/1.8/i686-darwin10","."]

When I require 'myfile' in my Ruby code (if I am running my system 1.8.7 version), Ruby will try and find the file myfile.rb in one of the directories above and run it. If not, it will raise a LoadError exception.

At a crude level, you could manually drop dependencies in the $LOAD_PATH to load libraries. But programmers are lazy and that’s a lot of work. Wouldn’t it be cool if there was a tool to manage gems for you?

Enter RubyGems.

RubyGems: Painless dependency management

RubyGems is a tool to discover, distribute, manage and build gems. When you install RubyGems (http://docs.rubygems.org/read/chapter/3), it does two things: it writes the source to one of the directories in Ruby’s $LOAD_PATH so you can require 'rubygems' in Ruby and installs the command line tool gem to help manage the gems themselves. They work together: by installing gems in a standard place, RubyGems can then work more intelligently about how to make libraries accessible from Ruby.

After I installed RubyGems 1.6.2, I see that rubygems.rb was installed in /opt/local/lib/ruby/site_ruby/1.8, which is part of the $LOAD_PATH. The gem command line tool was installed in /opt/local/bin.

Furthermore, the gem command tool I use to install gems has the following environment setup:

$ gem environment
RubyGems Environment:
- RUBYGEMS VERSION: 1.6.2
- RUBY VERSION: 1.8.7 (2010-01-10 patchlevel 249) [i686-darwin10]
- INSTALLATION DIRECTORY: /opt/local/lib/ruby/gems/1.8
- RUBY EXECUTABLE: /opt/local/bin/ruby
- EXECUTABLE DIRECTORY: /opt/local/bin
- RUBYGEMS PLATFORMS:
- ruby
- x86-darwin-10
- GEM PATHS:
- /opt/local/lib/ruby/gems/1.8
- /Users/iha/.gem/ruby/1.8
- GEM CONFIGURATION:
- :update_sources => true
- :verbose => true
- :benchmark => false
- :backtrace => false
- :bulk_threshold => 1000
- REMOTE SOURCES:
- http://rubygems.org/

Notice the value of INSTALLATION DIRECTORY; that’s where my gems are installed when I run gem install name_of_a_gem. How does RubyGems decide to put gems there? It’s relative to where the ruby executable directory is, which in my case is in /opt/local/bin/.

No wasted effort deciding for yourself where to put gems, the gem tool decides for you. You’ll notice too that it’ll try and find gems from the remote site http://rubygmes.org, a popular gem hosting site. Nice!

Let’s go ahead and install Nokogiri, a popular XML parser, from rubygems.org.

$ gem install nokogiri # go off to remote source http://rubygems.org
...
$ gem list</code>

*** LOCAL GEMS ***

nokogiri (1.4.4)

Great! We just installed our first gem. And going to the install directory we notice:

$ cd /opt/local/lib/ruby/gems/1.8/gems
$ ls
nokogiri-1.4.4/

as expected by the gem command-line tool’s environment.

Let’s run some Ruby code via irb and require Nokogiri.

$ irb
irb> require 'nokogiri'
LoadError: no such file to load -- nokogiri
from (irb):1:in `require'
from (irb):1
from :0

As expected, it can’t find Nokogiri, since the Nokogiri gem was installed in /opt/local/lib/ruby/gems/1.8/gems/nokogiri-1.4.4/, which is not in $LOAD_PATH, so Ruby can’t find it. To make installed gems accessible from Ruby we first have to load RubyGems (recall rubygems.rb is in the $LOAD_PATH):

irb> require 'rubygems'
=> true
irb> require 'nokogiri'
=> true

Success! We just loaded our first gem.

At this point, we might reasonably assume that RubyGems has placed Nokogiri in $LOAD_PATH, which is why require 'nokogiri' now works, but this is not the case. In fact, $LOAD_PATH has not changed at all:

irb> $LOAD_PATH
=> ["/opt/local/lib/ruby/gems/1.8/gems/nokogiri-1.4.4/lib", "/opt/local/lib/ruby/site_ruby/1.8", "/opt/local/lib/ruby/site_ruby/1.8/i686-darwin10", "/opt/local/lib/ruby/site_ruby", "/opt/local/lib/ruby/vendor_ruby/1.8", "/opt/local/lib/ruby/vendor_ruby/1.8/i686-darwin10", "/opt/local/lib/ruby/vendor_ruby", "/opt/local/lib/ruby/1.8", "/opt/local/lib/ruby/1.8/i686-darwin10", "."]

If $LOAD_PATH is unchanged, how were we able to require Nokogiri?? By overriding require.

Looking at the source, we notice that RubyGems 1.6.2 has done exactly that:

#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++

module Kernel

 if defined?(gem_original_require) then
    # Ruby ships with a custom_require, override its require
    remove_method :require
  else
    ##
    # The Kernel#require from before RubyGems was loaded.

    alias gem_original_require require
    private :gem_original_require
  end

  ##
  # When RubyGems is required, Kernel#require is replaced with our own which
  # is capable of loading gems on demand.
  #
  # When you call require 'x', this is what happens:
  # * If the file can be loaded from the existing Ruby loadpath, it
  # is.
  # * Otherwise, installed gems are searched for a file that matches.
  # If it's found in gem 'y', that gem is activated (added to the
  # loadpath).
  #
  # The normal require functionality of returning false if
  # that file has already been loaded is preserved.

  def require path
 if Gem.unresolved_deps.empty? or Gem.loaded_path? path then
      gem_original_require path
    else
      spec = Gem.searcher.find_active path

      unless spec then
        found_specs = Gem.searcher.find_in_unresolved path
        unless found_specs.empty? then
          found_specs = [found_specs.last]
        else
          found_specs = Gem.searcher.find_in_unresolved_tree path
        end

        found_specs.each do |found_spec|
          # FIX: this is dumb, activate a spec instead of name/version
          Gem.activate found_spec.name, found_spec.version
        end
      end

      return gem_original_require path
    end
  rescue LoadError =&gt; load_error
 if load_error.message.end_with?(path) and Gem.try_activate(path) then
      return gem_original_require(path)
    end

    raise load_error
  end

  private :require

end

Requiring RubyGems loads the Gem module which has it’s own internal path array. This array is used by the overridden require method to search for installed gems, in addition to looking in $LOAD_PATH.

That path is:

irb> Gem.all_load_paths
=> ["/opt/local/lib/ruby/gems/1.8/gems/nokogiri-1.4.4/lib"]

So we see the path to Nokogiri in the Gem module’s internal path, which is used in the overwritten require to search for gems. The Gem module constructs this array by going into the default gem respository (in this case /opt/local/lib/ruby/gems/1.8) and writes the absolute path to the lib directory of each gem into the array, as well as any gem-specific load paths defined in the .gemspec file of each gem. You can override the default gem repository by defining the environment variable $GEM_PATH.

This explains how we were able to require Nokogiri without changing $LOAD_PATH.

So now we see the big picture: Manage gems via the gem command-line tool; require 'rubygems' and then require any gem in Ruby after that.

Ruby 1.9

As of Ruby 1.9, you no longer need to explicitly require 'rubygems' as it’s now baked right into Ruby. However, if you are running 1.8, be careful of literring your code with require 'rubygems' all over as some prominent Rubyists have argued (https://gist.github.com/54177)–and I believe rightly–that it unecessarily couples your code to RubyGems, which is really a environment setup configuration.

The workaround is to set the RUBYOPT environment variable to ‘rubygems’ so that Ruby will run with ‘-rubygems’ as an option to automatically load RubyGems on startup.

Conclusion or The Path To Enlightenment

It might have occurred to you that despite my plug for RubyGems, there’s a problem. By default require 'nokogiri' pulls the latest gem from your gem repo. But what if I have different versions of Nokogiri? And what if my code needs to load different versions depending on some condition (say, testing versus development)?

Luckily there’s an answer: Bundler. We’ll explore Bundler and versioned dependency management in Rails in our next post. But in the meantime, you can require RubyGems and make your life that more painless for now.



Copyright © 2004–2009. All rights reserved.

RSS Feed. This blog is proudly powered by Wordpress and uses Modern Clix, a theme by Rodrigo Galindez.