Sneaky Abstractions

Subscribe to my Feed, follow me on , recommend me on Working With Rails or see my code on GitHub

Use English Everywhere

Posted on August 10, 2009 09:53 Tagged with english, languages, programming, elbonian.

One common question for many new Rails developers is “How do i make Rails’ pluralisation rules work with the X language?”. There’s a simple answer to that question:

Use English Everywhere.

And by everywhere, I mean everywhere. All non-user-facing (and preferably also user-facing) parts of your application should be in English. This includes, but is not limited to:

  • Class names, module names, variable names, etc.
  • Table, column and model names
  • All comments
  • All other documentation, rake tasks, scripts, etc.

Ideally, your entire process should use English: Tickets, TODOs, stories, what have you should also be in English. If you do everything in Elbonian there’s no way for a developer who doesn’t speak Elbonian to participate in developing your application.

But our entire team speaks Elbonian, can’t we use Elbonian in our app?

Nope. Even if you all speak Elbonian, there’s no way you can know that other developers in the future working on your app will speak Elbonian, but there’s a good chance they’ll understand English. If you use Elbonian in your app, you limit your pool of potential developers to the 6 Rails/whatever developers who actually speak Elbonian instead of the thousands who speak English at some level.

But our English isn’t that good

Doesn’t matter. Poor English is much better than no English.

But the user-facing parts of our app can still be in Elbonian, right?

Possibly, but you really, really should use English as the main language even in the user interface. You can then use i18n tools to provide the app in other languages.

But our entire user base speaks Elbonian!

You can’t possibly know that. What if your user base is actually twice as large as you think, but you didn’t realise this because the other half doesn’t speak Elbonian and thus couldn’t use your app? By not providing your app in English you’re restricting your user base to include only those who speak Elbonian. Why would you do that?

As an added bonus, if your app uses i18n from the start, adding even more languages becomes really easy.

Our app targets the English-speaking market, should we use i18n anyway?

Absolutely. You never know when your boss will go on holiday to Europe and suddenly realise people speak other languages than English and then decide you should “go international” to “tap into those markets”. But when he does, you’re ready for it. Plus, using i18n has other benefits such as separating content from structure.

But we fear that if we use English everywhere it will be easier for our employer or client to outsource the app somewhere else

Then you’re not doing a good enough job. Get better at it.

Barby 0.3.1: PDF-417

Posted on June 22, 2009 04:09 Tagged with barby pdf417 barcodes.

Just released Barby 0.3.1 which has support for PDF-417 barcodes, added by Aslak Hellesøy. You can update through RubyGems as usual:

sudo gem install barby

Note that the PDF-417 support depends on the Java version of pdf417lib, which means Barby can only generate these when run with JRuby.

Barby 0.3: Ruby 1.9 compatible and pure-ruby SVG outputter

Posted on May 25, 2009 15:31 Tagged with barby, ruby, barcodes.

I just tagged and released version 0.3.0 of Barby, the simple, extensible and generally awesome Ruby library for generating barcodes. Besides a number of minor additions, 0.3.0 features Ruby 1.9 compatibility (mostly by Chris Mowforth) and a brand new SVG outputter by Peter H. Li. You could create SVGs with Barby in previous versions too, but only by using the rather heavy Cairo graphics rendering library (which makes up for its heaviness with its versatility). Peter’s outputter is pure Ruby without any dependencies at all, making it easier to get going if all you need is SVG.

As soon as the gems hit Rubyforge, you can install the new version using the gem command:

[sudo] gem install barby

As always, if there’s something you would like to see added to or fixed in Barby, it’s open source ;) Especially if you have knowledge of barcode symbologies or formats to which barcodes can be exported, that’d be great. Barby is designed to be very extensible to make it easy to add these things.

How to easily create an auto-expanding textarea

Posted on February 16, 2009 08:15 Tagged with javascript.

