InquiryLabs

Politics, Programming and Possibilities

Archive for the ‘Software Engineering’ Category

Testing Wengo Visio

I had a couple of ideas with Apple’s iChat and started looking around for implementations of “my” idea. It turns out Wengo (a French company) has done something like what I imagined: video chat on the blog. I’ll try it here:

Update: It doesn’t look like it’s working. Hmph. Neat idea though.

Update 2: Let’s try Stickam instead:

Update 3: Or not. How about tokbox?

[removed tokbox widget for now]
Yep, Tokbox works! Cool.

Super Digg Feed

I love digg, but I can’t stand how they make me go to the site for every single article. Use this feed from Georgy Woods instead:

Super Digg Feed v2.0

And by the way, if you aren’t already using one, and if you visit several websites a day to “keep up on the news” or to find out if one of your friends has posted some news lately, you should definitely use a feed reader, like NewsFire on the Mac, or Google Reader on the web. (Leah, I’m talking to YOU :) )

Flock Rocks

I’m using Flock (1.2 beta) right now, and I have to say, I’m hooked.  Imagine the amazingness of FireFox, enhanced with the ability to keep in touch with all of your friends using facebook, flickr, digg and their blogs.  It’s like a special world-view just for me.

When I open it up, I can see who’s added new photos to their flickr stream, or what friends are doing right now on facebook.  I just found out that my old buddy from Rock Creek, Adam Mars, went on a trip to Europe that I didn’t know about! :)

I’ll play around with it for a little while longer and see if the two of us (me and Flock) have any “irreconcilable differences” before switching.  Anyway, nice job, Flock team!

Simplifying Rails Fixtures with Contexts

The Fixture Debate

If any of the debates at the Mountain West RubyConf last March could be called “heated”, I’d say the hottest one came when we started to discuss unit tests and functional tests in Rails.  I might be reading my own story into things, but what I got out of the discussion was that there is a consensus surrounding the idea that unit tests are good, and we’re all glad that Rails ships with a testing suite, but the brittleness of testing with fixtures is something that has yet to be solved universally.

The Flexible Solution, Redux

I’ve approached this problem before and offered a “flexible fixtures” patch (twice) to the core team that never made it in.  (It’s ok, I’m not bitter… I just think it’s a higher priority than they do).  With that patch having long been laid aside, I offer here a simple fix that will add much of the same functionality with a small change (fewer than 20 lines of reasonable length) to your test_helper.rb file (see below).

What you get is the ability to specify the directory (i.e. the “context”) from which to load certain fixtures. For example, you might have several fixtures that are always loaded (e.g. drop-down box data or other basic data that is required just for your app to run) and then several scenarios or contexts that rely on that base level of data.

This is how your unit test would look using this “context_fixtures” call:

class AccountingRulesTest < Test::Unit::TestCase
  context_fixtures base, :cities, :countries, :holidays
  context_fixtures three_clients, :users, :accounts, :transactions

  def test_transactional_banking
    # … etc.
  end

  # … etc.

end

You can use context_fixtures in your functional tests this way, too.  I organize my test/fixtures directory into subfolders such as test/fixtures/base, and test/fixtures/three_clients, etc.  Note that this solution is not as flexible as the “flexible fixtures” patch, since it still requires that the fixture files map one-to-one to the tables in your database.  As usual, however, it’s ok to choose not to load data into some tables.

Keeping Your Deprecated Fixtures Around

If you’re in the middle of a project and you realize that you need these contexts in order to reduce the complexity of writing tests, what do you do with the test cases and data that are already working just wonderfully?  You don’t want to have to discard those.  Instead, you could create your own custom TestCase classes, like this:

module Test
  module Unit
    class DeprecatedFixturesTestCase < TestCase
      self.fixture_path =
        File.join(RAILS_ROOT,
                  test, deprecated_fixtures)
    end
  end
end

module ActionController
  class DeprecatedFixturesTestCase < TestCase
    self.fixture_path =
      File.join(RAILS_ROOT,
                test, deprecated_fixtures)
  end
end

After adding the above code to your test_helper.rb file,

  1. Rename the current “fixtures” directory to “deprecated_fixtures”, and
  2. Use this DeprecatedFixturesTestCase class as the superclass of all of your “deprecated tests”.

It took me just a minute or two to search and replace “TestCase” with “DeprecatedFixturesTestCase”. With that change, from here on out, just use the regular TestCase class for your new tests and use “context_fixtures” instead of “fixtures”.

Context Fixture Source Code for “test_helper.rb”

ENV["RAILS_ENV"] = test
env = File.dirname(__FILE__) + /../config/environment
require File.expand_path(env)
require test_help

