Working Remotely? Thinking about it?

Are you a member of a geographically dispersed team? Are you thinking of working remotely, or hiring remote developers? Wide Teams is my new blog and podcast for distributed teams. Check it out for getting started guides, tips and best practices, news, interviews, screencasts, and more all about working remotely and collaborating with wide-spread teams.

ANN FireTower 0.0.4

2010 August 17
by avdi

For those of you using Campfire to communicate with your team, FireTower 0.0.4 is now out. New in this version is full Mac OSX support, courtesy of David T. Rogers.

Install:

gem install firetower

Enjoy!

Bookmark and Share

Treating Arrays as Sets

2010 August 17
tags: ,
by avdi

Reading through the Rake source code the other day (a pastime I highly recommend), I was reminded of a technique I don’t use often enough:

my_array = [:foo, :bar, :baz]
my_array |= [:baz, :buz] => [:foo, :bar, :baz, :buz]

Note that’s a single pipe before the equals sign.

The code above adds only unique elements to the array; duplicates are ignored. Ruby Arrays actually implement a small collection of set operations with the &, | operators. Of course, for serious set needs you can use Ruby’s Set, but |= is handy for uniquely appending to an array.

Hey, do you enjoy Virtuous Code? Do you enjoy Netflix, internet video, radio, and podcasts? How would you like to help me out and get yourself a sweet deal on a Roku player at the same time?

If you click this link you’ll get a 10% discount on a Roku player, and I’ll get a free month of Netflix. I’m being completely honest when I say our Roku box was the best $99 I’ve ever spent on an electronic device. Unlike so many devices that go obsolete after a Year, Roku has been steadily adding capabilities to it – first HD video, then a myriad of channels including Netflix, Amazon Unbox, Network news video, the NASA channel, university lectures, Pandora, podcasts, and much more. If you want a simple set-top box to put he internet in your TV, it doesn’t get much better than the Roku.

Bookmark and Share

Using Hashes as Caches

2010 August 5
by avdi

One of the coolest features of Ruby’s Hash class is that you can customize how it behaves when it can’t find a key. Stupid example:

