Autonomous Machine

Posts tagged with Code

Tweaking Ruby Enterprise Edition's garbage collection settings to speed up tests

I've been looking at ways to get the test suite for a project I'm working on running faster, and I came across slides from a presentation that present several ways to speed up tests. In particular, there are some environment variables that you can use to control the behavior of REE's garbage collector. I've found that using the values suggested in the slides decreases my test run times by 20-30%:

export RUBY_HEAP_MIN_SLOTS=1000000
export RUBY_HEAP_SLOTS_INCREMENT=1000000
export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1
export RUBY_HEAP_FREE_MIN=500000
export RUBY_GC_MALLOC_LIMIT=1000000000

I saved this script to my path, and when I want run Ruby with these settings, I prepend the command I'm running with 'rmem'. Or, as suggested by the slides, you can add the settings to your profile. Be careful, as they cause Ruby processes to use significantly more memory.

  • August 21, 2010
  • Article
  • Code, Rails, Rspec, Ruby

A simple content_for in PHP

I'd been meaning to check out PHP 5.3's closures. When someone asked me a question about Fitzgerald today, I had to look at the source to find the answer. I then spent five minutes sketching the following, which is a very minimal implementation of Rails' content_for view helper.

<?php

$contents = array();

function content_for($name, $method) {
  global $contents;
  $contents[$name] = $method;
}

function yield($name) {
  global $contents;
  if (array_key_exists($name, $contents)) {
      return $contents[$name]();
  }
}

$variable = "something great";

?>

<?php content_for('header', function() use($variable) { ?>
  <h1>'<?php echo $variable ?>' should be in the header</h1>
<?php })?>

<?php content_for('footer', function() { ?>
  <h1>should be in the footer</h1>
<?php })?>

<div class="header">
  <?php yield('header')?>
</div>

<p>Here is the content for a page.</p>

<div class="footer">
  <?php yield('footer')?>
</div>

The rendered result looks like this:

<div class="header"> 
    <h1>'something great' should be in the header</h1> 
</div> 
 
<p>Here is the content for a page.</p> 
 
<div class="footer"> 
    <h1>should be in the footer</h1> 
</div> 

Having to declare inherited variables with use is a little annoying, but otherwise, I'm impressed with this addition to PHP.

  • June 04, 2010
  • Article
  • Code, PHP

ocrunner provides prettier OCUnit output

The testing landscape in the Objective-C world is much more sparsely populated than it is in the Ruby world, with the best two options being OCUnit and Google's customized version of OCUnit which ships as a part of their Google Toolbox for Mac. If you haven't tested with OCUnit before, Apple has a nice article to get you started.

Not in Kansas Anymore

Coming from the Ruby world, I was accustomed to tests running constantly in a console as wrote code. When I started doing iPhone development, it took me a while to setup a confortable working environment. Figuring out the best way to run tests was the biggest component of this period of acclimation.

After working on my first iPhone app for a few weeks, I found running tests via the Xcode GUI to be occasionally useful for debugging, but in general I felt having to switch between targets in Xcode in order to build the tests provided to much resistance. I started using the xcodebuild command line programs to run tests, which was great, except the output is hopelessly verbose, which makes it quite difficult to see if a test failed.

Ruby to the Rescue

OCRunner is a little Ruby wrapper for xcodebuild. It will run your tests with xcodebuild and display the results in a concise and colorful manner:

Screenshot of OCRunner in action

To try it out:

gem install ocrunner
cd /your/project/directory
ocrunner --auto

The --auto options will rerun tests whenever an Objective-C or header file is modified. ocrunner --help will tell you about all the available options. The code is on GitHub.

In Closing

I'm now thinking that the best way to test Objective-C code probably involves MacRuby, but if you're using OCUnit, OCRunner will give you a more streamlined workflow for TDD.

  • May 25, 2010
  • Article
  • Code, OCUnit, Objective-C, Ruby

