Engine Yard Raises $15MM

When I started at Engine Yard in January, my employee number was in the low 20’s. Today, just half a year later, Engine Yard employs around 80 people and we’ve just announced that we’ve raised another $15 million, which should help us move our kick-ass Ruby projects along even faster.

Some things that have happened since I joined Engine Yard in January:

  • Rubinius runs Rails
  • Apple uses SproutCore, which is built on Merb
  • Serious Merb apps getting millions of hits have been launched and are running rock-solid on Engine Yard hardware
  • We announced Vertebra and have begun work in earnest. Over the past few months, we’ve begun to see working prototypes of parts of the project already usable for internal Engine Yard use
  • We began work on a Control Panel (I head up the project, code-named “ninja”), which we launched internally last week. Without any exaggeration whatsoever, getting to this point would not have been possible without Corey (atmos). If you’re an Engine Yard customer, buy him a beer.
  • DataMapper 0.9 was released, and Engine Yard is using it heavily internally, meaning that the Merb/DataMapper stack has gone from being a pipe-dream to being a real, viable-for-production, and used-in-production stack. In LinkedIn’s post-RailsConf post, they talk about Merb/DM as the future Ruby web stack.

It would seem as though a list like that should take a years, but all of that has happened in the last six months. It just goes to show how far a little bit of confidence from some savvy investors can go toward progress in the Ruby ecosystem.

Congrats fellow Engine Yarders!

jQuery Selector Refcardz

Bear Bibeault (my co-author on jQuery in Action) and I have put together a neat reference card for jQuery selectors that you can get from DZone.

Here’s a blurb they provided:

This reference card puts the power of jQuery selectors at your very fingertips. Written by Bear Bibeault and Yehuda Katz, co-authors of jQuery in Action (Manning Publications), jQuery selectors are one of the most important aspects of the jQuery library. These selectors use familiar CSS syntax to allow page authors to quickly and easily identify any set of page elements to operate upon with the jQuery library methods. Understanding jQuery selectors is the key to using the jQuery library most effectively.

Rails is a Pre-Fab House

At RailsConf, I had the opportunity to speak to a lot of people about Merb. I also listened to DHH’s keynote, which touched on some related concepts.

People coming from a Rails background, and are looking at Merb for the first time, wonder why they should throw away the phenomenal efficiency improvements they got from switching off of error-prone, tedious configuration scripts for another set of configuration when Rails makes all the decisions for them. DHH made this point fairly explicitly in his keynote. To sum up, he argued that people only think they want to make decisions; instead, they really want to be given a fully working, homogeneous solution so they can get on with their business.

Believe it or not, I agree.

The devil, as they say, is in the details.

In the real world of software applications, the monolithic solution doesn’t always fit your needs perfectly. That’s why Rails implemented, very early, a plugin architecture, which immediately reduces homogeneity.

You see, Rails is like a pre-fab house. For people who have gone through the pain of constructing a house before, pre-fab houses are very appealing. Suddenly, there’s no need to spend time with architects, contractors, or painters. You just place an order and you get a house. It seems great. You can get the furniture you want, or even repaint it.

And when you need to bring in a contractor for routine maintenance, you can have your pick of contractors. Because your house is the same as every other house they worked with. But soon you decide you want a window. Unfortunately, your house is pre-fab, so you pick up a hacksaw and hack away. Everything seems great until the first time it rains. And the water starts coming in.

Undaunted, you pick up the phone and call all those contractors you worked with before. When they get there, they take one look and let out a sigh. They have no idea how to deal with the glaring mess you have made for yourself. After paying a hefty bill to get everything fixed, you tell yourself that it’s still worth it. After all, you’re still ahead on time compared to Andy down the block who had to do everything from scratch.

But you see, there’s another option.

At a builder’s show, you see a shiny booth run by a new company called Mer Builders. They have put together a house kit that allows you to put together your house quickly and efficiently. And when you want a new window, you just pull out one of the wall blocks and replace it with a window block. Quick and easy.

But wait, you are probably thinking. I still need to put together the house. That smacks of all the pain of building a house from scratch. It’s not as bad, but I’ll still need to decide what pieces I want, figure out how they hook up, hire someone who knows how to put everything together, and more. Who wants that. A pre-fab house will do just fine, thank you very much.