# Everybody knows that you can communicate with foreigners by
# speaking loudly and slowly
english_to_french = Hash.new{|hash, key|
  hash[key] = key.upcase.split(//).join(" ") + "?!"
}
english_to_french["restroom"]   # => "R E S T R O O M?!"

One particularly useful application of this feature is to use a Hash as a cache for some slow operation. Here’s a snippet from Firetower, where a Hash is being used as a table of user accounts. If an unknown user ID is requested, the Hash makes a web service call to retrieve the requested data, stores it away, and returns it.

      @users = Hash.new do |cache, user_id|
        data = session.get(subdomain, "/users/#{user_id}.json")
        cache[user_id] = data['user']
      end
Bookmark and Share

“and” and “or” are like backwards statement modifiers

2010 August 3
by avdi

It occurred to me after reviewing all the feedback to my last post that despite making the connection to statement modifiers, I never directly contrasted the two. And that this might be an even simpler way of explaining the usefulness of and/or in Ruby. I’ve added the following examples to the original post, but in case you missed it:

and

You can think of and is as a reversed if statement modifier:

  next if widget = widgets.pop

becomes:

  widget = widgets.pop and next

Because of the low precedence of and, no extra parentheses are needed here as they would be for &&.

or

Likewise, or is a reversed unless statement modifier:

  raise "Not ready!" unless ready_to_rock?

becomes:

  ready_to_rock? or raise "Not ready!"

Conclusion

Which version to use – if/unless or and/or – depends on your taste and what reads well in a given case. But it’s nice to have the option.


Bookmark and Share

Using “and” and “or” in Ruby

2010 August 2
by avdi

If you use Ruby long enough, you will discover the and and or operators. These appear at first glance to be synonyms for && and ||. You will then be tempted to use these English oprators in place of && and ||, for the sake of improved readability.

Assuming you yield to that temptation, you will eventually find yourself rudely surprised that and and or don’t behave quite like their symbolic kin. Specifically, they have a much lower precedence. At this point, you may decide to swear off the use of and and or as too confusing.

But that would be doing your code a disservice. and and or are useful operators; you just need to understand their special place in Ruby programs.

and and or originate (like so much of Ruby) in Perl. In Perl, they were largely used to modify control flow, similar to the if and unless statement modifiers. A common Perl idiom is:

do_something() or die "It didn't work!";

The and and or keywords serve the same purpose in Ruby. Properly understood, and and or are control flow operators, not boolean operators.

and

andIs useful for chaining related operations together until one of them returns nil or false. For instance:

post = Post.find_by_name(name) and post.publish!

Here, the post will only be published if it is found, due to the short-circuiting nature of and. How does this differ from &&? Let’s take a look at an even simpler example:

foo = 42 && foo / 2

The intent here is to assign a variable and then divide it by 2. Since we are just assigning a constant value on the left side, both sides of the && will always be evaluated, right? Let’s give it a try:

NoMethodError: undefined method `/' for nil:NilClass
        from (irb):18
        from :0

Was that what you expected? As it turns out, with the relatively high operator precedence of &&, the way that code is actually parsed looks like this:

foo = (42 && foo) / 2

…which is clearly not what we want. Contrast that to the and version:

foo = 42 and foo / 2 => 21

…and now we have the answer we were expecting.

Another way of thinking about and is as a reversed if statement modifier:

  next if widget = widgets.pop

becomes:

  widget = widgets.pop and next

or

or, likewise, is useful for chaining expressions together. The best way to think about the chains constructed with or is as series of fallbacks: try this, if that fails try this, and so on. For instance:

  foo = get_foo() or raise "Could not find foo!"

You can also look at or as a reversed unless statement modifier:

  raise "Not ready!" unless ready_to_rock?

becomes:

  ready_to_rock? or raise "Not ready!"

Conclusion

and and or, despite an apparent similarity to && and ||, have very different roles. and and or are control-flow modifiers like if and unless. When used in this capacity their low precedence is a virtue rather than an annoyance.

UPDATE: Simplified and clarified some examples based on feedback; added comparisons to if/unless statement modifiers.

UPDATE 2: Preston Lee delivers a much more thorough history lesson on the Perl origins of these operators.


Bookmark and Share

RPCFN Solution

2010 July 21
by avdi

For the curious, my personal reference solution to my Ruby Challenge is now online. More commentary to come later.

Bookmark and Share

Greenletters: Painless automation and testing for command-line applications

2010 July 19
by avdi

539px-IBM-3279

Did you ever use Expect to automate a complex command-line procedure, like an FTP upload? Expect is handy – and very powerful – but for Ruby projects it sure would be nice to be able to automate console apps directly from Ruby.

You may not have known it, but Ruby actually ships with a tiny Expect clone called expect.rb. Unfortunately it’s more of a proof of concept than a fully functional automation tool.

Enter Greenletters. Greenletters begins to bring some of the power of Expect to Ruby, with a simple, straightforward API. For example, here’s a scripted interaction with the classic Colossal Cave Adventure:

  require 'greenletters'

  adv = Greenletters::Process.new("adventure", :transcript => $stdout)

  # Install a handler which may be triggered at any time
  adv.on(:output, /welcome to adventure/i) do |process, match_data|
    adv < < "no\n"
  end

  puts "Starting adventure..."
  adv.start!

  # Wait for the specified pattern before proceeding
  adv.wait_for(:output, /you are standing at the end of a road/i)
  adv << "east\n"
  adv.wait_for(:output, /inside a building/i)
  adv << "quit\n"
  adv.wait_for(:output, /really want to quit/i)
  adv << "yes\n"
  adv.wait_for(:exit)
  puts "Adventure has exited."

Greenletters also ships with some simple Cucumber steps, so you can immediately start using it to specify the behavior of your command-line apps:

    Given process activity is logged to "greenletters.log"
    Given a process "adventure" from command "adventure"
    Given I reply "no" to output "Would you like instructions?" from process "adventure"
    Given I reply "yes" to output "Do you really want to quit" from process "adventure"
    When I execute the process "adventure"
    Then I should see the following output from process "adventure":
    """
    You are standing at the end of a road before a small brick building.
    Around you is a forest.  A small stream flows out of the building and
    down a gully.
    """
    When I enter "east" into process "adventure"
    Then I should see the following output from process "adventure":
    """
    You are inside a building, a well house for a large spring.
    """

Want to give it a try? Then:

gem install greenletters

And check out the examples/ directory for inspiration. Let me know what you think!

Bookmark and Share

Announcing Firetower – A command-line interface to Campfire

2010 July 11
by avdi

OK, this is pretty early stuff but it’s already usable and I think it has a lot of potential.

BaldMountainLookoutFiretower is a command-line interface to Campfire. It’s currently for Linux systems only, but there’s no reason it can’t be extended to work on OS X as well.

I created it because I needed a command-line interface to Campfire that supported the current streaming Campfire API. I also wanted a bit more flexibility than existing tools provided.

You can read all the details at the Github page, but in a nutshell Firetower provides two services:

  1. A way to post messages and code snippets to Campfire from the command line; and
  2. A daemon which will monitor any number of campfire rooms (in any number of accounts) and take user-configurable action when events (such as new messages) occur.

The latter service is particularly flexible: it can be used to do anything from playing a sound when someone says something in a Campfire room, to implementing IRC-style bots which monitor rooms for keywords and respond accordingly.

For instance, here’s a simple (and HIGHLY UNSAFE!) Ruby eval-bot which you could drop into ~/.firetower/firetower.conf:

receive do |session, event|
  if event['type'] == 'TextMessage' && event['body'] =~ /^!eval (.*)$/
    event.room.account.paste!(event.room.name, "Eval result:\n" + eval($1).to_s)
  end
end

Which is triggered when anyone in the room prefaces a message with “!eval”:

campfire_eval2

Patches, suggestions, and bug reports welcome!

Bookmark and Share

Rack-Test and Capybara are uneasy bedfellows

2010 June 18

I’m using Capybara on a new project because apparently it’s the new hotness. Today I found out that all is not peaceful in the Cucumber/Capybara/Rack-Test stack. There is a cold war going on, and both Capy and Rack-test are jealously guarding their own cookie jars.

Why does this matter? Well, say you use post '/some_callback', :some => "data" in your tests to simulate a callback from an external service like Janrain. Then you use visit '/' to simulate the user loading a page after the callback.

Any cookies set during the post will be ignored by the visit call, because like I said earlier, Capy and Rack-Test don’t share cookies. So if that callback action set up a user session, that session is now lost from the point of view of Capybara (and all the Cucumber steps that use Capybara).

Putting this out there in case anyone else runs into it and is as befuddled as I was.

Bookmark and Share

Rails 3 resource routes with dots; or, how to make a Ruby developer go a little bit insane

2010 June 18
by avdi

This one cost me at least an hour of frustration.

So apparently the Rails router has considered the dot (“.”) to be a “separator” character along with the slash (“/”) since version 1.2. I don’t know in what context this ever seemed like a good idea, but whatever. It’s not the sort of thing that’s going to bite you every day, but when it does it will be in very weird ways. To wit:

First, a simple routes.rb.

  resources :users do
    resources :projects
  end

Fill in some typical values, and you get a path:

irb(main):009:0> app.user_projects_path("avdi")
=> "/users/avdi/projects"

Now fill in a value with a period in it, and watch it explode:

irb(main):010:0> app.user_projects_path("avdi.grimm")
ActionController::RoutingError: No route matches {
  :user_id=>"avdi.grimm", :action=>"create", :controller=>"projects"
}

:action => "create"? What?!! Who said anything about create?!

As it turns out, there is an invocation in your routes file which will fix this:

  resources :users, :constraints => { :id => /.*/ } do
    resources :projects
  end
irb(main):013:0> app.user_projects_path("avdi.grimm")
=> "/users/avdi.grimm/projects"

Now I know what you’re thinking. “That’s so obvious, why didn’t he think of that immediately?” What can I say, some days I’m slow.

Bookmark and Share