Pivotal Labs

dot.rake

edit Posted by Alex Chaffee on Saturday September 29, 2007 at 12:06AM

Treetop 1.0.1

edit Posted by Nathan Sobo on Saturday September 15, 2007 at 12:25AM

I've been working on a parsing framework for Ruby since January called Treetop. I just released version 1.0.1 and recorded this screencast demonstrating its use.

String#split and regex lookarounds

edit Posted by Felix Morio on Tuesday September 11, 2007 at 12:09AM

Ruby supports regular expression quite well, so it's not surprising that one can use a lookaround to match a specific position. That also works really well with String#split, so if one needs to extract the key/value out of a string such as this:

s = "TYPE=Exterior RED=119 GREEN=105 BLUE=88 TABLEREQ=PNTTBL-01 TABLE=Primary w/XL GENERICCLR=Beige GENERICCLRCODE=31"

this will do nicely:

s.split(/\s(?=[A-Z]*=)/)

Just splitting on "space" won't work because there are spaces inside the values, too ("Primary w/XML").

Simple and useful...

Ruby quiz du jour answer

edit Posted by Felix Morio on Thursday September 06, 2007 at 10:15PM

Josh got it right.

1.0/0

indeed resolves to "Infinity". Pretty cool!

-Felix

pong

edit Posted by Alex Chaffee on Thursday September 06, 2007 at 03:05AM

Oscillosocope Pong

ping is awesome, but it's a little simple-minded. I often find myself running several pings at a time, especially when debugging network configurations. And when you're watching ping run in several windows, as routers go up and down and packets spurt and congeal like blood in a trauma center, extra features spring naturally to mind...

Enter pong. It's a Ruby app I wrote that runs ping in the background and decorates the results, tracking statistics in realtime, refreshing the screen every 5 seconds. Here, I'll show you:

% pong localhost 192.168.1.240 192.168.1.1 google.com yahoo.com pivotalblabs.com

Last 10 seconds:
Mean            Missing         Host
   0.073 msec      0 (0.00%)    localhost (127.0.0.1)
   2.884 msec      0 (0.00%)    192.168.1.240 (192.168.1.240)
  25.745 msec      0 (0.00%)    192.168.1.1 (192.168.1.1)
  98.905 msec      0 (0.00%)    google.com (72.14.207.99)
  38.761 msec      0 (0.00%)    yahoo.com (66.94.234.13)
 113.418 msec      0 (0.00%)    pivotalblabs.com (72.9.100.34)

Last 60 seconds:
Mean            Missing         Host
   0.092 msec      0 (0.00%)    localhost (127.0.0.1)
   5.757 msec      0 (0.00%)    192.168.1.240 (192.168.1.240)
  24.198 msec      0 (0.00%)    192.168.1.1 (192.168.1.1)
  98.840 msec      1 (1.67%)    google.com (72.14.207.99)
  38.504 msec      0 (0.00%)    yahoo.com (66.94.234.13)
 110.687 msec      0 (0.00%)    pivotalblabs.com (72.9.100.34)

Entire run (97 sec):
Mean            Missing         Host
   0.088 msec      0 (0.00%)    localhost (127.0.0.1)
   5.716 msec      0 (0.00%)    192.168.1.240 (192.168.1.240)
  23.713 msec      1 (1.03%)    192.168.1.1 (192.168.1.1)
  99.261 msec      1 (1.03%)    google.com (72.14.207.99)
  35.403 msec      0 (0.00%)    yahoo.com (66.94.234.13)
 105.349 msec      4 (4.12%)    pivotalblabs.com (72.9.100.34)

I've packaged it up as a gem and put the source on RubyForge. Install it with

sudo gem install pong

and let me know what you think. Bug reports, feature requests, and (naturally) patches welcome. Currently it's only been tested on OS X and might work on other Unixes.

(Image of Edmond Lau's two-player analog oscilloscope Pong.)

Ruby quiz du jour

edit Posted by Felix Morio on Wednesday September 05, 2007 at 07:24PM

Question:

In Ruby, what does the following represent?

-1.0/0...0

Post your guesses as comments. Answer tomorrow. (No fair using irb.)

  • Felix and Alex and Koung

HasFinder -- It's Now Easier than ever to create complex, re-usable SQL queries

edit Posted by Nick Kallen on Sunday September 02, 2007 at 01:56AM

HasFinder is an extension to ActiveRecord that makes it easier than ever to create custom find and count queries.

Let's start with an example. Suppose you have an Article model; some articles are published, some are popular. Let's declare finders for each of these notions. You may be tempted to write something like the following:

class Article < ActiveRecord::Base
  def self.published
    find(:all, :conditions => {:published => true})
  end

  def self.popular
    ...
  end
  ...
end

But there are serious limitations to this approach. How do you find articles that are BOTH popular and published? How can you easily paginate published articles?

HasFinder Features

Let's define the equivalent finders using my new plugin, has_finder:

class Article < ActiveRecord::Base
  has_finder :published, :conditions => {:published => true}
  has_finder :popular, :conditions => ...
end

Query Composition

Now, you can elegantly compose queries:

Article.published.popular

This will return all articles that are both popular and published.

Calculations and Nested Finds

You can also easily paginate or call nested finders or do calculations:

Article.published.paginate(:page => 1)
Article.published.popular.count
Article.popular.find(:first)
Article.popular.find(:all, :conditions => {...})

Works with ActiveRecord has_many and has_many :through Associations

Furthermore, without any additional work, these finders will work with ActiveRecord associations.

class User
  has_many :articles
end

user.articles.popular.find(:first)
user.articles.published.popular.average(:view_count)

Finders are extendable just like ActiveRecord Associations

class Article
  has_finder :unpublished :conditions => {:published => false} do
    def published_all
      find(:all).map(&:publish)
    end
  end
end

Alternatively, you can use the :extend options:

class Article
  has_finder :unpublished, :conditions => ..., :extend => MyExtensionModule
end

Finders behave just like ActiveRecord Associations

For example, you can call #reload:

Article.published.popular.reload

Finders can take parameters

class Car
  has_finder :colored, lambda {|color| { :conditions => {:color => color} } }
end

Car.colored('red').paginate(:page => 1)

What makes HasFinder better than alternatives like scope_out and scoped_proxy?

There are already two plugins similar to HasFinder: scope_out and scoped_proxy. Both of them are excellent. In fact, Scoped Proxy was the model for HasFinder. Unfortunately, neither plugin provided all of the features I desired. Scope-Out lacks on-the-fly composition, a nice way to call a nested find, or the ability to do arbitrary calculations. Scoped Proxy is great, but it doesn't work with regular ActiveRecord Associations, it is not extendable like ActiveRecord associations, and it doesn't behave exactly like a regular ActiveRecord Association. Neither of them work out of the box with will_paginate. For all of these reasons and more, I rolled my own. It's now available as a gem.

Installation

% gem install has_finder

Usage

In environment.rb:

gem 'has_finder'
require 'has_finder'

See the examples above for usage.