Just a quick tip on how to easily create textareas that automatically expand to fit their content. I’d always thought this was a rather complicated and obtrusive thing to do, but it turns out it’s not. The textarea tag has rows and columns attributes which are hints to the browser as to how big it should be. I, as many others I suspect, have always ignored these because I use CSS to control this and thought of them as remnants from an earlier age when CSS didn’t exist. But there’s really no conflict here; these attributes have semantic meaning, and the browser uses them only as a hint as to how to render the textarea. You can still set the max-height to prevent the textarea from growing too large, for example.

Thus, to create an auto-expanding textarea we just need to change the rows attribute (leaving columns out, because it’s not that useful and it’s more complicated, although possible) as the content changes. We could use the change event, but that only fires after the user leaves the textarea, which is not very useful. Instead, we need to observe the textarea to see if the content changes. “Observing” a textarea or any other DOM element is really just fancy talk for checking the contents every X milliseconds with setInterval:

//Prototype
(function(){ //Don't pollute the global scope

  var textarea = $('my_textarea');

  var oldValue = textarea.value;
  setInterval(function(){
    var newValue = textarea.value;
    if (newValue != oldValue) {//Value has changed
      //Set the "rows" attribute to the number of lines + 2
      textarea.writeAttribute('rows', newValue.split("\n").length+2);
      oldValue = newValue;
    }
  }, 500);//Check every 0.5s

})();

Now, whenever the content of the textarea changes, the rows attribute will be updated to the number of lines (plus two), and the browser will expand it.

But hang on, what it we’ve got 100 textareas on the page, won’t this mean we’ll have 100 interval functions running at the same time? Yes, it will, and that’s not really ideal. If you think about it, we only care about the content when the user is editing it, right? Knowing this, and that intervals can be removed, we can use the textarea’s focus and blur events to enable and disable the observer:

//Prototype
$$('.some_class_name').each(function(textarea){ //The 100 textareas

  var interval,
      oldValue = textarea.value,

      //The observer function is the same, only we're assigning
      //it to a variable to be re-used
      observer = function(){
        var newValue = textarea.value;
        if (newValue != oldValue) {//Value has changed
          //Set the "rows" attribute to the number of lines + 2
          textarea.writeAttribute('rows', newValue.split("\n").length+2);
          oldValue = newValue;
        }
      };

  //When the user focuses the textarea, create the observer interval
  textarea.observe('focus', function(){
    //Assign the interval to a variable so it can be removed later
    interval = setInterval(observer, 500);//Check every 0.5s
  });

  //When the user is finished editing, remove the interval
  textarea.observe('blur', function(){
    clearInterval(interval);
  });

});

Now, there will never be more than one interval running. Once the user moves focus away from the textarea, the interval is removed.

Optimising by cheating - how to trick your users into thinking your site is fast

Posted on February 10, 2009 08:03 Tagged with javascript, optimisation, magic.

Optimising web site performance is somewhat of a black art – bottlenecks and slowdowns are sometimes found in unlikely places. Usually, most of the time from a user clicks a link until he sees the page in the browser is spent rendering the page and running JavaScripts that add behaviour to the elements. The ratio is usually somewhere around the familiar 80/20 split, so while optimising server performance is all well and good, it’s not going to have a huge impact compared to improving its performance in the browser. So you profile and debug your HTML, CSS and JavaScript to find the bottlenecks and make them faster. But when you’ve squeezed every last millisecond out of the browser’s rendering and JavaScript engine and it’s still slow, what do you do? Well, you cheat.

Do it on the off-beat

Your users don’t care about the time it takes for your JavaScript to run, they care about perceived performance. One way to cheat is to make it appear like the page is fully loaded while your JavaScript continues to run in the background.

When performing tricks, magicians will create a distraction so they can mark a card or hide something while you’re not paying attention – they’re doing it on the off-beat. Your users will usually spend a couple of seconds scanning the page after it loads to see what’s on it – this is the off-beat where you can work your magic while the user is distracted.

The setup