As you turn to leave, the Mer Builders salesperson calls after you. You see, it turns out that they understand that you’d rather not have to make all those decisions yourself. And they’ve put together a starter kit that looks kind of like the pre-fab house. You can order it today and have it delivered tomorrow. But when you want to replace a window, their network of certified Mer engineers will simply and easily swap out a wall block for a window block.

Heck, soon enough you’ll probably be doing all sorts of customizations on your own.

The moral of the story is… Use Mer Buil… er… Merb!

RailsConf Slides

Hey guys,

My talks at RailsConf were a ton of fun. The first night I did talks on Merb and jQuery which were completely packed, and the first day of the conference I did a talk on DataMapper which seemed to be well received as well.

While it was nice to hear that so many people wanted to see the DataMapper talk that some people were turned away, it sucks that some people got turned away. Without further ado, go check out my Merb and DataMapper slides at Slideshare:

I’ll try and get up the jQuery slides shortly as well. Enjoy!

Merb BoF at RailsConf

Hey guys!

Be sure to check out the Merb Birds of a Feather tonight if you’re in Portland for RailsConf. In order to avoid conflicting with a similar BoF, I have rescheduled the Merb talk for the second slot (8:30), and moved my jQuery BoF to 7:30.

New schedule:

jQuery and Ruby: 7:30 p.m.
Learn about Merb: 8:30 p.m.

The Greatest Thing Since Sliced Merb

A few days ago, the venerable Fabien Franzen (loob2 on IRC), released a groundbreaking new plugin for Merb that proves just how versatile Merb’s core infrastructure is.

His plugin, merb_slices, allows the creation of pluginized models, views, controllers, public assets, etc. that can be dropped into a Merb app and overridden with impunity.

There’s a merbunity screencast that can explain it better than I can (and you should really look at it).

The point I want to make, though, is that the entire (rather small) implementation fits squarely inside of the set of public APIs that Merb has exposed, which means that unlike Rails Engines, future releases of Merb are guaranteed not to break the slices plugin.

Just to be clear, when I say public APIs, I don’t mean Ruby’s public visibility. Merb’s public APIs are tagged in our documentation and are a contract with our users: “We won’t break this method without a LOT of thought and explicit warnings. Everything else, however, we can and will change with impunity.” This gives us a lot of power to go in and refactor large swaths of Merb without substantially changing the way that developers interact with the framework.

And it gives plugin authors like Fabien the confidence to build substantial pieces of functionality that extend Merb without fearing that the next version of Merb will break their plugin out of the blue.

Again, go watch the screencast; I think you’ll be quite impressed with how much functionality can be layered on top of just Merb’s public APIs.

As a final word, there was a single piece of functionality that Fabien used that wasn’t public. As a result of his experience, we looked at all of the available options and agreed that it needed to be made public (but changed the way it was accessed to make it easier to refactor internals without modifying the public interface). On the Merb team, if you want to build a plugin that hooks into Merb but can’t do it with just the public APIs, we likely consider that a bug to be fixed.

We consider cases of people using alias_method_chain on Merb to be a bug in Merb, and try to find ways to expose enough functionality so it will not be required.

Good night, and Good luck!

Can’t we all just get along?

Following up on Ezra’s great post today, I wanted to throw out my thoughts on the topic.

Pretty much since I got started on the Merb project (which I did primarily to get an awesome mailer in; I spent a long time wrestling with ActionMailer on a corporate project), people have looked at the Merb project as competition for Rails.

Honestly, to some degree, we’ve fueled that by providing benchmarks and comparisons between Merb and Rails. And since our architecture is so similar, it’s only natural that people’s initial reaction upon looking into Merb is, “Why should I use this instead of Rails?”

The truth is, Merb scratches a completely different itch from Rails. Rails was responding to the almost comical amount of configuration needed to get started on the Java or PHP “stacks” at the time. Its siren song was in making as many common choices for you as possible so you’d be able to start building your app quickly and efficiently.

Rails was a massive success. It changed the way the world looked at web development. Struts 2 touts convention over configuration and Cake PHP is virtually a clone of Rails.