# Add a little more granularity to our fixture
# directories so that we can load some fixtures from
# one directory (context), and other fixtures from
# other directories.
class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
  superclass_delegating_accessor :contexts
  self.contexts = {}

  alias context_free_initialize initialize
  def initialize(connection, table_name,
                 class_name, fixture_path,
                 file_filter = DEFAULT_FILTER_RE)
    if contexts.has_key?(table_name.to_s)
      fixture_path =
        File.join(RAILS_ROOT, test, fixtures,
                  contexts[table_name.to_s],
                  table_name.to_s)
    end
    context_free_initialize(
      connection, table_name,
      class_name, fixture_path,
      file_filter)
  end
end

module Test
  module Unit
    class TestCase
      self.use_transactional_fixtures = false
      self.use_instantiated_fixtures  = false

      # Provide the ‘context_fixtures’ class method
      # in conjunction with our modded Fixtures class
      # above.
      def self.context_fixtures(context, *fxtrs)
        fxtrs.each do |f|
          Fixtures.contexts[f.to_s] = context
        end
        fixtures *fxtrs
      end
    end
  end
end

Tags: , , ,

All Hail Rubinius! Rails is Running!

Some exciting news in the Ruby community has been reverberating today… Rails works in Rubinius!

Congrats to all involved, and thanks to EngineYard for sponsoring the project as well.

A Cleaner, Happier Blog

The dubious links have finally been cleaned up from my blog’s feeds. A search reveals none of the key words (e.g. loans, ringtones, porn) that were there before, so all evidence points to things being back to normal.

For the record, I tried to clean things up manually at first, but that quickly became an awful chore: more then 200 posts had been magically “edited” and the nefarious links inserted at the end. So I wrote a script to clean things up, using Ruby and Sequel:

require rubygems
require mysql
require sequel

db = Sequel.mysql inquirylabs_wordpress,
  :user => user,
  :password => password,
  :host => localhost

posts = db[:wp_posts]
posts.all.each do |p|
  posts.filter(:ID => p[:ID]).update(
    :post_content => p[:post_content].gsub(
      /(<font|<div\sid=wp_internal).*
        (porn|
         payday[-\s]loan|
         home[-\s]loan|
         ringtone).*$/x, )
end

Much better. :)

Thanks to those of you who helped me to identify the problem and, recently, to see that I hadn’t scoured all of the dark corners of the website.

TextMate Footnotes 3.0

José Valim has improved the Footnotes plugin and kindly taken the lead on maintaining it for Rails 2.0. Read about his awesome new features here. Thanks, José!

Installing Merb in Your Home Directory

I have a shared account on a server where Ruby 1.8.5 is installed but Merb is not. To install gems, I added “$HOME/lib/ruby/gems/1.8/bin” to my path, and the following 3 lines to my .profile:

export GEM_HOME=$HOME/lib/ruby/gems/1.8
export RUBYLIB=$HOME/lib/ruby:$HOME/lib/site_ruby/1.8
export RB_USER_INSTALL=true

I had to add the last line because hpricot is a compiled extension that uses the “install” command to put it in the correct directory once it’s done. Tip came from this site. Without RB_USER_INSTALL set to true, I received the following error:

/usr/bin/install -c -o root -g wheel -m 0755 hpricot_scan.so
install: /…/hpricot_scan.so: chown/chgrp:
Operation not permitted *** Error code 71

Next, I installed rubygems:

wget http://rubyforge.org/frs/download.php/20989/\
  rubygems-0.9.4.tgz
tar xzvf rubygems-0.9.4.tgz
cd rubygems-0.9.4

ruby setup.rb all –prefix=$HOME –siterubyver=$HOME\
  /lib/site_ruby/1.8

And last but not least:

gem install -y merb

Thanks to Ian Mckellar for starting me off.

