Yehuda Katz is a member of the Ember.js, Ruby on Rails and jQuery Core Teams; he spends his daytime hours at the startup he founded, Tilde Inc.. Yehuda is co-author of best-selling jQuery in Action and Rails 3 in Action. He spends most of his time hacking on open source—his main projects, like Thor, Handlebars and Janus—or traveling the world doing evangelism work. He can be found on Twitter as @wycats and on Github.

Ruby 2.0 Refinements in Practice

First Shugo announced them at RubyKaigi. Then Matz showed some improved syntax at RubyConf. But what are refinements all about, and what would they be used for?

The first thing you need to understand is that the purpose of refinements in Ruby 2.0 is to make monkey-patching safer. Specifically, the goal is to make it possible to extend core classes, but to limit the effect of those extensions to a particular area of code. Since the purpose of this feature is make monkey-patching safer, let’s take a look at a dangerous case of monkey-patching and see how this new feature would improve the situation.

A few months ago, I encountered a problem where some accidental monkey-patches in Right::AWS conflicted with Rails’ own monkey-patches. In particular, here is their code:

unless defined? ActiveSupport::CoreExtensions
  class String #:nodoc:
    def camelize()
      self.dup.split(/_/).map{ |word| word.capitalize }.join('')
    end
  end
end

Essentially, Right::AWS is trying to make a few extensions available to itself, but only if they were not defined by Rails. In that case, they assume that the Rails version of the extension will suffice. They did this quite some time ago, so these extensions represent a pretty old version of Rails. They assume (without any real basis), that every future version of ActiveSupport will return an expected vaue from camelize.

Unfortunately, Rails 3 changed the internal organization of ActiveSupport, and removed the constant name ActiveSupport::CoreExtensions. As a result, these monkey-patches got activated. Let’s take a look at what the Rails 3 version of the camelize helper looks like:

class String
  def camelize(first_letter = :upper)
    case first_letter
      when :upper then ActiveSupport::Inflector.camelize(self, true)
      when :lower then ActiveSupport::Inflector.camelize(self, false)
    end
  end
end
 
module ActiveSupport
  module Inflector
    extend self
 
    def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
      if first_letter_in_uppercase
        lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
      else
        lower_case_and_underscored_word.to_s[0].chr.downcase + camelize(lower_case_and_underscored_word)[1..-1]
      end
    end
  end
end

There are a few differences here, but the most important one is that in Rails, “foo/bar” becomes “Foo::Bar”. The Right::AWS version converts that same input into “Foo/bar”.

Now here’s the wrinkle. The Rails router uses camelize to convert controller paths like “admin/posts” to “Admin::Posts”. Because Right::AWS overrides camelize with this (slightly) incompatible implementation, the Rails router ends up trying to find an “Admin/posts” constant, which Ruby correctly complains isn’t a valid constant name. While situations like this are rare, it’s mostly because of an extremely diligent library community, and a general eschewing of applying these kinds of monkey-patches in library code. In general, Right::AWS should have done something like Right::Utils.camelize in their code to avoid this problem.

Refinements allow us to make these kinds of aesthetically pleasing extensions for our own code with the guarantee that they will not affect any other Ruby code.

First, instead of directly reopening the String class, we would create a refinement in the ActiveSupport module:

module ActiveSupport
  refine String do
    def camelize(first_letter = :upper)
      case first_letter
        when :upper then ActiveSupport::Inflector.camelize(self, true)
        when :lower then ActiveSupport::Inflector.camelize(self, false)
      end
    end
  end
end

What we have done here is define a String refinement that we can activate elsewhere with the using method. Let’s use the refinement in the router:

module ActionDispatch
  module Routing
    class RouteSet
      using ActiveSupport
 
      def controller_reference(controller_param)
        unless controller = @controllers[controller_param]
          controller_name = "#{controller_param.camelize}Controller"
          controller = @controllers[controller_param] =
            ActiveSupport::Dependencies.ref(controller_name)
        end
        controller.get
      end      
    end
  end
end

It’s important to note that the refinement only applies to methods physically inside the same block. It will not apply to other methods in ActionDispatch::Routing::RouteSet defined in a different block. This means that we can use different refinements for different groups of methods in the same class, by defining the methods in different class blocks, each with their own refinements. So if I reopened the RouteSet class somewhere else:

module ActionDispatch
  module Routing
    class RouteSet
      using RouterExtensions
 
      # I can define a special version of camelize that will be used
      # only in methods defined in this physical block
      def route_name(name)
        name.camelize
      end
    end
  end
end

Getting back to the real-life example, even though Right::AWS created a global version of camelize, the ActiveSupport version (applied via using ActiveSupport) will be used. This means that we are guaranteed that our code (and only our code) uses the special version of camelize.

It’s also important to note that only explicit calls to camelize in the physical block will use the special version. For example, let’s imagine that some library defines a global method called constantize, and uses a camelize refinement:

module Protection
  refine String do
    def camelize()
      self.dup.split(/_/).map{ |word| word.capitalize }.join('')
    end
  end
end
 
class String #:nodoc:
  using Protection
 
  def constantize
    Object.module_eval("::#{camelize}", __FILE__, __LINE__)
  end
end

Calling String#constantize anywhere will internally call the String#camelize from the Protection refinement to do some of its work. Now let’s say we create a String refinement with an unusual camelize method:

module Wycats
  refine String do
    def camelize
      result = dup.split(/_/).map(&:capitalize).join
      "_#{result}_"
    end
  end
end
 
module Factory
  using Wycats
 
  def self.create(class_name, string)
    klass = class_name.constantize
    klass.new(string.camelize)
  end
end
 
class Person
  def initialize(string)
    @string = string
  end
end
 
Factory.create("Person", "wycats")

Here, the Wycats refinement should not leak into the call to constantize. If it did, it would mean that any call into any method could leak a refinement into that method, which is the opposite of the purpose of the feature. Once you realize that refinements apply lexically, they create a very orderly, easy to understand way to apply targeted monkey patches to an area of code.

In my opinion, the most important feature of refinements is that you can see the refinements that apply to a chunk of code (delineated by a physical class body). This allows you to be sure that the changes you are making only apply where you want them to apply, and makes refinements a real solution to the general problem of wanting aesthetically pleasing extensions with the guarantee that you can’t break other code. In addition, refinements protect diligent library authors even when other library authors (or app developers) make global changes, which makes it possible to use the feature without system-wide adoption. I, for one, am looking forward to it.

Postscript

There is one exception to the lexical rule, which is that refinements are inherited from the calling scope when using instance_eval. This actually gives rise to some really nice possibilities, which I will explore in my next post.

What’s Wrong with “HTML5″

In the past year or so, the term “HTML5″ has increasingly been picked up by the tech press as the successor to “DHTML”, “Web 2.0″ or “Ajax”. When used by the tech press, it is becoming a generic term for “the next generation of web technology”, except that the term “HTML5″ is less precise than even that.

Consider the first paragraph of an article about HTML published this week:

HTML5 is the hot topic nowadays. Everyone from Apple to Google and everyone else in between have shown their support for the standard. Word has it that HTML5 is the Adobe Flash-killer. It seems that the World Wide Web Consortium [W3C] — which is the main international standards organization for the World Wide Web — doesn’t agree. If anything, the W3C doesn’t think that HTML5 is “ready for production yet.”

The problem with HTML5 appears to be that it currently lacks a video codec. In addition, digital rights management [DRM] is also not supported in HTML5, which obviously makes a problem for various companies.

My engineer friends have all but given up on pushing back against the “HTML5″ moniker. After all, it’s just a term for the tech press. Everyone who knows anything understands that it means just as little as requests for “Ajaxy animations” a few years back, right? I had started to agree with this line of reasoning. It’s true: there’s no point in being pedantic on this front for the sake of being pedantic.

Unfortunately, the term, and therefore the way the technology is understood by tech writers, is causing some fairly serious problems.

First, keep in mind that unlike “Ajax” or “Web 2.0″, which were pretty benign, vague terms, HTML5 sounds like a technology. It can have “beta” versions, and one day it will be “complete” and “ready for production”. Take a look at this snippet from an InfoWorld article:

His advice on HTML5 was endorsed by industry analyst Al Hilwa of IDC.

“HTML 5 is at various stages of implementation right now through the Web browsers. If you look at the various browsers, most of the aggressive implementations are in the beta versions,” Hilwa said. “IE9 (Internet Explorer 9), for example, is not expected to go production until close to mid-next year. That is the point when most enterprises will begin to consider adopting this new generation of browsers.”

And because HTML5 is portrayed as a “Flash killer”, whether it is “complete” or in “beta” sounds really relevant. In comparison, “Web 2.0″ was never portrayed as a technology, but rather the ushering in of a new era of web technologies which would allow people to build new kinds of applications.

The truth is, the “completion” of HTML5 is absolutely irrelevant. At some point, the W3C will approve the HTML5 spec, which will mean nothing about the overall availability of individual features. At some point, the other related specs (like Web Storage and Web Sockets) will be approved, and also mean nothing about the overall availability of individual features.

In response to this conundrum, most of my friends immediately throw out the idea of getting more specific with the tech press. And they’re right. The tech press is not going to understand Web Sockets or local storage. They’re having trouble even grasping HTML5 video.