Today, Merb exists not to supplant those ideas, because we fundamentally agree with convention over configuration, the common usage of the MVC pattern, the use of RESTful resources, and a bundle of other things that Rails introduced to the world. Instead, our niche is making life easier for hackers, those who find themselves repeatedly delving into the framework itself to squeeze the last bit of performance or customization out of it.

It is true that we think there are concepts in Merb that are incremental improvements over Rails. But we are not unhappy when those things make their way into the Rails core. Last month, Ezra spent a week porting over Merb’s rack support into Rails, and I spent a day improving the speed of the Rails Inflector by an order of magnitude. We’d love to see our provides API make it back into Rails, and we’ve already begun to see Rails focus more on efficiency and speed in the past few months.

The fundamental difference between Merb and Rails, the one that will likely remain as the most salient features of Merb slowly find their way into the Rails codebase, is our emphasis on hackability, and the Rails emphasis on get-up-and-go. We do not see this as a competition; we see it as a way to widen the appeal of Ruby (the language that we all love), and to keep people who fell in love with Ruby through Rails from falling out of love with Ruby when their needs become more about squeezing the very last drop of performance and customization out of Ruby.

To that end, I intend to continue pushing improvements from Merb back upstream to Rails. Some of them, like my Inflector change, will likely take some time to make it all the way back to the Rails trunk because they may break backwards compatibility, but the patches will be sitting in my github repository for the next backwards-compatibility breaking release :)

Let’s all be friends!

Ruby will be better for it.

Textmate gem

As I said last week, I created thor while building a binary to handle my textmate bundles.

I wanted a way to install/uninstall/list textmate bundles like gems. Textmate already has a centralized svn repository for its bundles, and there’s a way, through AppleScript, to tell Textmate to reload bundles. The end result: a textmate binary that handles textmate bundles like gems.

$ textmate remote

Marcomates Trunk Remote Bundles
-------------------------------
ANTLR
ASP
ASP_vb_NET
ActionScript
Active4D
Ada
Apache
AppleScript
Bison
Blogging
Bulletin Board
Bundle Development
C++ Qt
C
CSS
CTags
CVS
ColdFusion
Context Free
D
Darcs
... snip ...

$ textmate remote JavaScript

Marcomates Trunk Remote Bundles
-------------------------------
JavaScript MooTools
JavaScript Prototype & Script_aculo_us
JavaScript YUI
JavaScript jQuery
JavaScript

Marcomates Review Remote Bundles
--------------------------------
JavaScript JSDoc
JavaScript MooTools
JavaScript Prototype & Script_aculo_us
JavaScript

$ textmate list

Application Bundles
-------------------
ActionScript
Apache
AppleScript
Blogging
Bundle Development
C
CSS
... snip ...
User Pristine Bundles
---------------------

User Bundles
------------
RSpec
Ruby Haml
Ruby Sass
Ruby
Rucola
Treetop

System Pristine Bundles
-----------------------

System Bundles
--------------
Ragel

$ textmate install

Checking out JavaScript jQuery…
svn co http\://macromates.com/svn/Bundles/trunk/Bundles/JavaScript\ jQuery.tmbundle /Users/wycats/Library/Application\ Support/TextMate/Pristine\ Copy/JavaScript\ jQuery.tmbundle 2>&1
A /Users/wycats/Library/Application Support/TextMate/Pristine Copy/JavaScript jQuery.tmbundle/Commands
A /Users/wycats/Library/Application Support/TextMate/Pristine Copy/JavaScript jQuery.tmbundle/Commands/Documentation for Word : Selection.tmCommand
A /Users/wycats/Library/Application Support/TextMate/Pristine Copy/JavaScript jQuery.tmbundle/Snippets
A /Users/wycats/Library/Application Support/TextMate/Pristine Copy/JavaScript jQuery.tmbundle/Snippets/each.tmSnippet
A /Users/wycats/Library/Application Support/TextMate/Pristine Copy/JavaScript jQuery.tmbundle/Snippets/clone.tmSnippet
… snip …
Checked out revision 9623.
Reloading Bundles…
Done.

$ textmate uninstall “JavaScript Prototype & Script_aculo_us”

Removing bundle...
Reloading bundles...
Done.

Pretty cool, huh? If you want it, do gem install wycats-textmate --source http://gems.github.com.