So, what’s the secret to performing this magic trick well? First of all you have to make sure the user can’t see what you’re doing. Whatever you’re doing to the page must have minimal visual impact, or else the user will notice your distraction and the trick won’t work. This means not all of your JavaScript can be deferred to the off-beat, but most of the time you will have found some expensive parts that can by profiling the page. The page, when displayed to the user, must be usable in its initial state. Writing your JavaScript unobtrusively helps a long way in achieving this.

The example

I’ll use an example I ran into recently where making an element draggable took between 30-50ms. That doesn’t sound like much, but when you have 50 or more elements on the page that need to be draggable that means the user will have to wait an extra two seconds until the page is ready. This is many times the normal time it takes for a request to be returned from the server and makes a big difference in how fast the user perceives the page to be.

The code looked something like this:

Mysite = {};

Mysite.Thing = Class.create({

  initialize: function(el){
    this.element = el;
    this.makeDraggable();
  },

  makeDraggable: function(){
    //Make the element draggable
  }

});

onDOMReady(function(){

  //Find all things and add them to Mysite.things
  Mysite.things = $$('.thing').map(function(el){
    return new Mysite.Thing(el);
  });

});

This worked fine, but the problem was the makeDraggable method which was being run on initialisation of each new Thing. The browser would stop rendering while doing this, causing the page to appear as if it was still loading. And indeed, it was still loading – all the user would see was a spinning cursor of some sort and a blank canvas, even though the document had already loaded and was ready to be displayed. So how could this be deferred until after the page has been rendered?

The magic wand: setTimeout

The problem with running a lot of JavaScript on page load is that while running it the browser will stop rendering until you hand control back to it. If you can do this, the browser can finish rendering the page and then you can run time-intensive code. To hand control back to the browser, you can use the setTimeout function:

Mysite.Thing = Class.create({

  initialize: function(el){
    this.element = el;
  },

  makeDraggable: function(){
    //Make the element draggable
  }

});

onDOMReady(function(){

  //Find all things and add them to Mysite.things
  Mysite.things = $$('.thing').map(function(el){
    return new Mysite.Thing(el);
  });

  //Make all things draggable
  setTimeout(function(){
    Mysite.things.each(function(thing){
      thing.makeDraggable();
    });
  }, 1000);

});

Notice that the call to makeDraggable has been moved out of the initialize method and into an anonymous function in setTimeout. As soon as the timeout is set, the browser considers this bit of code finished and goes on to render the page. Then, when the timeout expires, the elements are made draggable. Usually the user won’t notice a thing because he’s distracted trying to make sense of the page that has just been loaded, and when he starts interacting with it it’s as if nothing happened.

Introducing Babilu: Rails i18n for your JavaScript

Posted on February 02, 2009 12:48 Tagged with rails, javascript, i18n.

Babilu is a Rails plugin that mirrors your i18n setup in JSON and JavaScript format. This allows you to take your translations with you when you cross that great divide which separates the server from the browser. It provides a very similar environment that you can use in your JavaScript code to do translations directly in the browser.

I18n.defaultLocale // "en"
I18n.locale // Whatever the locale has been set to on the server

I18n.t('hello') // "Hello World"
I18n.t('messages.invalid', {scope:['activerecord', 'errors']})  // "is invalid"
I18n.t('activerecord.errors.template.header', {count:4, model:'horse'}) // "4 errors prohibited this horse from being 
saved"

//Defaults work the same way as in Rails
I18n.t('doesntexist', {defaultValue:'humbaba'}) // "humbaba"
I18n.t('doesntexist', {defaultValue:':hello'}) // "Hello world"
I18n.t('doesntexist', {defaultValue:[':alsodoesntexist', 'The Sasqutch: Fact or Fiction?']}) // "The Sasquatch: Fact or 
Fiction?"

To install:

script/plugin install git://github.com/toretore/lucy.git
script/plugin install git://github.com/toretore/babilu.git

Then load the generated JavaScript in your layout:

<head>
  <script type="text/javascript" src="/javascripts/locales.js"></script>
</head>

Babilu will automatically reload your locales on each request in development mode, just like you’d expect, but in production they will only be loaded when the server starts up.