The thing is, the core problem isn’t that the name is too fuzzy. It’s what the name implies. HTML5 sounds like a technology which goes through a beta period and is finally complete. Instead, what the tech press calls “HTML5″ is really a continual process of improving the web browsers that people use. And honestly, that’s how I’d like to see the tech press cover us. Not as group of people working towards a singular milestone that will change the web as we know it, but as a group that has gotten our groove back.

Tech reporters: please stop talking about the current state of web technologies as an event (the approval of the HTML5 spec). There are interesting stories happening all the time, like Scribd, YouTube, and Gmail leveraging newer web technologies to improve their products. Little guys are doing the same every day. Not everything is about whether “Flash is dead yet”. It’s worth talking about the tradeoffs that guys like Hulu make, which prevent them from moving to web technologies. But make no mistake: large swaths of the web will be using next-generation browser features well before the last guy does. The process of getting there is an interesting story, and one you should be covering.

Bundler: As Simple as What You Did Before

One thing we hear a lot by people who start to use bundler is that the workflow is more complicated than it used to be when they first start. Here’s one (anonymized) example: “Trying out Bundler to package my gems. Still of the opinion its over-complicating a relatively simple concept, I just want to install gems.”

Bundler has a lot of advanced features, and it’s definitely possible to model fairly complex workflows. However, we designed the simple case to be extremely simple, and to usually be even less work than what you did before. The problem often comes when trying to handle a slightly off-the-path problem, and using a much more complex solution than you need to. This can make *everything* much more complicated than it needs to be.

In this post, I’ll walk through the bundler happy path, and show some design decisions we made to keep things moving as smoothly as before, but with far fewer snags and problems than the approach you were using before. I should be clear that there are probably bugs in some cases when using a number of advanced features together, and we should fix those bugs. However, they don’t reflect core design decisions of bundler.

In the Beginning

When you create a Rails application for the first time, the Rails installer creates a Gemfile for you. You’ll note that you don’t actually have to run bundle install before starting the Rails server.

$ gem install rails
Successfully installed activesupport-3.0.0
Successfully installed builder-2.1.2
Successfully installed i18n-0.4.1
Successfully installed activemodel-3.0.0
Successfully installed rack-1.2.1
Successfully installed rack-test-0.5.6
Successfully installed rack-mount-0.6.13
Successfully installed tzinfo-0.3.23
Successfully installed abstract-1.0.0
Successfully installed erubis-2.6.6
Successfully installed actionpack-3.0.0
Successfully installed arel-1.0.1
Successfully installed activerecord-3.0.0
Successfully installed activeresource-3.0.0
Successfully installed mime-types-1.16
Successfully installed polyglot-0.3.1
Successfully installed treetop-1.4.8
Successfully installed mail-2.2.6.1
Successfully installed actionmailer-3.0.0
Successfully installed thor-0.14.2
Successfully installed railties-3.0.0
Successfully installed rails-3.0.0
22 gems installed
$ rails s
=> Booting WEBrick
=> Rails 3.0.0 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2010-09-30 12:25:51] INFO  WEBrick 1.3.1
[2010-09-30 12:25:51] INFO  ruby 1.9.2 (2010-08-18) [x86_64-darwin10.4.0]
[2010-09-30 12:25:51] INFO  WEBrick::HTTPServer#start: pid=26380 port=3000

If you take a look at your directory, you’ll see that Bundler noticed that you didn’t yet have a Gemfile.lock, saw that you had all the gems that you needed already in your system, and created a Gemfile.lock for you. If you didn’t have a necessary gem, the Rails server would error out. For instance, if you were missing Erubis, you’d get Could not find RubyGem erubis (~> 2.6.6). In this case, you’d run bundle install to install the gems.

As you can see, while bundler is providing some added features for you. If you take your application to a new development or production machine with the Gemfile.lock, you will always use exactly the same gems. Additionally, bundler will resolve all your dependencies at once, completely eliminating the problem exemplified by this thread on the Rails core mailing list. But you didn’t have to run bundle install or any bundle command unless you were missing some needed gems. This makes the core experience of bundler the same as “I just want to install gems”, while adding some new benefits.

Adding Gems

When you add a gem that is already installed on your system, you just add it to the Gemfile and start the server. Bundler will automatically pick it up and add it to the Gemfile.lock. Here again, you don’t need to run bundle install. To install the gem you added, you can run bundle install or you can even just use gem install to install the missing gems.

Once again, while bundler is handling a lot for you behind the scenes (ensuring compatibility of gems, tracking dependencies across machines), if you have all the gems that you need (and specified in your Gemfile) already installed on your system, no additional commands are required. If you don’t, a simple bundle install will get you up to date.

Deployment

After developing your application, you will probably need to deploy it. With bundler, if you are deploying your application with capistrano, you just add require "bundler/capistrano" to your deploy.rb. This will automatically install the gems in your Gemfile, using deployment-friendly settings. That’s it!

Before bundler, you had two options:

  • Most commonly, “make sure that all the gems I need are on the remote system”. This could involve including the gem install in the capistrano task, or even sshing into the remote system to install the needed gems. This solution would work, but would often leave no trail about what exactly happened. This was especially problematic for applications with a lot of dependencies, or applications with sporadic maintenance
  • Using the GemInstaller gem, which allowed you to list the gems you were using, and then ran gem install on each of the gems. Heroku used a similar approach, with a .gems manifest. While this solved the problem of top-level dependencies, it did not lock in dependencies of dependencies. This caused extremely common problems with rack and activesupport, and a long tail of other issues. One particularly egregious example is DreamHost, which directs users to use a brittle patch to Rails

In both of these cases, there was no guarantee that the gems you were using in development (including dependencies of dependencies like Rack and Active Support) remained the same after a deploy. One recent example that I saw was that carrierwave added an updated dependency on the newest activesupport, which depends on Ruby 1.8.7. Without making any change to his .gems manifest, Heroku failed to deploy his application on their Ruby 1.8.6 stack.

With bundler, this sort of problem can never happen, because you’re always running exactly the same versions of third-party code in production as you are in development and staging. This should increase your confidence in deployments, especially when you come back to an application months after it was originally developed.

Tweaked Gems

Some times, you will need to make small changes to one of your dependencies, and deploy your application with those changes. Of course, in some cases you can make the tweaks via monkey-patching, but in other cases, the only real solution is to change the gem itself.

With bundler, you can simply fork the gem on Github, make your changes, and change the gem line in your Gemfile to include a reference to the git repository, like this:

# change this
gem "devise"
 
# to this
gem "devise", :git => "git://github.com/plataformatec/devise.git"

This behaves exactly the same as a gem version, but uses your tweaks from Github. It participates in dependency resolution just like a regular gem, and can be installed with bundle install just like a regular gem. Once you’ve added a git repository, you run bundle install to install it (since the normal gem command can’t install git repositories).

You can use :branch, :tag, or :ref flags to specify a particular branch, tag or revision. By default, :git gems use the master branch. If you use master or a :branch, you can update the gem by running bundle update gem_name. This will check out the latest revision of the branch in question.

Conclusion

Using bundler for the sorts of things that you would have handled manually before should be easier than before. Bundler will handle almost all of the automatable record-keeping for you. While doing so, it offers the incredible guarantee that you will always run the same versions of third-party code.

There are a lot of advanced features of Bundler, and you can learn a lot more about them at the bundler web site.

Here’s to the Next 3 Years

I officially joined Engine Yard on January 1, 2008, about a week before we announced our Series A funding, becoming its twenty-second employee. I was Engine Yard’s very first “Engineering” hire, and I would spend the next year working on Ezra’s Merb project, finally releasing Merb 1.0 at MerbCamp that October.

When I joined Engine Yard, I had already been working on the jQuery project for a couple years, having started visualjquery.com at a time in jQuery’s history before jQuery had version numbers. I learned a lot from John Resig about building and motivating open source communities, and I did my first professional work writing jQuery in Action.

The Merb project was my first full-time open source work, and I met some of my earliest open source friends while working on it. When I first met Carl, he was working on a rewrite of the Merb router, the one part of Merb I was still scared to work on. I met Andy Delcambre, who now works on Engine Yard’s AppCloud, after he volunteered to help with Merb.

I met Loren Segal, well-known for the YARD documentation tool, while working to give Merb documentation I could be proud of. And I became the first Github user outside of Chris, PJ and Tom in order to get the Merb project on git. If you’re paying attention, that made me Github user nil.id, and was the source of some hilarious bugs.

In Hampton Catlin’s first Ruby survey in 2008, about one in eight respondents said that they preferred Merb, and by the end of the year, the Rails and Merb teams were coming to blows. During this same time, Engine Yard had taken on a Series B round of funding (this time for $15 million), and had grown from a small company of a couple dozen to a company pushing 100. We had Sales and Marketing departments. We also had an Engineering department, which had spent a large part of the year on our first fully automated product, Engine Yard Solo.

On a personal level, I started getting heavily involved in Open Source other than Merb, especially DataMapper and Rubinius. I started speaking at conferences, starting with a talk on DataMapper at MountainWest RubyConf in 2008. Engine Yard also threw its first Hackfest at that event, an event we would repeat in 2009 and again in 2010. This event, and the work our great community marketing, Open Source and support teams would do over the next several years elevated Engine Yard’s reputation as a team of experts that would keep your app running no matter what.