By Thor’s Hammer!

For the past few months, I’ve become more and more disillusioned by the current state of Ruby’s scripting support. Sure, we have optparse, and a gamut of other solutions, but there’s no full-stack package for writing robust binaries.

Enter thor.

The idea behind thor initially came from my work on a textmate binary (more on that later today), which would manage installed Textmate bundles. Sure, there’s the getbundle bundle, and you can manually get bundles from subversion, but I wanted a single binary that handled all of that.

While I was building it, I decided to map the commands that people could enter to a class and its methods. I created a small file that I included with the textmate binary called class_cli, and created some syntax for mapping things, like so (note that this is not the final syntax):

class MyApp
  include CLI

  desc "list [list]“, “list some items”
  def list(list = “stuff”)
    puts list.split(/,\s*/).join(”\n”)
  end
end

MyApp.start

Assuming the binary is called app, you could then do app list "one,two,three", which would print:

one
two
three

In the case of the textmate binary, I created methods for list, install, installed, and uninstall.

This worked nicely, so I wanted to extract it out for use in other tools. I started the Hermes project on github, but while drinking with Chris Wanstrath, I was convinced that the name Thor would be more appealing. Oh, the things that alcohol can do. I was also convinced of a couple other things (again, in a slightly inebriated state):

  • rake and sake needed to be replaced for scripts, not as a replacement for make
  • nobody was going to use hermesthor if they need extra boilerplate like MyApp.start

Long story short, Chris convinced me to make Thor a full-fledged scripting solution. So I did.

Thor, as it exists today, has two components:

  • The Thor superclass, which works exactly like CLI/Hermes, except that you inherit from it instead of including it (class MyApp < Thor).
  • The Thor runner, which can run Thortasks that are in a local directory or installed from a remote location

The thor runner allows you to make files like:

# module: random

class Amazing < Thor
  desc "describe NAME", "say that someone is amazing"
  method_options :forcefully => :boolean
  def describe(name, opts)
    ret = “#{name} is amazing”
    puts opts["forcefully"] ? ret.upcase : ret
  end

  desc “hello”, “say hello”
  def hello
    puts “Hello”
  end
end

