→ I Love Labels

11 Aug 2010

I really love when checkbox labels are done properly.

To see what I mean click on this checkbox's text label ("Click Me!"):

Click Me!

<input type="checkbox"> Click Me!

Nothing happened, right? Right.

Now click on this checkbox's text label:

<label><input type="checkbox"> Click Me!</label>

Yep, awesome. Here's another way to do it (in case your <label> and <input> tags are far apart):

<input type="checkbox" id="ckbx"> <label for=ckbx">Click Me!</label>

→ do it like rake

22 Jul 2010

If you must require RubyGems in your Ruby library, do it like Rake:

begin
  require 'rake'
rescue LoadError
  require 'rubygems'
  require 'rake'
end

Everyone wins.

→ Managing Expectations

21 Jul 2010

If you look on Cultured Code's Arrivals page, you'll see something like this:

Things' Arrivals Board

This is a very tempting thing for small companies to do. You want your customers to know that you're working on something they want.

But ultimately, it's a bad idea. When Cloud Sync launches, I'll think, "Finally." If I didn't know they were working on it, I'd think, "Oh, Cloud Sync! Finally! Sweet!"

That is, when it's released my thoughts will focus on how long it's been on their Arrivals board. I won't think about all the awesome stuff they released in the meantime, some of which may have been more valuable than Cloud Sync.

Under promise, over deliver.

→ Slightly Obtrusive JavaScript

31 May 2010

There are good things and bad things about "Unobtrustive JavaScript." One bad thing: it's hard to tell what JavaScript is touching an element.

Idea: Only ever use classes and ids prefix with js- when touching the DOM with JavaScript.

For example:

<a href="#prices class="js-open-tab">Prices</a>

Now we know to look for any JavaScript touching .js-open-tab, which should only be a simple search away.

And hey, now JavaScript and CSS won't share selectors. Since we're separating our content and presentation, we might as well separate our behavior all the way too.

We could also use FireQuery, though it only works with one JavaScript library in one browser, and not with $.fn.live(). Though I do love it.

→ Higher Order Mustache

27 Apr 2010

On the GitHub East Coast tour a few weeks ago Tom Preston-Werner and I were trying to figure out a solution to what I saw as the Final Mustache Problem: caching.

In ERB you might do this:

<% cache "user:#{current_user.id}" do %>
  Some expensive stuff.
<% end %>

At GitHub we do a fair amount of HTML caching this way. Without this feature, we couldn't start porting the site to Mustache. Solving this problem would probably let us implement syntax highlighting and other similar concepts in Mustache, too.

Here's what we got: Higher Order Sections.

  Some expensive stuff.

How? If the value of cache_by_user_id is a lambda or function, Mustache will pass the unrendered block of text to it. The block can then do whatever it wants and its return value replaces the block.

Here's how we might do caching in Ruby:

class MyView < Mustache
  def cache_by_user_id
    lambda do |text|
      cache_key = "user:#{current_user.id}"

      if value = $cache.get(cache_key)
        value
      else
        rendered = render(text)
        $cache.set(cache_key, rendered)
        rendered
      end
    end
  end
end

The lambda is passed the raw template text. If we find something in the cache, we return that and it replaces the block. If we don't find anything in the cache we render the block, store it in the cache, then return it.

Examples

I opened sourced the mustache-syntax-highlighter recently, and also created a Gist of a Markdown helper we're using. Both are Higher Order Sections in action.

Bonus: both mustache.rb and mustache.js already support this feature.