Body and style: Two stylesheets in one

Posted on October 14, 2008 08:50 Tagged with ajax patterns, tip, javascript, css.

A couple of years ago there were a lot of people who wanted to provide “style switching” for their web sites. People came up with all sorts of (well, some) crazy solutions for injecting a new stylesheet into the browser window while removing the old one, even though it’s perfectly valid to provide several stylesheets, marking some as “alternate”.

<link rel="stylesheet" href="style1.css" type="text/css" />
<link rel="alternate stylesheet" href="style2.css" type="text/css" />

Most browsers will provide a way for the user to switch between the two stylesheets, but most users don’t know about it and if they do they usually won’t bother to check if there actually are alternate stylesheets for a page. So developers started adding links or buttons to their sites that dynamically switched the stylesheets.

Of course, this is still the preferred and kosher way of providing alternate stylesheets, but there’s another way to achieve the same thing that might be a bit more flexible. In my previous post I wrote about a pattern I use on elements in which class names tell us something about the element’s state. If you expand that to encompass the entire page, you can use the power of CSS to provide “virtual” stylesheets for parts of or the entire page. For example, with a stylesheet like this:

body.foo h1 { color: #f00; }

body.bar h1 { color: #0f0; }

And some javascript to change the class name on the body element:

MySite = {
  toggleStyle: function(){
    var body = $$('body').first(),
        classes = ['foo', 'bar', 'baz];
    return function(newClass){
      classes.each(function(c){ body.removeClassName(c); });
      body.addClassName(newClass);
    };
  }()
};

You can swicth the entire page from one style to another. The benefit of doing it like this is that you can be as granular as you like; you can change the style for the entire page or just one part of it just by adding and/or removing class names (yes, you can do that with separate files too, but it gets cumbersome). You can make use of the cascading nature of CSS to have a base style and then layer some extra style on top of it. The downside, at least for the “entire page” scenario, is that you will have to do a lot of repetition to narrow your style declarations to work only for body.foo or body.bar. But if you use something like SASS to write your stylesheets – which you should anyway, it takes away a lot of the work – you don’t have to repeat this stuff over and over again.

Unobtrusive Ajax patterns: element state

Posted on September 11, 2008 17:49 Tagged with unobtrusive, javascript, state, ajax patterns.

I’ve been a little busy lately, so I haven’t had the time to write anything new for my Ajax Patterns series of posts, but I thought I’d write a quick one explaining a simple, maybe obvious, but very useful pattern that I use all the time when dealing with “enhanced” elements. Usually, I wrap HTML elements inside JavaScript objects. This is another mini-pattern that abstracts the behaviour from the content instead of the hit-and-run pattern where elements are located using their IDs or class names, things are done to them and then they’re forgotten. I’ll just give you a quick example of what I mean before I get to the “state” pattern:

var posts = $$('.post').map(function(el){
  return {
    element: el,
    markRead: function(){
      //marks this post as read
    },
    markUnread: function(){
      //marks this post as unread
    },
    isRead: function(){
      //returns true if this post is read
    }
  };
})

With this, we get an array of objects that wrap a “post” element. This is a very common pattern like all the other patterns in this series. The three methods work on this element, but they abstract out the behaviour so you don’t have to touch the element directly. They all deal with state; the state of being read or unread, which has to be stored somewhere. As I’ve wrapped my elements in objects, I could just store the state as an attribute on the object, but HTML already has an excellent way of containing an element’s state: classes. By adding or removing the “read” class on the element, we can store the post’s state. This also means that posts can have an initial state and it’ll just work without us having to do any initialisation magic.

The object now looks like this:

Mysite = {};

Mysite.posts = $$('.post').map(function(el){
  return {
    element: el,
    markRead: function(){
      this.element.addClassName('read');
    },
    markUnread: function(){
      this.element.removeClassName('read');
    },
    isRead: function(){
      return this.element.hasClassName('read');
    }
  };
})

Note that I’ve saved the post objects on a global object Mysite, which means you can get to them later. From here, you could hijack a “Mark as read” form in each post element to use Ajax, and when it’s successfully marked the element as read on the server, it could call markAsRead on itself to change the class. Further, you could have different CSS rules for read and unread posts so that there is a visual feedback to the user that the post has been marked read, which is another great advantage of using class names for state.

This may all seem really obvious, and it is once you start doing it. But I think if you’re a beginner to this whole Ajax business it may not be something you would think about doing. I’ve seen a lot of examples in tutorials and other code where the same functionality would be implemented in a way that the server would send back the entire post element in HTML and the “dumb” client would just replace the content with whatever comes back from the server. There’s really no need to do that when it can be done more efficiently and more scalable. Let the server do its thing without intertwining its responsibilities with that of the client.

There's a Gopher on the Rails

Posted on August 14, 2008 13:30 Tagged with gopher, rails, tcp, ruby.

Welcome to the past!

In the beginning of the Internet, before there was even a Web 0.1, there was Gopher. It was awesome. Oh, wait, no it wasn’t. That’s why no-one uses it anymore. But it didn’t suck, and most decent Web browsers still support it. So, how can you integrate this with your Rails app to make your very own phlog? You can’t really, because Rails is HTTP and Gopher is not. But you can write a simple Gopher server that uses ActiveRecord to fetch your blog posts:

require File.dirname(__FILE__)+'/../config/environment'
require 'socket'

hostname = "tore.darell.no"
port = 70
server = TCPServer.new('0.0.0.0', port)
while session = server.accept
  request = session.gets.chomp

  begin
    if request.blank? #index
      session.puts "iWelcome to my phlog.\tfake\t(NULL)\t0"
      session.puts "i \tfake\t(NULL)\t0"
      Post.find_published(:all, :order => "created_at DESC").each do |post|
        session.puts "0#{post.title}\t#{post.slug}\t#{hostname}\t#{port}"
      end
    else #a post
      post = Post.find_by_slug(request)
      session.puts "#{post.title} by Tore Darell on #{post.created_at.strftime('%Y-%m-%d %H:%M')}"
      session.puts
      session.puts post.summary
      session.puts
      session.puts post.body
    end
  rescue Exception => e
    session.puts request.blank? ? "iFAIL\tfake\t(NULL)\t0" : "OH NOES :("
  ensure
    session.close
  end
end

It loads the entire Rails environment, which probably certainly isn’t necessary, but it’s just easier that way. To start the server, you probably have to be root. Also, remember to set RAILS_ENV if necessary:

RAILS_ENV=production sudo ruby script/gopher &

And just like that your blog has been transformed into a living relic from the early 90s. Take that, Web 2.0!

Unobtrusive Ajax patterns: the updatable selectbox

Posted on August 08, 2008 10:16 Tagged with unobtrusive, javascript, select, ajax patterns.

This is something I see people ask about all the time: How to make one select dropdown update another based on what the user selects in the first. In fact, I wrote a script to do that and a couple of other things, but sometimes it’s good to be able to know how something like this works and customise it when it doesn’t fit your needs.

The ideal scenario for this solution to work unobtrusively is when the selects have a clear one-to-many, tree-like relationship. Not having thousands of options also helps, because it means you don’t have to retrieve them asynchronously (i.e. no ajax) from the server to prevent it from becoming too slow. This is the scenario I’ll go through in this article.

<form>
  <select name="foo" id="foo" class="updates:bar">
    <option value="1">1</option>
    <option value="2">2</option>
  </select>
  <select name="bar" id="bar">
    <optgroup label="1" class="foo:1">
      <option value="1">1.1</option>
      <option value="2">1.2</option>
    </optgroup>
    <optgroup label="2" class="foo:2">
      <option value="3">2.1</option>
      <option value="4">2.2</option>
    </optgroup>
  </select>
</form>

Here, the “foo” select will limit the options in the “bar” select based on what is selected in “foo”. Another way to put it is that the “bar” select observes the “foo” select and changes itself based on which option is selected in “foo”.

The unobtrusive part is that it will still work without JavaScript. The options are logically grouped in optgroup elements named in such a way that the used can see how it fits together. Of course, you’ll still need to validate the choice on the server to make sure the option selected in “bar” logically belongs to the option selected in “foo”.

So, what do we actually need to do here to make it work the way we want? First, we need to find all select elements with a class name matching “updates:<something>”. This tells us that the select, when changed, is going to update another selectbox with the ID “<something>”.

document.observe('dom:loaded', function(){

  $$('select').select(function(source){
    var className = source.readAttribute('class');
    var m = className && className.match(/updates:([^ ]+)/);
    if (m) {
      //We have a match
    }
  });

});

Now we have the ID of the target select and we can extract the optgroup elements inside it:

$$('select').select(function(source){
    var className = source.readAttribute('class');
    var m = className && className.match(/updates:([^ ]+)/);
    if (m) {//We have a match
      var target  = $(m[1]), //The target select
          name = source.readAttribute('id');// "foo" (in the example, can be anything)
      //Remove the optgroups from the target element and store them for later
      var groups = target.select('optgroup').invoke('remove');
    }
  });

Note that we remove the optgroups from the target element and store them in a variable that can be used later.

Now that we have both the source and the target elements, we can define what is going to happen when the source element is changed. Let’s extract this into a function of its own:

function updateTarget(){
  var selectedValue = source.getValue();//"1" or "2" in the example
  var re = new RegExp(name+':'+selectedValue); // ex: /foo:1/
  var associatedGroup = groups.find(function(g){
    return g.readAttribute('class').match(re);
  });
  target.update();//Empty the target first
  //Insert the option elements (not the optgroup itself)
  associatedGroup.select('option').each(function(o){
    target.insert({bottom:o});
  });
};

This function does a number of things in order to replace the contents of the target select. First, it gets the value of the selected option element in the source element. This value tells us which optgroup from the target it’s associated with. Then it loops through the saved groups and saves the associatedGroup. The associated group is the one which has a class name which matches the ID of the source element plus a colon and then the selected value. So, if the value “2” is selected in the “foo” element, the optgroup that has a class name of “foo:2” will be the associatedGroup. When this group has been found, it empties the target, and inserts the groups option elements (not the entire optgroup, because there’s no need for it since it’ll be the only one).

Now that we have the basic functionality in place, all we need to do is attach an event listener to the source element that runs it onchange. We’ll also run the function the first time on page load since no change has taken place yet.

source.observe('change', function(){
  updateTarget();
});
updateTarget();//On page load

The entire script now looks like this:

$$('select').select(function(source){
    var className = source.readAttribute('class');
    var m = className && className.match(/updates:([^ ]+)/);
    if (m) {//We have a match
      var target  = $(m[1]), //The target select
          name = source.readAttribute('id');// "foo" (in the example, can be anything)
      //Remove the optgroups from the target element and store them for later
      var groups = target.select('optgroup').invoke('remove');
      //The function that performs the update
      function updateTarget(){
        var selectedValue = source.getValue();//"1" or "2" in the example
        var re = new RegExp(name+':'+selectedValue); // ex: /foo:1/
        var associatedGroup = groups.find(function(g){
          return g.readAttribute('class').match(re);
        });
        target.update();//Empty the target first
        //Insert the option elements (not the optgroup)
        associatedGroup.select('option').each(function(o){
          target.insert({bottom:o});
        });
      };
      source.observe('change', function(){
        updateTarget();
      });
      updateTarget();//On page load
    }
  });

And here’s a (hopefully) working example:

I haven’t really checked to see if it works in browsers other than those based on Gecko, but there shouldn’t be any blocking problems with this technique. Also, the heavy use of closures in these examples might be a recipe for memory leaks in some browsers (IE, I’m looking at you), I don’t really know and I think Prototype actually takes care of cleaning up my mess in that case. I don’t think I’d do it exactly like this in real life, I just chose to in the example for simplicity. The technique would still be the same though.

1 2 3 4 5

I am Citizen Insane