echo "hey, it works" > /dev/null

just enough to be dangerous

Install gems through an authenticating proxy


Because I keep forgetting how:

gem install gem<em>name --include-dependencies \
  -p http://[user]:[pass]@[proxy</em>host]:[proxy_port]

You might also want to add additional gem sources. The normal command for this is gem sources -a [sourceurl] but the sources command unfortunately doesn't take a proxy parameter. You can directly add a source url to this line in gem/lib/rubygems/defaults.rb.

def self.default</em>sources
  %w[http://gems.rubyforge.org/]
end

For example, I added github thus:

def self.default_sources
    %w[http://gems.rubyforge.org/ http://gems.github.com]
  end

This is of course horribly hacky. If you know of a better way, please tell me.

Variable class names using Markaby


Markaby is a Ruby library that lets you write HTML in Ruby. It's built into the Camping framework as the templating engine. To create elements, you call a method of that name.

</p>
 
<h1>In Camping, you don't have to set up the Builder.</h1>
 
<h1>I'll leave it out in the other examples.</h1>
 
<p>mab = Markaby::Builder.new
mab.p "This is a paragraph."
mab.div "I can do the same thing with a div."

To nest your HTML, you can pass a block.

form :method => 'post' do
  legend 'Import stuff'
  textarea :name => 'queries', :rows => '25', :cols => '100'
  input :type => 'submit', :value => 'Import!'
end

[A side note, the textarea method inserts some whitespace by default. Very annoying, so if you know how to get rid of it in a non-hacky way, please let me know.]

It uses lots of metaprogramming trickery to make your life a whole lot easier. For example, you can add an arbitrary class to an element by calling the class name as a method.

div.example "This div will be of class example."

The class methods can also be chained.

div.example.special "This div will be of class example <em>and</em> special."

You can do the same thing with an id by simply appending a bang (!) to the class name.

div.main<em>content! "This div will have the id main</em>content."

But what if you want a variable class name? I can't just tack the variable name on because the magic will mean that the class will be the name of the variable, not the value.

%w[one two three].each {|c| puts mab.p.c.to_s}

That's not going to work. It will output this.

<p class="c">
<p class="c">
<p class="c">

Ruby's send method to the rescue.

%w[one two three].each {|c| puts mab.p.send(c)}

This correctly outputs this.

<p class="one">
<p class="two">
<p class="three">

It's relatively absolute


In one of the experiments I'm running for my research, I have to take a snapshot of a page and serve it locally. Of course, if I just grab the HTML, any relative URLs will break and the locally served page is unlikely to look much like the original. So, I put together a bit of code to make the links absolute. I remember trying to do this a few years ago in Python and having enormous headaches, but this Ruby version was relatively painless. That says more about my skills as a coder than anything about the relative (get it?) merits of Python and Ruby.

%w[uri net/http hpricot].each {|lib| require lib}
url = 'http://en.wikipedia.org/wiki/Night'
response = Net::HTTP.get<em>response(URI.parse(url))
body = Hpricot.parse(response.body)
absolutisable = { 'a' => %w[href],
                  'applet' => %w[codebase],
                  'area' => %w[href],
                  'blockquote' => %w[cite],
                  'body' => %w[background],
                  'del' => %w[cite],
                  'form' => %w[action],
                  'frame' => %w[longdesc src],
                  'iframe' => %w[longdesc src],
                  'head' => %w[profile],
                  'img' => %w[longdesc src usemap],
                  'input' => %w[src usemap],
                  'ins' => %w[cite],
                  'link' => %w[href],
                  'object' => %w[classid codebase data usemap],
                  'q' => %w[cite],
                  'script' => %w[src],
                }
(body/"#{absolutisable.keys.join('|')}").each do |elem|
  absolutisable[elem.name].each do |attr|
    uri = elem.attributes[attr]
    elem.raw</em>attributes[attr] =
      URI::parse(url).merge(uri).to_s unless uri.nil?
  end
end
puts body

This code doesn't take into account @import'ing CSS, and internal CSS links like url will break it, but I think it accounts for everything else.

Camping seems more interesting


Turns out I don't go through the most rigorous process to decide what technology to use. I've been using Camping for quite a while now, on a couple of small internal projects. I know there are other lightweight Ruby frameworks out there, such as Sinatra and Ramaze. So, why did I choose Camping? Why? Simply because Camping seems more interesting, and things should be fun. And maybe that question is part of the answer, _why.

Anonymous functions


I've been working on Habari a bit recently, so have been writing more PHP than Ruby lately. Given that Habari's code quality is pretty good, that hasn't been too terrible. However, I recently had to prepend a URL to a bunch of file paths, and was thinking in Ruby, where I would have done something like this:

url = "http://twofishcreative.com/"
resources = %w[one two three]
resources.map! { |resource| url + resource }
puts resources

The beauty of this is that it keeps the callback code with the calling code, making it easier to read. PHP doesn't have blocks, but it does have the create_function() function, which lets you create an anonymous function, so you can have your callback inline too.

$url = "http://twofishcreative.com/";
$resources = array("one", "two", "three");
array<em>walk($resources, 
  create</em>function('&amp;$resource,$k,$url',
    '$resource = $url.$resource;'), $url);
print_r($resources);

Ouch! That quoted function! Deity forbid you actually want to do anything complex in there. And you get a completely new scope, so you have to pass in any variables you need. And if you want to use more than one variable you need to do some horrible kludge like passing an array of variables.

I'll leave it as an exercise for the reader to work out which I prefer.

Serving static files in Camping, with a single route


I've written here and here about serving static files with Camping, but each time I've set up a new route for each resource type. You can serve all static files with a single route by following the instructions on the wiki.

Here's the code that's presented there.

module Camping::Controllers
  class Static &lt; R '/static/(.+)'<br>
    TYPES = {'.css' => 'text/css', '.js' => 'text/javascript', 
                  '.jpg' => 'image/jpeg'}
    PATH = File.expand_path(File.dirname(<strong>FILE</strong>))
    def get(path)
      @headers['Content-Type'] = TYPES[path[/&#46;\w+$/, 0]] || "text/plain"
      unless path.include? ".." # prevent directory traversal attacks
        @headers['X-Sendfile'] = "#{PATH}/static/#{path}"
      else
        @status = "403"
        "403 - Invalid path"
      end
    end
  end 
end

You would then create a path by calling, for example, R(Static, 'style.css') from your view. The X-Sendfile header tells the server to send the specified file. If you want to support other kinds of resources, simply add an entry into the TYPES hash.

If you're using LIGHTTPD, apparently some old versions don't support the X-Sendfile header, but they do support a custom X-LIGHTTPD-send-file header, so modify the code above accordingly. I haven't tested it but the current version should work fine with X-Sendfile.

This is one of those lines of code that just shines with Ruby magic.

@headers['Content-Type'] = TYPES[path[/&#46;\w+$/, 0]] || "text/plain"

A couple of things are happening here. The path string passed in to the function, which is the name of the resource, is accessed using a regular expression, path[/.\w+$/, 0], a dot followed by one or more word characters. The 0 says which atom of the match data to return, and is actually redundant, I believe, as no atoms are defined, and 0 is the entire match anyway. There are more details in the String API.

The regular expression grabs the extension of the file, which is then used as the key into the TYPES hash. If the extension is in the hash, the appropriate content type will be returned and the header set. If it isn't in the hash, nil will be returned, Ruby's tasty || operator will come into effect, and the content type will be set to a sensible default, text/plain.

Using JQuery with Camping


Camping is great, yeah. JQuery too. Maybe you want to use them together? Here's how.

First, you need to set up a route for your JQuery. I've talked about sending static files with Camping before, so this is just a modification of that. [You can serve static files more sensibly than setting up a route for each type. Maybe one day I'll write about that.]

In your controller:

module MyApp::Controllers
  class Index &lt; R '/'
    def get
      render :index
    end
  end
  class JQuery &lt; R '/resources/jquery.js'
    def get
      current<em>dir = File.expand</em>path(File.dirname(<strong>FILE</strong>))
      @headers['Content-Type'] = "text/javascript"
      @headers['X-Sendfile'] = "#{current_dir}/resources/jquery.js"
    end
  end
end

Now you have to get the JQuery library in your view.

module MyApp::Views
  def layout
    html do
      head do
        title 'Using JQuery in Camping'
      end
      body { self &lt;&lt; yield }
    end
  end
  def index
    script :src => R(JQuery), :type => 'text/javascript'
    script do '
      $(document).ready(function() {
          alert("Hello world!");
      });
      '
    end
  end
end

The call to the R function creates the URL for the JQuery library. Now you can embed any JQuery yumminess that you want, right there in your view.

Serving static files with Camping


Camping interprets every request to the server using the paths in the controllers, so if you want to serve static files, like external stylesheets or images, you need to provide a controller for them. Take this bit of Markaby:

img :src => 'images/logo.png'

This will get interpreted by Camping and end up with this HTML:

<img src="images/logo.png">

When the browser reads that, it will send a GET request to the Camping server looking for logo.png, that Camping will try to match against the controller paths. If you haven't set one up, you'll get an error.

So, in your Controllers module:

class StaticImage &lt; R '/images/(.*)'
  def get(static_name)
    current_dir = File.expand_path(File.dirname(<strong>FILE</strong>))
    @headers['Content-Type'] = "image/png"
    @headers['X-Sendfile'] = "#{current_dir}/images/#{static_name}"
  end
end

and in your View module, create the link like this:

img :src => R(StaticImage, 'logo.png')

Shake and bake for any kind of static resource you want to send.

hpricot downcases element names


The title says it all really. I'm using hpricot for the first time, and the page I'm scraping has quaint uppercase HTML elements, shouting its TABLEs at me. It took me quite a while to work out that I didn't have to shout at hpricot.

Ruby Find and changing directories


When working with Ruby's Find, don't change directories with FileUtils.cd, as Find gets confused. You're better off working with full paths (use File.expand_path).