Carmen now supports states for nine countries

Thanks to Andriy Tyurnikov and Tobias Schmidt for recently adding support for the Ukraine and Germany, respectively. And to the others that have fixed bugs or brought issues to my attention.

Carmen is a collection of country and state names and abbreviations, along with replacements for the state_select and country_select plugins that leverage this data.

  • December 16, 2009
  • Article
  • Code, Rails, Ruby

Apply jQuery event handlers once with $.fn.safe()

Today I was in this situation:

  • I had a page that could mutate in a lot of different ways (AJAX, user interaction, etc)
  • I needed a way to execute a block of code against only the new DOM elements on the page (to avoid duplicating the event handlers on the already existing elements)
  • I didn't want to use livequery (delegation would have created its own set of problems)

This is what I came up with:

$('ul.choices a').safe('choices').click(function(event) {
  // code to only execute once for any DOM element
};

$.fn.safe works similarly to jQuery's filter. It returns a jQuery object containing only DOM elements that haven't already been returned for the specified key ('choices' in the above example). So it's safe to execute the code above multiple times without repercussions. Obviously, looping through a large set of elements can be costly, but for smaller sets this simple solution works great.

Here's what's going on behind the scenes:

var $$ = function(param) {
    var node = jQuery(param)[0];
    var id = jQuery.data(node);
    jQuery.cache[id] = jQuery.cache[id] || {};
    jQuery.cache[id].node = node;
    return jQuery.cache[id];
};

$.fn.safe = function(name) {
  return this.filter(function(i, element) {
    $$(this).unsafe = $$(this).unsafe || [];
    if ($.inArray(name, $$(this).unsafe) == -1) {
      $$(this).unsafe.push(name);
      return true;
    } else {
      return false;
    }
  });
};

I'm using the $$ helper I first saw on Yahuda Katz's blog- you should too. It makes working with jQuery's data cache much easier.

See Also

LowPro for Prototype will only apply a given behavior to a DOM element once, but I haven't used it since moving to jQuery for all new projects.

  • November 20, 2009
  • Article
  • Code, JavaScript, jQuery

Convert HTML to Haml within Textmate

I have been integrating a lot of well built HTML templates into Rails applications this week. I've found Haml to be the best templating language, and I like to convert preexisting templates to use it as I add them to a project.

The Haml gem installs a command line executable that performs this conversion, html2haml. The program takes whatever is passed as standard input, performs the conversion, and writes the result to standard out. For a while I was using command this in combination with the pbcopy/pbpaste commands (I work on a Mac) to apply this to the content of the clipboard:

pbpaste | html2haml | pbcopy

This worked, but the extra copying and pasting was annoying. So I made a TextMate command to eliminate the tedium:

Screenshot of the TextMate bundle editor

The actual command is this (it's a bit hard to see above):

echo $TM_SELECTED_TEXT | html2haml

You could add a key binding as well, but so far I haven't bothered to.

  • November 13, 2009
  • Article
  • Code, Mac, Rails, Ruby

Add an ActiveRecord scope for easier eager loading

In the optimization phase of a project, one of the first things I do is look for pages that could benefit from the use of ActiveRecord's eager loading. Since named_scopes were introduced in Rails 2.1, most of my model loading has involved a chain of scopes, and it is always frustrating to have to change

@blogs = Blog.published.active

to

@blogs = Blog.published.active.scoped(:include => [:slugs, :topic => :slugs])

It's a small difference, but one I've never really liked. It seems like an obvious choice would be to add a named_scope to all subclasses of ActiveRecord::Base and have that handle the :include parameter. I finally wrote the 11 lines of code required to do this today:

module ActiveRecord
  module EagerLoadScope
    def self.included(base)
      base.named_scope :eager_load, lambda { |*inclusion|
        {:include => inclusion}
      }
    end
  end
end

ActiveRecord::Base.class_eval { include ActiveRecord::EagerLoadScope }

And now that line looks like this:

@blogs = Blog.published.active.eager_load(:slugs, :topic => :slugs)

Again, it's a small improvement, but one I consider worthwhile.

  • October 28, 2009
  • Article
  • Code, Rails, Ruby

Dollar Spec is a tiny JavaScript spec library

Dollar spec is a tiny JavaScript spec framework that gets out of the way and lets you get things done. It supports nested describes and before/after blocks, but that is about it. The standard set of expectations is small right now, but they are easy to add.

Why another JavaScript spec framework?

I wanted a small, pure-JS framework that supported a syntax I didn't have to think too much to use. I wanted to only add as much syntax as was neccessary, and leave the rest to JavaScript. I wanted to run JavaScript tests from the console. I wanted a really extensible way to add new expectations. And I wanted minimal namespace usage. DollarSpec creates a single global entity, $spec.

Also, it seemed like a good way to stretch my brain. I've been doing a lot of JavaScript development recently, and it was fun to apply some of the new techniques I've picked up.

OK Let's See What You've Got

Here's a sample spec for an awesome addition function:

$spec.describe('my awesome addition function', function(spec) {

    var add = function() {
       var total = 0;
       for (var i = 0, l = arguments.length; i < l; i++) {
           total += arguments[i];
       }
       return total;
    };
    
    spec.before(function() {
        // code in this block is run before each spec
        // and yes, describe blocks can be nested
    });
    
    spec.it('adds two numbers', function(expect) {
        expect(add(2,2)).to.equal(4);
    });

    spec.it('adds three numbers', function(expect) {
        expect(add(1,1,2)).to.equal(4);
    });

    // to show a failing spec
    spec.it('adds two numbers', function(expect) {
        expect(add(1,1,2)).to.equal(5);
    });

    // to show a pending spec
    spec.it('casts and adds strings');
});

$spec.run();

If you run this inside Firefox, you will get some messages in the Firebug console:

Filter results

These message can be adjusted to your liking:

// To disable console output (defaults to true)
$spec.opts.console = false;

// Print a line to the console for each test (defaults to false)
$spec.opts.verbose = true;

If you don't want to use the console reporting, the results of all specs are collected and returned by $spec.stats(). This makes it easy to do whatever you wish with the results.

Supported expectations

Keep in mind that any expectation can be negated using not(). For example:

expect(3).to.not().equal(8);

expect(actual).to.be(object)

Compares the expected and actual values using ===.

expect(actual).to.beA(Object)

Verifies that actual is an instance of Object.

expect(actual).to.equal(expected)

Compares actual and expected using ==.

expect(affectorFunction).to.change(affectedFunction)

Compares the value returned from calling affectedFunction before and after calling affectorFunction.

expect(affectorFunction).to.change(affectedFunction).by(amount)

Compares the difference between the value returned from calling affectedFunction before and after calling affectorFunction to amount.

expect(callbackFunction).to.raiseError([verifyFunction])

Verifies that callbackFunction raises an exception when called.

Optionally will call verifyFunction and pass in a raised exception for further inspection. verifyFunction must return true or false.

Custom expectations

DollarSpec's expectations are built from two pieces- verbs and matchers.

Verbs

A verb is a function that can be used in an expectation to define something about the parameters of what is expected. The most basic verbs simply define which matcher to use. Verbs must always return this in order to allow chaining to work. Here is the verb definition for equal:

$spec.verb('equal', function(expected) {
    this.set('matcher', 'equal');
    this.set('expected', expected);
    return this;
});

This verb will cause the expectation to use the equal matcher, and stores the value of expected so it can be examined in the matcher later.

Matchers

Matchers are functions that determine if an expectation passes or fails. They can also define messages to be displayed to the user when a test fails. Here's the beA matcher:

$spec.matcher('beA', function(result) {
  result.failure = "Expected an instance of " + this.klass.toString() + ", but it was " + typeof(this.actual);
  result.negatedFailure = "Expected instance of a class other than " + this.klass.toString() + ", but it was one";

  return this.actual instanceof(this.klass);
});

result.negatedFailure is the message to be displayed when the tests passes, but was used in a negated expectation using not().

You can see how the built-in verbs and matchers are implemented in the Github repository.

Dogfood for Dinner

Dollar Spec has a suite of specs, written using Dollar Spec and powered by diligence, a tiny remote JavaScript test runner library. It requires Node.js, which is awesome. Go check it out if you haven't yet.

To run the specs:

cd spec
node suite.js

Open a browser and go to localhost:5678. You should see something like the following:

Dollar Spec Results

Diligence is still under development, but its working well so far on a few JavaScript projects I'm working on. I'll post more about it as it matures.

More information

There is a bit more info in the README on Github. Feedback is always welcome!

Alternatives

You should probably take a look at ScrewUnit if you're looking for a more complete/mature BDD framework.

Now go write some specs.

  • September 04, 2009
  • Article
  • Code, JavaScript

Install Passenger and nginx from source on Ubuntu

Passenger 2.2.3 came out this week, and while up until now I was using the Ubuntu packages from Brightbox (great blokes, really), I was having some problems with serving caches files and I didn't want to wait for the package to be updated. The package itself can be found on Github if you'd like to see it in more detail.

I used a combination of two guides to get everything working: one at Slicehost's wiki and another blog post by someone whose name may or may not be Johnny Pez.

It can be a little confusing to jump back and forth between the two, so I've posted a compiled set of steps here. After working through this article, you can continue on with the second Slicehost article for setting up the rest of your environment.

Passenger

I'm going to assume you have Ruby and RubyGems installed. If not, do that first before continuing.

Install the Passenger gem:

sudo gem install passenger

Then you need to build the nginx extension, which will be needed when we compile it.

cd `passenger-config --root`
sudo rake nginx

nginx

You'll need to install nginx's prerequisites:

sudo apt-get install libpcre3 libpcre3-dev libpcrecpp0 libssl-dev

Then, download the nginx source and unpack it. Everyone seems to be using the legacy stable version of nginx, and I haven't tried any of the newer ones yet.

wget http://sysoev.ru/nginx/nginx-0.6.37.tar.gz
tar xzvf nginx-0.6.37.tar.gz

Now we need to configure nginx.

cd nginx-0.6.37
./configure --sbin-path=/usr/local/sbin --with-http_ssl_module  \
--add-module=`passenger-config --root`/ext/nginx

You can change the configure flags if you want (see the comments on the Slicehost article), but I've left them alone so the rest of Slicehost's articles can be followed without modification.

Assuming the configure succeeded, all that's left is to compile and install.

make
sudo make install

All Systems Go

To make sure everything is working, start nginx:

sudo /usr/local/sbin/nginx

Visit your server's IP, and you should see the nginx welcome screen. This is good! Kill nginx:

sudo kill `cat /usr/local/nginx/logs/nginx.pid`

Now continue on with the Slicehost series to complete your nginx configuration. You'll also probably want to mirror the default configuration layout (these articles specify Intrepid, but the steps will be pretty close on most recent versions of Ubuntu).

  • June 19, 2009
  • Article
  • Code, Installation, Rails, Ruby

Interrogation creates boolean accessors from named_scope declarations

This is a little hack I came up with today when I got tired of duplicating logic in scopes and accessor methods. If I define a method in a model like this:

class Submarine < ActiveRecord::Base
  named_scope :on_surface, :conditions => {:location => 'surface'}
  named_scope :submerged, :conditions => {:location => 'under water'}
end

I think I should be able to interrogate the model to see if it is in these scopes without needing to define Submarine#on_surface? or Submarine#submerged? This is what I want to be able to do:

sub = Submarine.first => #<Submarine id: 1, location: 'surface'>
sub.on_surface? => true
sub.submerged? => false

Interrogation will allow for exactly this. The first version would fire a database query on each call, but I've since added in an attempt at parsing simple conditions against a model's attributes, with a fallback to the database for complicated conditions.

One last thing

The largest problem with this approach is an object's state is not always in sync with the database. I've thought about this a lot, and at this point I think it's best to raise an exception when using these methods on dirty objects. I think handling dirty objects is beyond the scope of this little hack.

The code is on Github.

  • June 05, 2009
  • Article
  • Code, Rails, Ruby

Duplicate a Mac OS X Terminal window with Ruby and Appscript

Even though OS X's Terminal now supports multiple tabs, I still find myself using lots of separate windows so I can see everything at once. A common pain point was opening a second Terminal window and changing to the current working directory (I do this a lot from the root of Rails apps: one window for running the server, and one for git and other work).

I've since written a little Ruby script that essentially duplicates the current Terminal window. Save the following as dup and put it somewhere on your path:

#!/usr/bin/env ruby
#
# Duplicates a terminal window, optionally running the passed command
# % dup (creates new window)
# % dup command arg1 arg 2 (new window, plus runs passed command)

require 'rubygems'
require 'appscript'

include Appscript

def quote(command)
  command.gsub(/(\$`\\!")/){|m|"\\\\#{m}"}
end

path = ENV['PWD']
terminal = app('Terminal')
coords = terminal.windows.first.position.get
dimensions = terminal.windows.first.size.get

command = "cd \"#{quote(path)}\" && clear"
command << " && #{quote(ARGV.join(' '))}" unless ARGV.empty?

terminal.do_script(command)
terminal.windows.first.size.set([dimensions[0], dimensions[1]])
terminal.windows.first.position.set([coords[0] + dimensions[0] + 10, coords[1]])

Appscript is required, but it is only a sudo gem install rb-appscript away. The script will pass and arguments passed to it to the new terminal window. One common use for me is dup script/server.

  • May 30, 2009
  • Article
  • Code, Mac, Ruby

Reloading Rails plugins in development mode

In Rails 2.3 you can cause your plugins to be reloaded with each request by adding this to your development.rb file:

config.reload_plugins = true

This was possible before, but it required altering Dependencies.load_once_paths and other black magic. I've always had issues with these approaches, and so it's nice to see official support for such a useful feature.

  • April 23, 2009
  • Article
  • Code, Rails, Ruby

Carmen: A Rails plugin for geographic names and abbreviations

On a recent project I became tired of state select and country select, the ubiquitous Rails plugins for providing a list of state or country names in views. I didn't like that their data was defined in code. Or that their data was defined in the view, so validating a model field against them was messy.

I started to refactor country select by moving the list of countries into a Geography module. But then I needed a list of states, and their abbreviations, and it struck me as odd that I needed two plugins that worked differently in order to provide what seemed to be some very basic functionality to my app.

Well she sneaks around the world, from Kiev to Carolina...

Carmen is the result of my frustration: a small unified library that handles country and state names and abbreviations. It stores its data lists in YAML, so it's easy to edit and add new state lists.

Carmen's primary use is providing a list of countries (or states within country), and, optionally, their abbreviations.

Carmen::states('US') => [['Alabama', 'AL'], ['Arkansas', 'AR'], ... ]
Carmen::state_names('US') => ['Alabama', 'Arkansas', ... ]
Carmen::state_codes('US') => ['AL', 'AR', ... ]

Similar methods are available for countries. It also has some convenience methods to assist in converting between names and abbreviations:

Carmen::country_name('US') => 'United States'
Carmen::country_code('Canada') => 'CA'
Carmen::state_code('Manitoba', 'CA') => 'MB'
Carmen::state_name('AZ', 'US') => 'Arizona'

Any of the state methods that require a country code will use a default country code if none is supplied. This defaults to 'US', but can be easily changed for those outside the US:

Carmen.default_country = 'CA'

And of course, it's simple to use Carmen in your model validations:

class Address < ActiveRecord::Base
  validates_inclusion_of :country, :in => Carmen::country_codes
end

Carmen also supplies view helpers that work the same as those in country select or state select, so it should be a drop in replacement in most cases. I've posted the docs, and the code is on Github.

  • April 01, 2009
  • Article
  • Code, Rails, Ruby

Using will_paginate with DataMapper and Sinatra

Yes, it can be done. But not using prebuilt gems, since we need to use the agnostic branch of the will paginate repository for DataMapper support. Here's what I did to install the necessary version of will_paginate:

git clone git://github.com/mislav/will_paginate.git
cd will_paginate
git checkout --track -b agnostic origin/agnostic # check out agnostic branch
gem build will_paginate.gemspec # build the gem
sudo gem install will_paginate-3.0.0.gem # install the gem

You could also create a fork, merge the code from agnostic into the master branch, push to GitHub, and have your own username-will_paginate gem to install. I decided this wasn't worth the effort, at least for the project I was working on.

Models

When will_paginate is required, it does some checks to see if it is running under Rails or Merb, and if so, mixes the class methods and view helpers into the base classes for you. If you're working with another framework (such as Sinatra), you'll need to require the finders and view helpers on your own:

require 'will_paginate'
require 'will_paginate/finders/data_mapper'

At this point, YourModelName#paginate will return paginated collections. But we need to be able to render pagination links as well...

Views

will_paginate has abstracted out the view logic into a few modules, and all it depends on is the implementation of the WillPaginate::ViewHelpers::LinkRenderer#url method. To get the view helper working, I added the following to the bottom of my Sinatra app's file (based on the supplied the merb adapter):

require 'will_paginate/view_helpers/base'
require 'will_paginate/view_helpers/link_renderer'

WillPaginate::ViewHelpers::LinkRenderer.class_eval do
  protected
  def url(page)
    url = @template.request.url
    if page == 1
      # strip out page param and trailing ? if it exists
      url.gsub(/page=[0-9]+/, '').gsub(/\?$/, '')
    else
      if url =~ /page=[0-9]+/
        url.gsub(/page=[0-9]+/, "page=#{page}")
      else
        url + "?page=#{page}"
      end      
    end
  end
end

helpers WillPaginate::ViewHelpers::Base

The code assumes the page number will be in the query string; it could easily be modified to work in other situations.

  • February 17, 2009
  • Article
  • Code, Ruby

Git Error: fatal: reference is not a tree error

If you do what I do and keep your Rails plugins in separate git repos using git submodules, you will encounter a git error if you've made changes to the local repositories for a plugin and try to deploy without pushing the changes up to the server:

fatal: reference is not a tree: 17f1db7f33c986f0d4a9dc0c5846322095cda96b

To resolve this, cd into the relevant directory (vendor/plugins/whatever/) and push to the repo. It seems obvious, but I've made this mistake once or twice.

  • February 07, 2009
  • Article
  • Code, Rails

Obvious Tip 1: Short Circuiting Logic While Debugging

Who hasn't forced a conditional statement one way or the other to force part of a complicated system to always trigger during a bout of (potentially late night, potentially ill-advised) hackery? I've learned the hard way to always take the twenty seconds to add a warning so I don't forget to remove the hack. Of course, specs are going to fail if I forget to, but it's easy to spend time looking in the wrong places for a fix to something as sturdy as if statements.

puts('! OVERRIDING SOME LOGIC !')
if true || some_method_that_may_or_may_not_return_true?
  ...
end

Make sure to put the reminder outside the conditional. Depending on what you're working on, you can use a framework logger if you have one. I used puts above because the code I'm working on (which sparked this entry) is standalone.

  • January 20, 2009
  • Article
  • Code, Ruby