Update: For the record, the following gems were needed for my project:

  • mongrel (installs fastthread, daemons, gem_plugin, cgi_multipart_eof_fix)
  • sqlite3-ruby
  • ruby2ruby (installs ParseTree, RubyInline, hoe, rubyforge
  • merb_sequel (installs sequel, sequel_core, metaid, sequel_model, assistance)

What Makes jQuery a Good Choice?

I’ve been told that jQuery has been around since January of 2006. At some point during the last year, many developers within the Ruby community began to embrace it as an alternative to Prototype and Scriptaculous. Many of the programmer friends I look up to in the Merb community, specifically, are big advocates of jQuery.

So this post is an attempt at summarizing the strengths I’ve found in jQuery as opposed to the two other javascript libraries that I’ve worked closely with: mooTools and Prototype / Scriptaculous. My motivation for this is a soon-to-be-made decision regarding the javascript library that will be used in a browser-based application that I’m working on at a company in Chicago. The application needs a simple user interface and fairly powerful front-end. I’ve advocated the use of jQuery, and thought it would be useful to set out the reasons for my preference here on the InquiryLabs blog.

jQuery is well-documented

There is a fine set of documentation at jquery.com. Scriptaculous hasn’t seen much improvement in its documentation in over a year. Prototype’s documentation is (in my opinion) pretty, but still lacking.

jQuery is concise

It uses as its central paradigm the idea of “querying” the DOM for the desired elements and returning a collection (like a dataset, but with DOM elements) and then acting on the result, or set of elements. The reason it can be concise is that the element sets are chainable. For example:

document.ready(function() {
  for (var i = 0; i <= 6; i++)
    $(h + i +  [@id]).each(function() {
      $(<a class=”anchorlink”>\u00B6</a>).
        attr(href, # + this.id).
        attr(title, Permalink to this headline).
        appendTo(this);
    });
});

(Hat tip, lucumr) In the above example, anchor tags are added to all headlines in the document. Note the clever use of chaining which reduces the size of the code, yet retains its expressiveness.

jQuery is easily extended

Whether it’s a simple function or an entire plugin, jQuery is built for extending. The ability to query for “element sets” and then act directly on those results is not limited by the core code. Since it’s so easy to add custom functions to element sets, it becomes natural. For example, I found that I often needed to add or subtract a value from a CSS property. I solved this problem by extending the jQuery core element set, like so:

jQuery.fn.cssDelta = function(property, delta) {
  var value = parseInt(this.css(property));
  return this.css(property, (value + delta) + px);
};

Using the above code, I can query for a set of elements and adjust the height property (for example) in one fell swoop. This will now add 5 pixels to the height of each “rack-item” element:

$(.rack-item).cssDelta(height, 5);

jQuery is small

According to Jeff Robbins and John Resig, the Drupal team chose it over Prototype because it is a mere 15k compared to Prototype’s 80k. The Dojo library is even larger.

Update:I decided to test this out myself to see what results I’d get. Resig’s comment was probably from jQuery’s earlier days when it was a micro framework. As far as I understand, it’s still possible to compress the jQuery library down to 18k or so, but that’s possible for Prototype, too. In fact, my tests show that un-gzipped, compressed code gets both down to 51k using Dojo’s ShrinkSafe online app.

Update 2:Thanks to Peter Higgins below for commenting on the size of Dojo. For comparison, its compressed (but un-gzipped) size is 77k.

jQuery has broad acceptance

Feedburner, Technorati, Drupal, Edgewall Trac, etc.

Contrasting Prototype

Here are some examples of the concise nature of jQuery, taken from the jQuery blog:

// AJAX Updater in Prototype:

new Ajax.Updater(placeholder, url, { method: get, parameters: par });

// AJAX Updater In jQuery:

$(#placeholder).load(url + par);

// Note: This example doesn’t deal with the obvious
// iteration benefits we get if we wanted to load the
// response into every <p> object, for instance.

// Adding a class to an element in Prototype:

Element.addClassName(element, className);

// Adding a class to an element in jQuery:

$(#element).addClass(className);

// Adding a class to a group of elements in Prototype:

$$(.element).each(function(node) {
  Element.addClassName(node, className);
}

// Adding a class to a group of elements in jQuery:

$(.element).addClass(className);

“That last one is the clearest example of the difference in methodology. Because jQuery is passing messages to jQuery objects, the code is barely changed. jQuery doesn’t care that we’re now adding a class to a group of objects instead of one object; the underlying code is the same (add the class to the set of elements in the object). Prototype, on the other hand, requires an iterator.”

“And as your code becomes more complex, jQuery’s scales easily, while nested loops become the norm in frameworks like Prototype.”

Notes on the Facets Gem

The Facets gem is fairly popular, and for good reason. I was poking through the documentation on the plane home from Chicago (I have a contract position there for the next month) and found a couple of neat things to share:

Facets library

  • Autoarray class—an Array that autovivifies any number of dimensions. For example:a = Autoarray.new
    a[3][4][5] = 1
    would create a 3-dimensional array with values initialized to ‘nil’ and the appropriate cell set to 1.
  • Dictionary class—a Hash that retains order. The order, by default, is whatever order its contents were given in; however, it can also enforce any arbitrary ordering that you provide.
  • Enumerable extensions—a (very nice) module that extends the Enumerable mixin. It’s huge! There are so many idioms captured in this that I can’t explain them all. But if you like Ruby for it’s concise syntax and easy chaining of things like ‘each’, ‘map’ and ’select’, you’ll like what you see in here.
  • File.rewrite—open, modify, write back to disk, all in a single ruby block.
  • FileUtils.head and FileUtils.tail—handy functions that let you get at the first few or last few lines of a file.

There’s plenty more to look at in the Facets gem… these are just a few that caught my attention. Install the gem and then use “gem server” to check out the documentation ;)