As Engine Yard grew, a lot of people asked us why we were supporting Merb when so much of our business depended on the success of the Rails community. By late 2008, it was probably the most common question I got when speaking at conferences. In truth, the best I could tell was that Engine Yard was worried about the future of Rails, and wanted to make sure that Ruby remained successful. What we didn’t realize at the time was that the one full-time employee (me) that Engine Yard had on Merb was more than the total number of worldwide full-time developers on Rails. In short, Rails was a fully volunteer project, and that had something to do with some of the issues that drove people to Merb in the first place.

At the end of 2008, Tom Mornini, the CTO of Engine Yard, recognized that if we could join forces (and this was definitely a big if), we could help shore up Rails into the future. I remember the first time Tom asked me about it in the stairwell of our South Park office. I thought he was off the wall to even suggest it. After all, it didn’t seem like the teams could get along at all. But the Merb team had adopted so much of the Rails philosophy that at its core, the only question that remained was how aggressive the Rails project would get to clean things up.

In the years since Ezra first announced Merb, Rails had gotten thread-safe, Rack support, and some improvements to the internals. After hashing out the details (in some very contentious conversations), we decided to give it a try, announcing we would merge the projects on December 23, 2008. That announcement quite literally changed the trajectory of my life. In the almost two years since that announcement, I have worked harder than I have ever worked before, and am more proud of the work I have done than I have ever been before.

Perhaps more importantly, I have worked with some of the best open source developers in the business without whom Rails 3 would have been a pale shadow of itself. Including me, Rails 3 brought on eight new committers. The Rails 3 project did more than improve the quality of the codebase: it reinvigorated the community of developers actively contributing. And by moving toward a model that allowed Rails to have more dependencies, Rails became the center of a thriving Ruby community, where anyone can reuse the code that makes Rails tick for their non-Rails projects.

In the summer of 2009, José Valim became a Google Summer of Code student dedicated to rewriting the Rails generators so that users of DataMapper, RSpec, and Haml could use the standard Rails generators. A lot of people thought it was too optimistic to do in a summer, but José finished the job well before the end of the summer, giving him time to continue his contributions.

Around the same time, Mikel Lindsaar decided to write a ground-up mail implementation, releasing the imaginatively named mail gem in October 2009. This project, which involved writing a parser that could parse the gigabytes of mail in the Trec and Enron email databases, strained credulity, and would enable us to give ActionMailer the facelift it needed for Rails 3.0.

Santiago Pastorino showed up out of nowhere, with a level of pluck that is rarely seen in the Ruby community. Despite a noticeable language barrier, Santiago went from a warning fixer to a Rails committer. This month, he became an official member of the Rails core team. While working on Rails, I learned a lot from a lot of people, but Santiago’s raw determination and skill should stand out as an example to the Ruby community.

Everyone knows Aaron Patterson, and I was just as surprised as everyone else when he started the long, dedicated task of improving the performance of the Arel library. He already has quite the reputation in the Ruby community, and even has commit access to Ruby itself, so I’m personally gratified to work with him on Rails. If you haven’t yet watched it, watch his Worst Ideas Ever presentation from RubyConf last year. Be prepared to laugh.

Xavier Noria has been a one-man documentation machine, helping to grow and maintain the Rails guides, and constantly reminds everyone that documentation is just as essential to the codebase as tests. Without him, Rails 3 might have been great internally, but nobody would know it. Documentation folks often get little love in open source projects, but to me, the work Xavier does is key to our success.

More recently, I’ve been extremely impressed by Piotr Sarnacki’s work (for Ruby Summer of Code) on finally delivering on the promise of truly mountable engines. His work is already merged into Rails master, and will ship with Rails 3.1. As with the rest of the guys I’ve talked about, he took on a pretty complicated and entangled task, and managed to get more done in less time than people expected. Keep an eye on him!

In short, the Rails 3 project was about more than code; it was about reshaping the Rails community. I’m proud to have been a part of growing the Rails ecosystem, and humbled by the number of people who have worked so hard for so little.

Now that we released Rails 3, I have had an opportunity to think about what to do next. I could, of course, continue full-time work on Rails for Engine Yard, which has been a fantastic place to do Open Source for the past several years. I am still extremely interested in open web technologies, and want to do my part to help the open web succeed. Having robust, mature server side frameworks that are easy for anyone to use is certainly one large piece of the puzzle, and I’ve really enjoyed helping to bring the core of Rails up to date with modern web technologies.

But as Avi Bryant pointed out last year at DjangoCon, the technology of the open web is shifting toward the client side. That doesn’t change the need for robust, mature server-side frameworks. Even the richest web applications get and sync their data with servers, mostly over the HTTP protocol. And although a lot of people have opined that rich clients can simply wire directly into something like CouchDB or MongoDB, applications with rich clients tend to have the same kinds of complex needs (like authorization) as more tranditional document-based applications have. I see Rails remaining an excellent server-side solution even as clients become richer over the next few years.

There’s still a lot to do for Rails in the future, and I want to be a part of that. On the other hand, the field of rich client development is just getting starting, with new mobile devices like the iPhone, Android and iPad giving us an almost blank canvas to work on. Unfortunately, a lot of the really big bets in this space are on selling licenses to either entire libraries or the development tools needed to efficiently work with the tools.

What the open web needs is a robust, easy to use framework with development tools that are trivial to get started with and awesome to work with. And both the library and the developer tools need to be offered for free, like Rails or jQuery. Since 2008, I have poured my soul into helping to build an amazing open source Ruby web framework and the ecosystem that powers it. Now, I want to bring that same energy and enthusiasm to building great tools that leverage the power of the modern open web and a free and open source community around them.

That’s why I was so excited when I saw that Charles Jolley, who worked on Apple’s Mobile Me product, announced that he was leaving Apple to form a new company dedicated to those same principles. Charles had helped build Mobile Me on SproutCore, a free and open source framework, and had managed to make sure that Apple continued to contribute back to the open source project under the MIT license.

In his blog post announcing that he was leaving Apple, Charles said “SproutCore is now and will always be totally free and open source. I think this business of charging for a commercial license is not an effective way to grow a project. Sure you make a little cash, but at what expense to the community? My goal is to make SproutCore and all of the developer tools that surround it totally free to everyone. All I ask is that you participate in the community somehow to make things a little better for those who come after you.”

This philosophy closely mirrored my thinking on the future of client-side development, and seeing a mature client-side framework open a permissive open source philosophy really excited me. Since the beginning of 2010, I was starting to think that if I wanted a permissively licensed client-side toolkit, I was going to have to build it and its community myself. I already knew about SproutCore–early versions of its build tools were built on Merb, and had met Charles a few times. After reading his blog post, I emailed him to find out what he was thinking about doing and he told me about his plans for SproutCore.

The SproutCore library itself, today, is definitely recovering from having been developed almost exclusively inside Apple. It comes with a number of amazing low-level primitives, and you can build a large, complex application on it. That said, it never had a big enough new user community to get a very friendly public API. Thankfully, it’s much, much easier to build a great public API than it is to build the core of a web application toolkit. Starting this week, I will be joining Charles’ company, Strobe, and will get right to work on the next generation of the SproutCore tools.

I have to say, I’m excited about what comes next.

Postscript

Because you’re probably wondering, I will still be active in the Rails community, and will be doing work for Engine Yard on Rails 3.1. I plan to use Rails 3 and Engine Yard for the server-side elements of the projects I will be doing, and really want the new Rails 3.1 features I talked about at Windy City Rails. I will also be helping Engine Yard start a new Technical Advisory Board, which will help provide community feedback for its cloud products, and guidance about what open source efforts could use the Engine Yard bump. I forsee being part of both the Rails and Engine Yard family for years to come.

Announcing Handlebars.js

For a number of years, I’ve been about as active in client-side development (through jQuery) as I have been active in server-side development (through Merb and then Rails). Recently, I’ve released a couple of libraries (jQuery Offline and Rack::Offline), designed to make it easier to build applications that can withstand both flaky connections and a complete lack of connectivity. Of course, those libraries leveraged features in modern browsers, and have gotten a bunch of use.

For jQuery Offline, the basic strategy is that instead of requesting a new JSON object before you can show anything on the page, you first try to retrieve that data from cache, show some stale content. In parallel, you’d download the new content (if possible), and update the display with the content in question. You’ve probably seen this pattern at work in applications like the official Twitter application for the iPhone, which shows stale content when you first boot the app, and downloads new content if you have Internet connectivity in the background.

To take the JSON and convert it into some HTML for the page, I recommended jquery-tmpl or mustache.js. Both of these libraries allow you to take a JSON object and convert it on the fly into HTML, which you can insert into the page. Both libraries are still very good, and I could easily imagine problem-free uses for both of them.

Of the two libraries, I really liked Mustache’s approach. Mustache envisions a template as something that is completely code-free, and populated via a JavaScript Object. This Object can contain normal values, or functions which are used as helpers.