If you call the file *.thor or Thorfile and place it in your current directory, any directory above you, or tasks/*.thor, you can then invoke the thorfile in any of the following ways:

$ thor -T
Tasks
-----
amazing:describe NAME [--forcefully]   say that someone is amazing
amazing:hello                          say hello

$ thor amazing:hello
Hello

$ thor amazing:describe “This blog reader”
This blog reader is amazing

$ thor amazing:describe “This blog reader” –forcefully
THIS BLOG READER IS AMAZING

You can also install local tasks or remote tasks to your system thor cache and make them available anywhere:

$ thor install task.thor
Your Thorfile contains:
# module: random

class Amazing < Thor
  desc "describe NAME", "say that someone is amazing"
  method_options :forcefully => :boolean
  def describe(name, opts)
    ret = “#{name} is amazing”
    puts opts["forcefully"] ? ret.upcase : ret
  end

  desc “hello”, “say hello”
  def hello
    puts “Hello”
  end
end
Do you wish to continue [y/N]? y
Storing thor file in your system repository

$ thor installed
Name      Modules
—-      ——-
random    amazing

Tasks
—–
amazing:describe NAME [--forcefully]   say that someone is amazing
amazing:hello                          say hello

$ thor amazing:hello
Hello

… same as above …

You can also specify a URL instead of a file name; like sake, thor uses open-uri to get the files. You uninstall or update thor modules based on the short name that was provided; if # module: name exists at the top of the file, thor will use that by default. You can also use thor install task.thor --as my_short_name. If you don’t provide a short name, thor will ask for one.

Later, you can do thor update short_name and thor will remember where you got the module from and try to update it. thor uninstall short_name will remove the module from your list of installed modules.

Of course, thor -T (or thor list) will list local tasks and system-wide tasks in the resulting list, so you don’t need a separate tool to track your thortasks, and a local task can be made into a system task trivially.

Finally, thor itself is self-hosting; the thor runner uses the Thor superclass. As a result, I added some more features to the superclass as I built the runner:

  • You can map short names to their full name: map "-T" => :list, which is why thor -T and thor list are identical
  • You can provide additional options that get passed in as a Hash (method_options :as => :required). The available option types are :required, :optional, and :boolean. The resulting hash is passed in as the final parameter to your method and the pretty-printed help automatically includes them in the usage screen.

Take a look at the thor repository on github, and specifically, the thor runner for more information on how it all fits together.

Best Things Come in Threes

I was at the Dallas Tech Fest this past weekend, and had the opportunity to meet up with some cool guys in the DataMapper community (Sam, Adam, Ben and Bryan). While I was there, I ended up hacking out a few unrelated tools that I thought I’d share with the community.

benchwarmer

Benchwarmer is an improved DSL for doing benchmarks (hat tip for the name to br0nette). It provides options for grouping, and produces output like:

Running the benchmarks 100000 times each...

                         Option 1 |   TWO | Option 3 |
 -----------------------------------------------------
 Squeezing with #squeeze     0.15 |  0.15 |     0.14 |
              with #gsub     0.38 |  0.35 |     0.36 |
 -----------------------------------------------------
 Spliting    with #split     0.43 |  0.51 |     0.61 |
             with #match     0.29 |  0.35 |     0.38 |
 -----------------------------------------------------

You get that output by doing:

  Benchmark.warmer(TIMES) do
    columns :one, :two, :three
    titles :one => "Option 1", :three => "Option 3"      

    group("Squeezing") do
      report "with #squeeze" do
        one { "abc//def//ghi//jkl".squeeze("/") }
        two { "abc///def///ghi///jkl".squeeze("/") }
        three { "abc////def////ghi////jkl".squeeze("/") }
      end
      report "with #gsub" do
        one { "abc//def//ghi//jkl".gsub(/\/+/, "/") }
        two { "abc///def///ghi///jkl".gsub(/\/+/, "/") }
        three { "abc////def////ghi////jkl".gsub(/\/+/, "/") }
      end
    end

    group("Spliting") do
      report "with #split" do
        one { "aaa/aaa/aaa.bbb.ccc.ddd".split(".") }
        two { "aaa//aaa//aaa.bbb.ccc.ddd.eee".split(".") }
        three { "aaa///aaa///aaa.bbb.ccc.ddd.eee.fff".split(".") }
      end
      report "with #match" do
        one { "aaa/aaa/aaa.bbb.ccc.ddd".match(/\.([^\.]*)$/) }
        two { “aaa//aaa//aaa.bbb.ccc.ddd.eee”.match(/\.([^\.]*)$/) }
        three { “aaa///aaa///aaa.bbb.ccc.ddd.eee.fff”.match(/\.([^\.]*)$/) }
      end
    end
  end

Most of that is optional; you can get usable benchmarks by stripping the DSL down to:

  Benchmark.warmer(TIMES) do
    report "squeezing with #squeeze" do
      "abc//def//ghi//jkl".squeeze("/")
    end
    report "squeezing with #gsub" do
      "abc//def//ghi//jkl".gsub(/\/+/, "/")
    end
  end

which produces:


                         Results |
----------------------------------
 squeezing with #squeeze    0.15 |
    squeezing with #gsub    0.34 |
----------------------------------

It is available at github. I will add the appropriate stuff so you can do
gem install wycats-benchwarmer. For now, you can just check out the git repo and do rake install.

I extracted this out of the benchmarks I was doing as I was building…

10x Faster Rails and Merb Inflector

On the plane over to Dallas Tech Fest, I thought it would be nice to try and improve the performance of the Rails Inflector, which is currently pretty slow (albeit probably not a bottleneck). Merb already uses the Facets English Inflector, which is 2x or so faster, but I was pretty sure I could do even better.

When I analyzed the English Inflector, I noticed a few things:

  • They were doing something similar to Rails looping over a list of regexen and picking the correct ones
  • Without exception, the correct choice was the longest string that matched the end of the word.
  • Matching a string (like fooses) against a regex with (foo|foos|fooses) will always match the longest string
  • Neither Rails nor English were caching the resulting words, which don’t change, and in the case of Inflecting Rails models and controllers, are a small universe of total words

As a result, I did two optimizations:

  • I packed all of the regexen into a single regex, and got rid of the sort-by-longest-string code. I then did a simple sub! against the word, pulling the results out of the rules Hash (that already existed in English)
  • English already cached irregular words (its first step was to look in the irregular words hash for the word in question), so I simply extended this cache to include any word already found.

Between these two optimizations, I was able to get around 10x over Rails, and got a huge boost for simple pluralization words (not so much for things like “person” => “people”). Rails also caught a bunch of cases in their tests that were not supported by English, so I added support for things like capital versions (”Person” => “People”) and partial words (”foo_child” => “foo_children”).

Here are the benchwarmer results:

                                         OLD  | NEW   | RAILS
Simple: account => accounts    Singular  0.16 |  0.02 |  0.25
                                 Plural  0.14 |  0.03 |  0.24
-------------------------------------------------------------
Simple: American => Americans  Singular  0.16 |  0.02 |  0.27
                                 Plural  0.16 |  0.31 |  0.27
-------------------------------------------------------------
Abnormal: dwarf => dwarves     Singular  0.07 |  0.04 |  0.17
                                 Plural  0.06 |  0.03 |  0.17
-------------------------------------------------------------
Abnormal: hero => heroes       Singular  0.05 |  0.03 |  0.20
                                 Plural  0.06 |  0.02 |  0.21
-------------------------------------------------------------
One Way: cactus => cactuses    Singular  0.11 |  0.02 |  0.26
                                 Plural  0.07 |  0.02 |  0.26
-------------------------------------------------------------
One Way: wife => wives         Singular  0.11 |  0.02 |  0.16
                                 Plural  0.13 |  0.03 |  0.14
-------------------------------------------------------------
Uncountable: fish => fish      Singular  0.03 |  0.02 |  0.03
                                 Plural  0.02 |  0.02 |  0.03
-------------------------------------------------------------
Exception: person => people    Singular  0.02 |  0.03 |  0.09
                                 Plural  0.03 |  0.02 |  0.11
-------------------------------------------------------------

It does break back-compat a bit with Rails, as the mechanism for adding new rules is simpler in order to be compatible with English’s faster inflector algorithm. I also had to remove Inflector#clear, which I wasn’t sure anyone was actually using (it allowed the clearing of very specific types of rules, which can no longer be supported as irregular words and regular singularization/pluralization rules are dumped in the same list for efficiency).

The new way of defining rules is:

Inflector.inflections do
  # One argument means singular and plural are the same.

  word 'equipment'
  word 'information'
  word 'money'
... snip ...
  word 'Swiss'     , 'Swiss'
  word 'virus'     , 'viri'
  word 'octopus'   , 'octopi'
... snip ...
  rule 'person' , 'people', true
  rule 'shoe'   , 'shoes', true
  rule 'hive'   , 'hives', true
  rule 'man'    , 'men', true
  rule 'rf'     , 'rves'
  rule 'ero'    , 'eroes'
... snip ...
  singular_rule 'of' , 'ofs' # proof
  singular_rule 'o'  , 'oes' # hero, heroes
... snip ...
  plural_rule 's'   , 'ses'
  plural_rule 'ive' , 'ives' # don't want to snag wife
  plural_rule 'fe'  , 'ves'  # don't want to snag perspectives

All of the inflector tests still pass in Rails, with the exception of the #clear tests, which were too coupled to the old implementation to salvage (they actually introspected into specific ivars).

The Rails modifications are available on my Rails branch on github. I hope to be able to push
the changes upstream if the Rails core folks are amenable :).

OSX Window Resizing Tools

I was going crazy trying to figure out a way to cordon off a section of my screen for screencasts (the center 800×600 for instance), and ended up in crazy AppleScript-land. I ended up with two useful scripts:

  • center, which takes any window, resizes it to a provided size, and centers it on the screen
  • maximize, which takes any window and maximizes it to fill the screen (even for crazy-zoom-windows like Safari)

Both scripts take drawers into consideration, so you can resize a window like TextMate to the correct size.

It is available at github and comes with a convenient raketask for installing
that will compile and copy your scripts into the appropriate folders. It also comes with a raketask that will install FastScripts Lite, which will
allow you to bind keys to these scripts (see the README for full details).

Next Page »