<script type="text/x-mustache-template" name="posts">
{{#posts}}
<h1><a href="{{url}}">{{title}}</a></h1>
 
{{#div}}
{{body}}
{{/div}}
{{/post}}
</script>

You’d then populate this template with a JavaScript object:

var view = {posts: [
  { id: 1,
    url: "/posts/1",
    title: "Hello world!",
    div: function(text, render) { return "<div class='post entry'>" + render(text) + "</div>" },
    post: "Hello world. This is my first post"
  },
  { id: 2,
    url: "/posts/2",
    title: "Goodbye world!",
    div: function(text, render) { return "<div class='post entry'>" + render(text) + "</div>" },
    post: "Goodbye world. Sadly, this is going to be my last post"
  }
]};
 
var template = $("script[name=posts]").html();
var html     = Mustache.to_html(template, view)

The basic idea here is that the template itself is completely free of code, and just uses keys from the JavaScript Object to convert it into HTML. The JavaScript Object can have some functionality, and even code, to help the template along. I really like the idea of limiting the template to referencing an element of the JavaScript object, and completely firewalling any kind of code to the view object. Among other things, this allows a single template to run in both Ruby on the server-side and JavaScript on the client side.

When using Mustache, I ran into a few issues. One minor issue was that the base implementation of mustache.js was essentially interpreted, rather than compiled. This means that the implementation is slower than you might expect of a template language, especially one as limited as Mustache.

More concerningly, the base Mustache syntax was too limited for a lot of things I wanted to use it for. I wasn’t immediately sure if it was just me, so I asked a bunch of people about their opinions of Mustache. One of the people who replied was Alan Johnson, who had been using Mustache a lot and volunteered his thoughts. Without much prompting, Alan’s concerns about the limitations of Mustache (in both our cases, born from real attempts to use it) closely mirrored mine. My thinking validated for the moment, I got to work trying to extend Mustache to get around these limitations.

Before I continue, here are some of the more important problems I had:

  • Function values (like div above) needed to be located in the same place in the hierarchy as object being used as a context. This made providing a set of global helpers (like a framework would want to do) quite difficult.
  • Even if the syntax was modified to make function helpers global, the functions would not have access to the current context, so they would be of limited value (imagine trying to change the url key above into a helper)
  • I commonly wanted access to a key in a parent scope when working in a child scope. For instance, if a post had many comments, I would sometimes want access to the post’s title (or other details) while rendering the child

There were other small irritations, but these were definitely the major ones. A lot of the people I spoke to solved these problems by rewriting the JavaScript Object before passing it into the Mustache system. Some of my initial thinking, in fact, revolved around making that sort of rewriting easier. In the end, though, I wanted to extend the Mustache syntax with a few new features that would make it behave more like what I expected.

From the beginning, I wanted my extensions to be a strict superset of the official Mustache manual, which is pretty clear in some areas and somewhat more vague in other areas. I really like the Mustache syntax and philosophy, and wanted to make sure whatever I came up with would not diverge philosophically from what I enjoyed about Mustache itself.

Compiled, Not Interpreted

The first step was to make the Mustache syntax compiled, not interpreted. There is another project (called Mu) which is a compiled variant of Mustache, but it was explicitly built for Node.js, and is built around server-side JavaScript, rather than client-side JavaScript. I also wanted to build it with some of the extensions I wanted to add in mind from the beginning.

The parser/compiler is a lot like the ERB compiler, and has a lot of what you’d expect from a parser/compiler (getChar, peek, addText, addExpression, etc.). I designed it from the beginning to be extended, taking some of the architecture from Erubis, which separates out how different kinds of tags are added to the source it is building up. We’ll probably have to make a few tweaks before extensions can be easily dropped in, but I already have a couple in mind that will help flesh out the API.

Extended Paths

The first extension to Mustache is “extended paths”. In Mustache, paths are always relative to the current context (which can change with iteration), and are always a single key. For instance, the url path from the above example references the url key in the current post that Mustache is iterating over.

Extended paths allow you to go deeper into the Object (byline/name) or up the hierarchy (../title). This doesn’t diverge from the core Mustache philosophy of avoiding code in templates, but it does allow templates to more flexibly reference other parts of the Object, apart from the context they are in the process of rendering. A lot of people implement this feature by rewriting the Object before passing it into the template–Handlebars allows that rewriting to happen on the fly.

Global Lambdas with Access to the Current Context

Mustache allows the Object to contain lambdas, but they must appear in the same context as the rest of the keys being rendered. If iterating over a list of projects, for instance, each project must have a key referencing the lambda, even if it’s always the same. Handlebars allows you to provide a global Object of lambdas, which it will look in when it does not find a key in the current context. This allows you to create helpers to use throughout your Template. Again, people implemented this feature by rewriting the Object, and Handlebars is just making it possible to achieve the same goal without that rewriting.

After adding global lambdas, those helpers might want to do different things based on the context. Handlebars invokes its helper functions with a this that reflects the current context. We can rewrite the above example as:

var view = {posts: [
  { id: 1,
    title: "Hello world!",
    div: function(text, render) { return "<div class='post entry'>" + render(text) + "</div>" },
    post: "Hello world. This is my first post"
  },
  { id: 2,
    title: "Goodbye world!",
    div: function(text, render) { return "<div class='post entry'>" + render(text) + "</div>" },
    post: "Goodbye world. Sadly, this is going to be my last post"
  }
]};
 
var helpers = {
  url: function() {
    return "/posts/" + this.id;
  }
}

Of course, this example is pretty simple, and you could have just done {{title}}, but this illustrates that helpers can use the current context to control the output.

Helpers Take a Context

Helpers could be made even more generic if they could take a context (referenced as a path) as an argument. As I’ve shown above, helpers are always executed with their current rendering context as this, but it could be convenient to pass a different context, referenced by its path, to the function.

{{#projects}}
  <p>Back: {{url ..}}</p>
 
  <div>
    {{body}}
  </div>
{{/project}}

In this example, we want each project to include a link back to the parent project. By passing in a context (in this case, the object referenced by the extended path ..) we can make our helpers even more generic.

var helpers = {
  url: function(context) {
    return "/" + context.type + "/" + context.id;
  }
}

Block Helpers

The Mustache manual is a bit light on how lambda functions should work, referencing a render method that it doesn’t pass into the function. I wanted block helpers to take a function that was essentially identical to the compiled function for the entire template, and would be populated in the same way a regular template gets populated. A good example use for this type of helper is a custom list.

<script type="text/x-handlebars-template" name="items">
{{#list items}}
<h1>{{title}}</h1>
<div>{{body}}</div>
{{/list}}
</script>
var view = { items:
  [
    { title: "Hello world",         body: "This is my first post" },
    { title: "Goodbye cruel world", body: "This will be my last post ;(" }
  ]
}
 
var helpers = {
  list: function(context, fn) {
    var buffer = "<ul class='list'>\n";
    for(var i=0, j=context.length; i < j; i++) {
      buffer.push( "<li>" + fn(context[i]) + "</li>\n" )
    }
    buffer.push("</ul>");
  }
}
 
var source   = $("script[name=items]").html();
var template = Handlebars.compile(source);
 
template(view, helpers)

This will output:

<ul class='list'>
<li><h1>Hello world</h1>
<div>This is my first post</div></li>
<li><h1>Goodbye world</h1>
<div>This will be my last post ;(</div></li>
</ul>

As you can see, block helpers can now invoke the sub-template many times with different contexts. And block helpers, like regular helpers, can receive a context, expressed by an extended path, as a parameter.

Iteration and Booleans Are Just Block Helpers

One thing that bugged me was that iteration and booleans were special-cased in the normal Mustache specification. I didn’t want to change the behavior of iteration or booleans, but I did want to make them behave the same as regular block helpers. By making block helpers more powerful, I was able to achieve this with one small additional change.

In particular, rather than hardcode the behavior of iteration and booleans, I created a new feature allowing a particular function to be used when a block helper could not be found. This way, every use of {{#foo}} was a block helper, but iteration was just invoking the special helperMissing block helper. In both this case and the case of conditionals, the missing helper was treated as a context to be looked up as a path.

The helperMissing function itself is quite simple:

Handlebars.helperMissing = function(object, fn) {
  var ret = "";
 
  if(object === true) {
    return fn(this);
  } else if(object === false) {
    return "";
  } else if(toString.call(object) === "[object Array]") {
    for(var i=0, j=object.length; i < j; i++) {
      ret = ret + fn(object[i]);
    }
    return ret;
  } else {
    return fn(object);
  }
};

First, if the object referenced is true, we invoke the template block, using the current context. If the object referenced is false, we return an empty String.

If the object referenced is an Array, we iterate over the elements of the Array, invoking the template block once in the context of each element of the Array. This looks a lot like the items block helper we created above.

Finally, if the object referenced is anything else, we invoke the template block in the context of that object. Because we made block helpers more powerful, it is easy to implement the hardcoded boolean, iteration and context-switching behavior of the Mustache spec in terms of the block helpers. Note that if you wanted to change this behavior, you would just need to override Handlebars.helperMissing with a new function of your own design.

Better Inverted Sections

Finally, Mustache allows the specification of inverted sections, which behave like the reverse of a block. For instance, where {{#boolean}} will run the block if boolean is true (or a non-falsy value), and skip it if boolean is false, {{^boolean}} will run the block if boolean is false, and skip it if boolean is true (or non-falsy value).

A very common usage of inverted sections is to behave like if/else blocks:

{{#project}}
<h1>{{name}}</h1>
<div>{{body}}</div>
{{/project}}
{{^project}}
<h1>No projects</h1>
{{/project}}

Because of how common this is, Handlebars has a shortened syntax for this case:

{{#project}}
<h1>{{name}}</h1>
<div>{{body}}</div>
{{^}}
<h1>No Projects</h1>
{{/project}}

Additionally, you can specify the inverse form of a custom block helper by assigning a not property on the helper function.

{{#list projects}}
<h1>{{name}}</h1>
<div>{{body}}</div>
{{^}}
<h1>No Projects</h1>
{{/project}}
var helpers = {
  list: function(items, fn) {
    if(!items.length) return "";
 
    var buffer = "<ul>";
    for(var i=0, j=items.length; i < j; i++) {
      buffer += fn(items[i]);
    }
    buffer += "</ul>"
    return buffer;
  }
}
 
helpers.list.not = function(items, fn) {
  if(!items.length) { return fn(); }
}

Wrapping Up

Long story short: the goal of handlebars.js is to create a syntax-compatible superset of Mustache that solves a lot of problems I’ve had when working with Mustache (especially as part of a larger library).

I want to personally thank Alan Johnson for contacting me early and fleshing out my initial prototype into a workable, releasable library. His experience with Mustache, as well as his willingness to spend time on the nitty gritty details really made the difference. Thanks!

As always, please submit bug reports to the GitHub Issues tracker associated with the project. I really love the new GitHub pull request system, so please submit patches using it.

Automatic Flushing: The Rails 3.1 Plan

preamble: this post explains, in some detail, how we will implement a nice performance boost for Rails developers. Understanding the details might help gain the full benefits of the optimization, but you will gain some benefits even if you have no idea how it works.

As you’ve probably seen, DHH announced that we’d be looking at flushing in Rails 3.1 to improve the client-side performance of typical Rails applications.

The most obvious solution, and one that already exists in plugin form, is to allow a layout to have a new flush method, which would immediately flush the contents of the layout to the browser. By putting the flush method below the JavaScript and CSS includes, the browser could begin downloading and evaluating those static assets while the server continues building the page.

Unfortunately, this solution has a major problem: it requires a fairly significant change in the current model of how people build applications. In general, for performance optimizations (including client-side optimizations), we like to make the default as fast as possible, without asking people to understand a brand new paradigm, centered around the optimization.

The problem lies in the fact that a Rails layout is essentially a template with a bunch of holes to fill in.

<html>
  <head>
    <title><%= yield :title %></title>
    <%= javascript_include_tag :defaults %>
    <%= yield :extra_javascripts %>
    <%= stylesheet_link_tag :defaults %>
    <%= yield :extra_stylesheets %>
  </head>
  <body>
    <%= yield :sidebar %>
    <%= yield %>
  </body>
</html>

I this simple example, each yield is a slot that is filled in by the template (usually via content_for). In order to achieve this, Rails evaluates the template first, which populates a Hash with each piece of content. Next, it renders the layout, and each yield checks the Hash for that content. In short, because of the way layouts work, Rails renders the template first, and then the layout.

To get around this, one option would be to say that everything before the flush must not use yield, and must be able to run before the template. Unfortunately, it’s somewhat common for people to set up a content_for(:javascripts) in a template, to keep the JavaScript needed for a particular snippet of HTML close to the HTML. This means that not only does the user have to be careful about what can go above and below the flush, he can no longer use content_for for things high up in the template, which is a fairly significant change to the overall design of Rails applications.

For Rails 3.1, we wanted a mostly-compatible solution with the same programmer benefits as the existing model, but with all the benefits of automatic flushing. After a number of very long discussions on the topic, José Valim came up with the idea of using Ruby 1.9 fibers to jump back and forth between the template and layout.

Let’s start by taking a look at a very simplified version of the current Rails rendering pipeline. First, we set up a Buffer object purely for logging purposes, so we can see what’s happening as we push things onto the buffer.

module Basic
  class Buffer < String
    def initialize(name, context)
      @name    = name
    end
 
    def <<(value)
      super
 
      puts "#{@name} is pushing #{value.inspect}"
    end
  end
end

Next, we create a simple version of ActionView::Base. We implement the content_for method simply, to print out a bit of logging information and stash the value into the @content_for Hash. Note that the real version is pretty similar, with some added logic for capturing the value of the block from ERB.

module Basic
  class ViewContext
    def initialize
      @buffer      = Buffer.new(:main, self)
      @content_for = {}
    end
 
    def content_for(name, value = nil)
      value = yield if block_given?
      puts "Setting #{name} to #{value.inspect}"
      @content_for[name] = value
    end
 
    def read_content(name)
      @content_for[name]
    end
  end
end

Next, we create a number of methods on the ViewContext that look like compiled ERB templates. In real life, the ERB (or Haml) compiler would define these methods.

module Basic
  class ViewContext
    def layout
      @buffer << "<html><head>"
      @buffer << yield(:javascripts).to_s
      @buffer << yield(:stylesheets).to_s
      @buffer << "</head><body>"
      @buffer << yield.to_s
      @buffer << yield(:not_existant).to_s
      @buffer << "</body></html>"
      @buffer
    end
 
    def template
      buffer =  Buffer.new(:template, self)
      content_for(:javascripts) do
        "<script src='application.js'></script>"
      end
      content_for(:stylesheets) do
        "<link href='application.css' rel='stylesheet' />"
      end
      puts "Making a SQL call"
      sleep 1 # Emulate a slow SQL call
      buffer << "Hello world!"
      content_for(:body, buffer)
    end
  end
end

Finally, we define the basic rendering logic:

module Basic
  class ViewContext
    def render
      template
      layout { |value| read_content(value || :body) }
    end
  end
end

As you can see, we first render the template, which will fill up the @content_for Hash, and then call the layout method, with a block which pulls the value from that Hash. This is how yield :javascripts in a layout works.

Unfortunately, this means that the entire template must be rendered first, including the (fake) slow SQL query. We’d prefer to flush the buffer after the JavaScripts and CSS are determined, but before the SQL query is made. Unfortunately, that requires running half of the template method, then continuing with the layout method, retaining the ability to resume the template method later.

You can think of the way that templates are currently rendered (in Rails 2.x and 3.0) like this:

flush.001.png

Unfortunately, this makes it very hard to get any more performance juice out without asking the end-developer to make some hard choices. The solution we came up with is to use Ruby 1.9 fibers to allow the rendering to jump back and forth between the template and layout.

flush.002.png

Instead of starting with the template and only rendering the layout when ready, we’ll start with the layout, and jump over to the template when a yield is called. Once the content_for that piece is provided by the template, we can jump back to the layout, flush, and continue rendering. As we need more pieces, we can jump back and forth between the template and layout, flushing as we fill in the holes specified by the yield statements.

The implementation is mostly straight-forward:

require "fiber"
 
module Fibered
  class ViewContext < Basic::ViewContext
    def initialize
      super
      @waiting_for = nil
      @fiber       = nil
    end
 
    def content_for(name, value = nil)
      super
      @fiber.resume if @waiting_for == name
    end
 
    def read_content(name)
      content = super
      return content if content
 
      begin
        @waiting_for = name
        Fiber.yield
      ensure
        @waiting_for = nil
      end
 
      super
    end
 
    def layout
      @fiber = Fiber.new do
        super
      end
      @fiber.resume
      @buffer
    end
 
    def render
      layout { |value| read_content(value || :body) }
      template
      @fiber.resume while @fiber.alive?
      @buffer
    end
  end
end

For our fibered implementation, we’ll inherit from Basic::ViewContext, because we want to be able to use the same templates as we used in the original implementation. We update the content_for, read_content, layout and render methods to be fiber-aware. Let’s take them one at a time.

def layout
  @fiber = Fiber.new do
    super
  end
  @fiber.resume
  @buffer
end

First, we wrap the original implementation of layout in a Fiber, and start it right away. Next, we modify the read_content method to become Fiber-aware:

def read_content(name)
  content = super
  return content if content
 
  begin
    @waiting_for = name
    Fiber.yield
  ensure
    @waiting_for = nil
  end
 
  super
end

If the @content_for Hash already has the content, return it right away. Otherwise, say that we’re waiting for the key in question, and yield out of the Fiber. We modify the render method so that the layout is rendered first, followed by the template. As a result, yielding out of the layout will start the template’s rendering.

def render
  layout { |value| read_content(value || :body) }
  template
  @fiber.resume while @fiber.alive?
  @buffer
end

Next, modify the content_for method so that when the content we’re waiting for is provided, we jump back into the layout.

def content_for(name, value = nil)
  super
  @fiber.resume if @waiting_for == name
end

With this setup, the layout and template will ping-pong back and forth, with the layout requesting data, and the template rendering only as far as it needs to go to provide the data requested.

Finally, let’s update the Buffer to take our fibered implementation into consideration.

module Basic
  class Buffer < String
    def initialize(name, context)
      @name    = name
      @fibered = context.fibered?
    end
 
    def <<(value)
      super
 
      if @fibered
        puts "Flushing #{value.inspect}" if @fibered
      else
        puts "#{@name} is pushing #{value.inspect}"
      end
    end
  end
 
  class ViewContext
    def fibered?
      false
    end
  end
end
 
module Fibered
  class ViewContext
    def fibered?
      true
    end
  end
end

Now that we’re rendering the layout in order, we can flush as we go, instead of being forced to wait for the entire template to render before we can start flushing.

It’s worth mentioning that optimal flushing performance will be based on the order of the content_for in your template. If you run your queries first, then put the expensive template rendering, and only finally do the content_for(:javascript) at the end, the flushing behavior will look like this:

flush.003.png

Instead of flushing quickly, before the SQL call, things are barely better than they are in Rails 2.3, when the entire template must be rendered before the first flush. Because things are no worse, even in the worst-case scenario, we can make this the default behavior. Most people will see some benefit from it, and people interested in the best performance can order their content_for blocks so they cause the most beneficial flushing.

Even for people willing to put in the effort, this API is better than forcing a manual flush, because you can still put your content_for blocks alongside the templates that they are related to.

Look for this feature in Rails 3.1!

Small Caveat

For the purposes of this simplified example, I assumed that content_for can only be run once, immediately setting the value in the @content_for Hash. However, in some cases, people want to accumulate a String for a particular value. Obviously, we won’t be able to flush until the full String for that value is accumulated.

As a result, we’ll be adding a new API (likely called provide), which will behave exactly the same as content_for, but without the ability to accumulate. In the vast majority of cases, people will want to use provide (for instance, provide :sidebar), and get all the benefits of autoflushing. In a few cases, people will want to be able to continue accumulating a String, and will still be able to use content_for, but the template will not return control to the layout when that happens.

Also note that this (fairly detailed) explanation is not something that you will need to understand as a Rails developer. Instead, you will continue to go about your development as before, using provide if you have just a single piece of content to add, and content_for if you have multiple pieces of content to add, and Rails will automatically optimize flushing for you as well as we can.

A Tale of Abort Traps (or Always Question Your Assumptions)

For a few months now, the bundler team has been getting intermittent reports of segfaults in C extensions that happen when using bundler with rvm. A cursory investigation revealed that the issue was that the C extensions were compiled for the wrong version of Ruby.

For instance, we would get reports of segfaults in nokogiri when using Ruby 1.9 that resulted from the $GEM_HOME in Ruby 1.9 containing a .bundle file compiled for Ruby 1.8. We got a lot of really angry bug reports, and a lot of speculation that we were doing something wrong that could be obviously fixed.

I finally ran into the issue myself, on my own machine a couple days ago, and tracked it down, deep into the fires of Mount Doom. A word of warning: this story may shock you.

It Begins

I usually use rvm for my day-to-day work, but I tend to not use gemsets unless I want a guaranteed clean environment for debugging something. Bundler takes care of isolation, even in the face of a lot of different gems mixed together in a global gemset. Last week, I was deep in the process of debugging another issue, so I was making pretty heavy use of gemset (and rvm gemset empty).

I had switched to Ruby 1.9.2 (final, which had just come out), created a new gemset, and run bundle install on the project I was working on, which included thin in the Gemfile. I had run bundle install to install the gems in the project, and among other things, bundler installed thin “with native extensions”. I use bundler a lot, and I had run this exact command probably thousands of times.

This time, however, I got a segfault in Ruby 1.9, that pointed at the require call to the rubyeventmachine.bundle file.

Debugging

Now that I had the bug on a physical machine, I started debugging. Our working hypothesis was that bundler or Rubygems was somehow compiling gems against Ruby 1.8, even when on Ruby 1.9, but we couldn’t figure out exactly how it could be happening.

The first thing I did was run otool -L on the binary (rubyeventmachine.bundle):

$ otool -L rubyeventmachine.bundle 
rubyeventmachine.bundle:
  /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/libruby.1.dylib
  (compatibility version 1.8.0, current version 1.8.7)
  /usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
  /usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
  /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.3)
  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.0.1)
  /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)

So that’s weird. I had run bundle install from inside an rvm gemset, yet it was being compiled against the libruby that ships with OSX. I had always suspecting that the problem was a leak from another rvm-installed Ruby, so this was definitely a surprise.

Just out of curiosity, I ran which bundle:

$ which bundle
/usr/bin/bundle

Ok, now I knew something was rotten. I printed out the $PATH:

$ echo $PATH
/Users/wycats/.rvm/gems/ruby-1.9.2-p0/bin:...
$ ls /Users/wycats/.rvm/gems/ruby-1.9.2-p0/bin
asdf*             erubis*           rake2thor*        sc-build-number*
autospec*         prettify_json.rb* redcloth*         sc-docs*
bundle*           rackup*           ruby-prof*        sc-gen*
edit_json.rb*     rake*             sc-build*         sc-init*

In other words, a big fat WTF.

I asked around, and some people had the vague idea that there was a $PATH cache in Unix shells. Someone pointed me at this post about clearing the cache.

Sure enough, running hash -r fixed the output of which. I alerted Wayne of rvm to this problem, and he threw in a fix to rvm that cleared the cache when switching rvms. Momentarily, everything seemed fine.

Digging Further

I still didn’t exactly understand how this condition could happen in the first place. When I went digging, I discovered that shells almost uniformly clear the path cache when modifying the $PATH. Since rvm pushes its bin directory onto the $PATH when you switch to a different rvm, I couldn’t understand how exactly this problem was happening.

I read through Chapter 3 of the zsh guide, and it finally clicked:

The way commands are stored has other consequences. In particular, zsh won’t look for a new command if it already knows where to find one. If I put a new ls command in /usr/local/bin in the above example, zsh would continue to use /bin/ls (assuming it had already been found). To fix this, there is the command rehash, which actually empties the command hash table, so that finding commands starts again from scratch. Users of csh may remember having to type rehash quite a lot with new commands: it’s not so bad in zsh, because if no command was already hashed, or the existing one disappeared, zsh will automatically scan the path again; furthermore, zsh performs a rehash of its own accord if $path is altered. So adding a new duplicate command somewhere towards the head of $path is the main reason for needing rehash.

By using the hash command (which prints out all the entries in this cache), I was able to confirm that the same behavior exists in bash, but it seems that the which command (which I was using for testing the problem) implicitly rehashes in bash.

During this time, I also took a look at /usr/bin/bundle, which looks like this:

$ cat /usr/bin/ruby
#!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'bundler' is installed as part of a gem, and
# this file is here to facilitate running it.
#
 
require 'rubygems'
 
version = ">= 0"
 
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
  version = $1
  ARGV.shift
end
 
gem 'bundler', version
load Gem.bin_path('bundler', 'bundle', version)

As you can see, executable wrappers created by Rubygems hardcode the version of Ruby that was used to install them. This is one of the reasons that rvm keeps its own directory for installed executables.

A Working Hypothesis

It took me some time to figure all this out, during which time I was speaking to a bunch of friends and the guys in #zsh. I formed a working hypothesis. I figured that people were doing something like this:

  1. Install bundler onto their system, and use it there
  2. Need to work on a new project, so switch to rvm, and create a new gemset
  3. Run bundle install, resulting in an error
  4. Run gem install bundler, to install bundler
  5. Run bundle install, which works, but has a subtle bug

Let’s walk through each of these steps, and unpack exactly what happens.

Install bundler on their system

This results in an executable at /usr/bin/bundle that looks like this:

#!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'bundler' is installed as part of a gem, and
# this file is here to facilitate running it.
#
 
require 'rubygems'
 
version = ">= 0"
 
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
  version = $1
  ARGV.shift
end
 
gem 'bundler', version
load Gem.bin_path('bundler', 'bundle', version)

There are two important things here. First, it hardcodes the shebang to the system Ruby location. Second, it uses Rubygems to look up the location of the executable shipped with bundler, which will respect GEM_HOME.

Switch to rvm, and create a new gemset

Switching to an rvm gemset does a few relevant things. First, it prepends ~/.rvm/gems/ruby-1.9.2-p0@gemset/bin onto the $PATH. This effectively resets the shell’s built-in command cache. Second, it sets $GEM_HOME to ~/.rvm/gems/ruby-1.9.2-p0. The $GEM_HOME is where Ruby both looks for gems as well as where it installs gems.

Run bundle install, resulting in an error

Specifically,

$ bundle install
/Library/Ruby/Site/1.8/rubygems.rb:777:in `report_activate_error': 
Could not find RubyGem bundler (>= 0) (Gem::LoadError)
	from /Library/Ruby/Site/1.8/rubygems.rb:211:in `activate'
	from /Library/Ruby/Site/1.8/rubygems.rb:1056:in `gem'
	from /usr/bin/bundle:18

Most people don’t take such a close look at this error, interpreting it as the equivalent of command not found: bundle. What’s actually happening is a bit different. Since bundle is installed at /usr/bin/bundle, the shell finds it, and runs it. It uses the system Ruby (hardcoded in its shebang), and the $GEM_HOME set by rvm. Since I just created a brand new gemset, the bundler gem is not found in $GEM_HOME. As a result, the line gem 'bundler', version in the executable fails with the error I showed above.

However, because the shell found the executable, it ends up in the shell’s command cache. You can see the command cache by typing hash. In both bash and zsh, the command cache will include an entry for bundle pointing at /usr/bin/bundle. zsh is a more aggressive about populating the cache, so you’ll see the list of all commands in the system in the command cache (which, you’ll recall, was reset when you first switched into the gemset, because $PATH was altered).

Run gem install bundler, to install bundler

This will install the bundle executable to ~/.rvm/gems/ruby-1.9.2-p0@gemset/bin, which is the first entry on the $PATH. It will also install bundler to the $GEM_HOME.

Run bundle install, which works, but has a subtle bug

Here’s where the fun happens. Since we didn’t modify the cache, or call hash -r, the next call to bundle still picks up the bundle in /usr/bin/bundle, which is hardcoded to use system Ruby. However, it will use the version of Bundler we just installed, since it was installed to $GEM_HOME, and Rubygems uses that to look for gems. In other words, even though we’re using system Ruby, the /usr/bin/bundle executable will use the rvm gemset’s Bundler gem we just installed.

Additionally, because $GEM_HOME points to the rvm gemset, bundler will install all its gems to the rvm gemset. Taken together, these factors make it almost completely irrelevant that the system Ruby was used to install gems. After all, who cares which Ruby installed the gems, as long as they end up in the right place for the rvm’s Ruby.

There are actually two problems. First, as we’ve seen, the version of Ruby that installs a gem also hardcodes itself into the shebang of the executables for the gem.

Try this experiment:

$ rvm use 1.9.2
$ rvm gemset create experiment
$ rvm gemset use experiment
$ /usr/bin/gem install rack
$ cat ~/.rvm/gems/ruby-1.9.2-p0@experiment/bin/rackup
#!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'rack' is installed as part of a gem, and
# this file is here to facilitate running it.
#
 
require 'rubygems'
 
version = ">= 0"
 
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
  version = $1
  ARGV.shift
end
 
gem 'rack', version
load Gem.bin_path('rack', 'rackup', version)

As a result, any gems that bundler installed will put their executables in the gemset’s location, but still be hardcoded to use the system’s Ruby. This is not actually the problem we’re encountering here, but it could cause some weird results.

More concerningly, since our system Ruby installed the gems, it will also link any C extensions it compiles against its own copy of libruby. This shouldn’t be a major issue if you’re using a version of Ruby 1.8 in rvm, but it is a major issue if you’re using Ruby 1.9.

Now, we have a gem stored in your rvm’s Ruby that has a .bundle in it that is linked against the wrong Ruby. When running your application, Ruby 1.9 will try to load it, and kaboom: segfault.

Postscript

The crazy thing about this story is that it’s a lot of factors conspiring to cause problems. The combination of the shell command cache, $GEM_HOME making it look like SYSTEM Ruby was doing the right thing, and hardcoding the version of Ruby in the shebang line of installed gems made this segfault possible.

Thankfully, now that we figured the problem out, the latest version of rvm fixes it. The solution: wrap the gem command in a shell function that calls hash -r afterward.

Amazing.

Using >= Considered Harmful (or, What’s Wrong With >=)

TL;DR Use ~> instead.

Having spent far, far too much time with Rubygems dependencies, and the problems that arise with unusual combinations, I am ready to come right out and say it: you basically never, ever want to use a >= dependency in your gems.

When you specify a dependency for your gem, it should mean that you are fairly sure that the unmodified code in the released gem will continue to work with any future version of the dependency that matches the version you specified. So for instance, let’s take a look at the dependencies listed in the actionpack gem:

activemodel (= 3.0.0.rc, runtime)
activesupport (= 3.0.0.rc, runtime)
builder (~> 2.1.2, runtime)
erubis (~> 2.6.6, runtime)
i18n (~> 0.4.1, runtime)
rack (~> 1.2.1, runtime)
rack-mount (~> 0.6.9, runtime)
rack-test (~> 0.5.4, runtime)
tzinfo (~> 0.3.22, runtime)

Since we release the Rails gems as a unit, we declare hard dependencies on activemodel and activesupport. We declare soft dependencies on builder, erubis, i18n, rack, rack-mount, rack-test, and tzinfo.

You might not know what exactly the ~> version specifier means. Essentially, it decomposes into two specifiers. So ~> 2.1.2 means >= 2.1.2, < 2.2.0. In other words, it means “2.1.x, but not less than 2.1.2″. Specifying ~> 1.0, like many people do for Rack, means “any 1.x”.

You should make your dependencies as soft as the versioning scheme and release practices of your dependencies will allow. If you’re monkey-patching a library outside of its public API (not a very good practice for libraries), you should probably stick with an = dependency.

One thing for certain though: you cannot be sure that your gem works with every future version of your dependencies. Sanely versioned gems take the opportunity of a major release to break things, and until you have actually tested against the new versions, it’s madness to claim compatibility. One example: a number of gems have dependencies on activesupport >= 2.3. In a large number of cases, these gems do not work correctly with ActiveSuport 3.0, since we changed how components of ActiveSupport get loaded to make it easier to cherry-pick.

Now, instead of receiving a version conflict, users of these gems will get cryptic runtime error messages. Even worse, everything might appear to work, until some weird edge-case is exercised in production, and which your tests would have caught.

But What Happens When a New Version is Released?

One reason that people use the activesupport >= 2.3 is that, assuming Rails maintains backward-compatibility, their gem will continue to work in newer Rails environments without any difficulty. If everything happens to work, it saves you the time of running their unit tests against newer versions of dependencies and cutting a new release.

As I said before, this is a deadly practice. By specifying appropriate dependencies (based on your confidence in the underlying library’s versioning scheme), you will have a natural opportunity to run your test suite against the new versions, and release a new gem that you know actually works.

This does mean that you will likely want to release patch releases of old versions of your gem. For instance, if I have AuthMagic 1.0, which worked against Rails 2.3, and I release AuthMagic 2.0 once Rails 3.0 comes out, it makes sense to continue patching AuthMagic 1.0 for a little while, so your Rails 2.3 users aren’t left out in the cold.

Applications and Gemfiles

I should be clear that this versioning advice doesn’t necessarily apply to an application using Bundler. That’s because the Gemfile.lock, which you should check into version control, essentially converts all >= dependencies into hard dependencies. However, because you may want to run bundle update at some point in the future, which will update everything to the latest possible versions, you might want to use version specifiers in your Gemfile that seem likely to work into the future.

Threads (in Ruby): Enough Already

For a while now, the Ruby community has become enamored in the latest new hotness, evented programming and Node.js. It’s gone so far that I’ve heard a number of prominent Rubyists saying that JavaScript and Node.js are the only sane way to handle a number of concurrent users.

I should start by saying that I personally love writing evented JavaScript in the browser, and have been giving talks (for years) about using evented JavaScript to sanely organize client-side code. I think that for the browser environment, events are where it’s at. Further, I don’t have any major problem with Node.js or other ways of writing server-side evented code. For instance, if I needed to write a chat server, I would almost certainly write it using Node.js or EventMachine.

However, I’m pretty tired of hearing that threads (and especially Ruby threads) are completely useless, and if you don’t use evented code, you may as well be using a single process per concurrent user. To be fair, this has somewhat been the party line of the Rails team years ago, but Rails has been threadsafe since Rails 2.2, and Rails users have been taking advantage of it for some time.

Before I start, I should be clear that this post is talking about requests that spent a non-tiny amount of their time utilizing the CPU (normal web requests), even if they do spend a fair amount of time in blocking operations (disk IO, database). I am decidedly not talking about situations, like chat servers where requests sit idle for huge amounts of time with tiny amounts of intermittent CPU usage.

Threads and IO Blocking

I’ve heard a common misperception that Ruby inherently “blocks” when doing disk IO or making database queries. In reality, Ruby switches to another thread whenever it needs to block for IO. In other words, if a thread needs to wait, but isn’t using any CPU, Ruby’s built-in methods allow another waiting thread to use the CPU while the original thread waits.

If every one of your web requests uses the CPU for 30% of the time, and waits for IO for the rest of the time, you should be able to serve three requests in parallel, coming close to maxing out your CPU.

Here’s a couple of diagrams. The first shows how people imagine requests work in Ruby, even in threadsafe mode. The second is how an optimal Ruby environment will actually operate. This example is extremely simplified, showing only a few parts of the request, and assuming equal time spent in areas that are not necessarily equal.


Untitled.001.png


Untitled.002.png


I should be clear that Ruby 1.8 spends too much time context-switching between its green threads. However, if you’re not switching between threads extremely often, even Ruby 1.8′s overhead will amount to a small fraction of the total time needed to serve a request. A lot of the threading benchmarks you’ll see are testing pathological cases involve huge amounts of threads, not very similar to the profile of a web server.

(if you’re thinking that there are caveats to my “optimal Ruby environment”, keep reading)

“Threads are just HARD”

Another common gripe that pushes people to evented programming is that working with threads is just too hard. Working hard to avoid sharing state and using locks where necessary is just too tricky for the average web developer, the argument goes.

I agree with this argument in the general case. Web development, on the other hand, has an extremely clean concurrency primitive: the request. In a threadsafe Rails application, the framework manages threads and uses an environment hash (one per request) to store state. When you work inside a Rails controller, you’re working inside an object that is inherently unshared. When you instantiate a new instance of an ActiveRecord model inside the controller, it is rooted to that controller, and is therefore not used between live threads.

It is, of course, possible to use global state, but the vast majority of normal, day-to-day Rails programming (and for that matter, programming in any web framework in any language with a request model) is inherently threadsafe. This means that Ruby will transparently handle switching back and forth between active requests when you do something blocking (file, database, or memcache access, for instance), and you don’t need to personally manage the problems the arise when doing concurrent programming.

This is significantly less true about applications, like chat servers, that keep open a huge number of requests. In those cases, a lot of the application logic happens outside the individual request, so you need to personally manage shared state.

Historical Ruby Issues

What I’ve been talking about so far is how stock Ruby ought to operate. Unfortunately, a group of things have historically conspired to make Ruby’s concurrency story look much worse than it actually ought to be.

Most obviously, early versions of Rails were not threadsafe. As a result, all Rails users were operating with a mutex around the entire request, forcing Rails to behave like the first “Imagined” diagram above. Annoyingly, Mongrel, the most common Ruby web server for a few years, hardcoded this mutex into its Rails handler. As a result, if you spun up Rails in “threadsafe” mode a year ago using Mongrel, you would have gotten exactly zero concurrency. Also, even in threadsafe mode (when not using the built-in Rails support) Mongrel spins up a new thread for every request, not exactly optimal.

Second, the most common database driver, mysql is a very poorly behaved C extension. While built-in I/O (file or pipe access) correctly alerts Ruby to switch to another thread when it hits a blocking region, other C extensions don’t always do so. For safety, Ruby does not allow a context switch while in C code unless the C code explicitly tells the VM that it’s ok to do so.

All of the Data Objects drivers, which we built for DataMapper, correctly cause a context switch when entering a blocking area of their C code. The mysqlplus gem, released in March 2009, was designed to be a drop-in replacement for the mysql gem, but fix this problem. The new mysql2 gem, written by Brian Lopez, is a drop-in replacement for the old gem, also correctly handles encodings in Ruby 1.9, and is the new default MySQL driver in Rails.

Because Rails shipped with the (broken) mysql gem by default, even people running on working web servers (i.e. not mongrel) in threadsafe mode would have seen a large amount of their potential concurrency eaten away because their database driver wasn’t alerting Ruby that concurrent operation was possible. With mysql2 as the default, people should see real gains on threadsafe Rails applications.

A lot of people talk about the GIL (global interpreter lock) in Ruby 1.9 as a death knell for concurrency. For the uninitiated, the GIL disallows multiple CPU cores from running Ruby code simultaneously. That does mean that you’ll need one Ruby process (or thereabouts) per CPU core, but it also means that if your multithreaded code is running correctly, you should need only one process per CPU core. I’ve heard tales of six or more processes per core. Since it’s possible to fully utilize a CPU with a single process (even in Ruby 1.8), these applications could get a 4-6x improvement in RAM usage (depending on context-switching overhead) by switching to threadsafe mode and using modern drivers for blocking operations.

JRuby, Ruby 1.9 and Rubinius, and the Future

Finally, JRuby already runs without a global interpreter lock, allowing your code to run in true parallel, and to fully utilize all available CPUs with a single JRuby process. A future version of Rubinius will likely ship without a GIL (the work has already begun), also opening the door to utilizing all CPUs with a single Ruby process.

And all modern Ruby VMs that run Rails (Ruby 1.9′s YARV, Rubinius, and JRuby) use native threads, eliminating the annoying tax that you need to pay for using threads in Ruby 1.8. Again, though, since that tax is small relative to the time for your requests, you’d likely see a non-trivial improvement in latency in applications that spend time in the database layer.

To be honest, a big part of the reason for the poor practical concurrency story in Ruby has been that the Rails project didn’t take it seriously, which it difficult to get traction for efforts to fix a part of the problem (like the mysql driver).

We took concurrency very seriously in the Merb project, leading to the development of proper database drivers for DataMapper (Merb’s ORM), and a top-to-bottom understanding of parts of the stack that could run in parallel (even on Ruby 1.8), but which weren’t. Rails 3 doesn’t bring anything new to the threadsafety of Rails itself (Rails 2.3 was threadsafe too), but by making the mysql2 driver the default, we have eliminated a large barrier to Rails applications performing well in threadsafe mode without any additional research.

UPDATE: It’s worth pointing to Charlie Nutter’s 2008 threadsafety post, where he talked about how he expected threadsafe Rails would impact the landscape. Unfortunately, the blocking MySQL driver held back some of the promise of the improvement for the vast majority of Rails users.

Everyone Who Tried to Convince Me to use Vim was Wrong

A couple weeks ago, I took the plunge and switched to vim (MacVIM, to be precise). It wasn’t the first time I tried to make the switch, and I had pretty much written it off entirely.

Why? Because the past few times I tried switching to vim, I took the advice of a master vim user, and quickly sunk into the quicksand of trying to learn a new tool. In every prior attempt, I gave vim a few days before I gave up. And every time, I managed to get virtually no work done the entire time, spending about 90 percent of my day fighting with my editor (a more charitable way to put it would be “learning my editor”).

Invariably, the master vim users that were helping me make the switch would encourage me to stick it out. “If you just give it a few weeks, you’ll never want to switch back.”

The trouble was, I had work to do. I could only switch editors if the new editor did not significantly impede on my day-to-day work. I can already hear the responses: “That’s simply impossible. It’s a new editor designed for advanced users. You’ll just have to put up with the pain until you get used to it.”

Here’s the thing, though: I didn’t really have to put up with a huge amount of pain when switching to Textmate for the first time. In fact, it was downright pleasant.

The last few times someone tried to get me to switch to vim, I issued them a simple challenge. Can you tell me a way to switch that will not significantly reduce my productivity for the first few weeks. It wasn’t a challenge that was intended to fully shut down discussion. When I really thought about it, Textmate wasn’t doing all that much for me. It was a glorified Notepad which had working syntax highlighting and understand where to put the cursor when I hit enter (most of the time).

I don’t actually use “snippets” all that often, or all that many “commands”. I don’t mind the extensibility of Textmate, but I’m not a hardcore Textmate hacker myself, meaning that I’m ok with any editor that has the same level of extensibility that Textmate has (namely, all of them).

Despite what I considered a relatively reasonable request, my challenge was met with disdain and even anger by most of the people I talked to. “If you feel that way, Vim probably isn’t for you.” “You’re learning a new EDITOR for God’s sakes. Of COURSE there’s going to be a learning curve.”

I had written off the entire sorry affair.

A few weeks ago, Carl told me that he was playing with Vim. His explanation was that he had seen a number of people be really productive with it, and he was curious. Carl is definitely willing to put up with more pain to learn something new than I am, so I issued the same challenge to him.

Perhaps because he wasn’t steeped in hardcore vim hacker lore, he didn’t angrily dismiss the entire premise of my question. Thinking about it a bit more, I realized that most of the people who had tried to get me into vim had suggested that I dive in head first. “First thing: turn off the arrow keys.” “Don’t use the mouse. Force yourself to use the keyboard.”

Carl convinced me to use vim for the first couple of days pretty much exactly as I use Texmate (with the exception of having to switch between normal and insert modes). I installed NERDTree on MacVIM, grabbed the most common vim “packages”, and was off to the races. (I should note that I installed topfunky’s PeepOpen, which definitely helped with a very common workflow that I find it hard to live without).

For the first day, I clunked around by using my mouse’s scroll wheel, clicking and highlighting things, and spending most of my time in insert mode. It was slightly less productive than Textmate, but mostly in the range of what I’d expect switching to a new tool. In short, while I felt a bit out of sorts, I was able to get plenty of work done that first day.

As the days went on, I learned a few commands here and there. The first big one for me was ci as in ci " (it means: replace what’s inside the next set of " and go into insert mode). This singlehandedly made up for most of the productivity losses I was feeling from learning a new tool. Throw in o, O, A, :N and /search and I was already quite a bit more productive than I had been in Textmate.

Sure, I’m still plodding around in some cases, but only a handful of days later, using Textmate for anything feels clunky (most commonly, I try to use o or O to insert a new line above or below the one I’m currently on).

I was able to get here because I used my mouse wheel and button, arrow keys, apple-f to find text, apple-s to save files, and a whole slew of other common idioms, instead of grinding to a halt and trying to switch all of my practices at once.

To those who would say “that’s obvious; of course you learn vim incrementally”, I would simply say that having spoken to a number of vim users in the past, I never got that advice. Instead, I got a lot of advice about turning off my arrow keys, disallowing the use of the mouse, and learning the (MORE EFFICIENT!!!) vim ways to do everything, all at once. People just couldn’t stomach the idea of me continuing to use an outmoded practice (like apple-f) when vim had much better tools available just a (huge volume of) memorization away.

To those who are considering using vim, my recommendation is to use MacVIM, NERDTree, PeepOpen (or command-t), and use the mouse, arrow keys, and familiar OSX’isms all you want. Very quickly, it will become obvious that there’s a better way to do all kinds of things, and you can pile on the newly found efficiency once you’ve successfully made the switch without losing the ability to do work in the short-run.

Archives

Categories

Blogroll

Meta