Ventorium: my lark of a project

Over the past few weeks, in spare moments, I put together a little Twitter bot which allows the service to blow off some steam. Ventorium works pretty simply. Follow “ventorium” on Twitter. Send @ventorium a message. See what spews forth from ventorium’s maw.

I must keep the secret to how ventorium writes its messages. Though if you think hard enough, you can probably figure it out.

Give ventorium a shot. It may alleviate your own need to bitch.

MinneBar 2008 and distributed teamwork

Distributed Team
Photo by Yves Hanoulle

MinneBar forewarning. I will be participating in a panel discussion on distributed teamwork. I put out a call a while back and received several responses. A good core group has formed, all with varying experiences in the distributed, or “virtual,” team environment.

My experience is clearly with Iridesco working on Harvest. My focus will be on ways to find a distributed team to work with as well as the tools we use to communicate. Soapbox-wise, I’ll be pretty adamant about creating an actual team that includes a bit of play with their work. We’re hacking on a new piece of Harvest that we think will improve this situation. We also have been trying other ways to establish a distributed watercooler.

I hope to see you at MinneBar. If you are interested in distributed teams, please come participate in our panel discussion. Even if you are just considering breaking those corporate shackles for a more humane work environment, what a great way to jump start your search!

Five Rails tips

Ryan Bates, of the excellent Railscasts, is running a contest to generate a bevy of Rails tips on the web. (And look, Harvest is part of the grand prize package. W00T!)

Here’s my contribution:

Handy test helper to check your layout:

Do you have any layout variability served up in your controllers? Maybe you’re doing some iUI work and want to test that no layout is being served up at all?

def assert_layout(layout)
  assert_equal layout, @response.layout
end

Usage:

assert_layout ‘layouts/application’
assert_layout nil

Handy test helper to check your format:

In a similar vein, do you have format variability served up in your controllers? Say you are presenting a mobile site that adjusts the format according to subdomain. Well, you may want to test that as well.

def assert_format(format)
  assert_equal format.to_sym, @request.format.to_sym
end

Usage:

assert_format :iphone

The flexibility of assert_select:

Did you know you can use regular expressions with assert_select? It’s pretty fun. Here’s a selector to verify a page does not include any table rows with ids of the form “day_entry_#”.

assert_select "tr[id*=?]", /day_entry_\d+/, :count => 0

Massage params when tweaking them for specific iPhone keyboards:

When developing a web app for the iPhone, the only apparent way to specify an entry field use the numeric keyboard is to include the string “zip” in the input name. To get the keypad numeric keyboard, include the string “phone”. What I like to do is append “_zip_keys” as necessary to an entry field’s proper name.

<%= form.text_field(:hours, :name => ‘day_entry[hours_zip_keys]‘) %>

This obviously causes problems when you are depending on Rails magic to build objects from passed parameters. In application.rb I created some massaging functions that rip through the params hash (and its subhashes) renaming the keys that are suffixed “_zip_keys” or “_phone_keys”.

##
# Some params on iPhone pages may be trailed with _zip_keys or _phone_keys to bring up proper keyboards.
# This method removes this sugar from the keys.
def massage_iphone_params
  return unless iphone_request?
  massage_iphone_keys(params)
end

IPHONE_KEYS_REGEX = /(_zip_keys|_phone_keys)$/

def massage_iphone_keys(_hash)
  temp_value =
  _hash.each do |key, value|
    massage_iphone_keys(value) and next if value.is_a?(Hash)
    if IPHONE_KEYS_REGEX === key.to_s
      temp_value = _hash.delete(key)
      _hash[key.to_s.sub(IPHONE_KEYS_REGEX, )] = temp_value
    end
  end
end

Making use of this key translator is as simple as a before_filter:

before_filter :massage_iphone_params, :only => [:create, :update]

Git meme

Here are my git aliases, which started with those presented in the Peepcode screencast.

# Git
alias gb="git branch"
alias gba="git branch -a"
alias gco="git checkout"    # add branch name to checkout
alias gm="git merge"        # add branch name to merge into current
alias gc="git commit -v"
alias gd="git diff | mate"
alias gl="git pull"
alias glb="git pull origin" # add branch name to the end
alias gp="git push"
alias gpb="git push origin" # add branch name to the end
alias gst="git status"
gcob(){ git branch –track $1 origin/$1; gco $1; }  # add remote root branch name to the end

(Most are self-explanatory. That last one basically creates a local branch named identically to its tracked source, and checks it out.)

Virtual Teamwork or You Can Go Home Again

Over the past year I have entered into a new world of working from home as part of a “virtual team.” This team situation carries with it most of the issues of a typical team as well as its own, unique hurdles. Working in a home office adds even more particulars.

In less than three weeks, MinneBar will be upon us again. This event provides a great opportunity to talk about virtual teams and working from home. I’d like to put together a discussion of such things, with a few people who hold varying roles in a virtual team structure to provide direction.

If you plan to be at MinneBar and spend 80% or more of your “billable time” working as part of a virtual team, please get in touch either via comment or email. Hopefully we can draw 3-6 folks with various viewpoints. I believe the hottest topics will be idea generation, project ownership, and team building. As for structure, I’d like to mostly spur on a group discussion rather than talk at people. Since I basically have zero experience presenting, suggestions are welcome.

While I think the challenges of working from home (You Can Go Home Again) are interesting, Virtual Teamwork is probably a topic that is more in demand. Though, I’m certainly open to focusing on the home office if that is seen as a better target. Get in touch and we can smooth the idea out - virtually.

Memetape 2

Push through the afternoon, folks. Five o’clock is just around the bend.

Kauffman Stadium, day 2

Dashing off another quick batch of pictures from the Good Guys disappointing loss at The K.

As expected, Francisco Liriano’s return was a bit rocky.

The King is back.

Hot chocolate and baseball, two great tastes…well, during playoff baseball.

Hot Cocoa

Hard to tell, but the sun did come out for moments today. One particularly fun moment was when the sun came out for 10 seconds right as the Royals shortstop, Tony Pena, Jr., looked up to catch a popup. Well, he didn’t catch it after that flash of sun.

This picture is a field view from just after that play.

Sun!

Jose Guillen topped that error in the first inning by plain dropping a fly ball in the outfield. The Royals fans hate Guillen, by the way. Probably because he’s not hitting right now. And they say only the east coast fans drift from day-to-day.

I was disappointed in the quality of fans at KC. Everywhere we sat involved scream-at-the-top-of-their-lungs loudmouths behind us yelling gems like “hit the ball, Tehan, the object of the game is to hit the ball!”, “Yeah, sit down! That’s it, sit down!” (to Twins fans), and “Yeaaaahhhhhhhhhhhhhhhhhhhhh!!!” (for about 15 seconds after a mid-inning prize).

Royals child-fans go shirtless for their moment of fame.

Shirtless Royals kids.

While Liriano needed to go out anyway, it appeared quite clear that 90 pitches was his pre-game-determined limit:

Thanks, F-bomb.

Royals fans mainly prefer beachballs to baseball. And who can blame them?!

Beachball.

Cold Kauffman Stadium

Some lighter fare. Phone pictures from 37 degree Saturday night at Kauffman Stadium.

Our starting seats:

Right field line.

Second seats with The Dad:

Behind the dugout

Particularly obnoxious crowd (both Twins and KC fans). Particularly obnoxiously run jersey promotion. 20k jerseys, 1.5k people in front of us at Gate D. Out of jerseys before we arrive at the gate. Yay.

Great stadium (under construction, so kind of a mess).

A fateful bases loaded, nobody out, score zero runs “rally”:

Bases juiced

Breathtaking new scoreboard (from Daktronics, I believe). They’re adding a crown on the top later:

Scoreboard

A Rails way to track additional schema info

Baked NYC
Photo by rachel is …

Right now at Harvest we are baking a few pans of Twitter integration. We’re not sure if they’ll turn out moist and delicious, but hopefully they stop short of dry and forgettable. It’s been a fun, and somewhat frustrating, process getting this feature cooking.

The key interaction Harvest is using is Twitter’s direct message. Send Harvest a message and we’ll pick it up and do something with it. Through the Twitter API, one can grab all direct messages since a certain direct_message.id. In this case, direct_message.id is used as a chronology identifier - the larger the id, the newer the message.

In order to go out and grab a batch of messages, the previous max direct_message.id needed to be tracked somewhere. To me, this felt similar to Rails’ schema_info table - direct_message_info we’ll call it. So with all of those Rails opinions, how do you set up such a schema-tracking table? First, you migrate:

class CreateDirectMessageInfo < ActiveRecord::Migration
  def self.up
    create_table :direct_message_info, :id => false do |t|
      t.column :last_id, :integer
    end
    ActiveRecord::Base.connection.insert("INSERT INTO direct_message_info VALUES(28700000)")
  end

  def self.down
    drop_table :twitter_direct_message_info
  end
end

This migration is fairly simple. When creating the table, we specify that there is no need for the Rails-default id column. Also, insert an initial starting value. I suggest playing with the API and selecting a value reasonably close to the latest id numbers for Twitter’s direct messages.

Then, throw your ActiveRecord model out the window for models/direct_message_info.rb:

class DirectMessageInfo
 
  class << self
    def get_most_recent_id
      ActiveRecord::Base.connection.select_one("SELECT last_id FROM direct_message_info")["last_id"].to_i
    end
   
    def set_recent_id(last_id)
      ActiveRecord::Base.connection.update("UPDATE direct_message_info SET last_id = #{last_id}") if last_id
    end
  end
 
end

Two pretty simple class methods for getting and setting your new schema info value.

Technorati Tags: ,

ActiveResource HTTP basic auth with email address

As I’ve started to play around here and there with ActiveResource, I’ve noticed lots of complaints about how ActiveResource’s implementation of HTTP basic auth leaves a lot to be desired. Specifically with regard to its lack of support for email addresses as usernames. This won’t work:

class Expense < ActiveResource::Base
  self.site = "https://barry@bjhess.com:password@website.com"
end

Turns out it’s fairly simple to authorize via email address in ActiveResource. Just send the header:

class Expense < ActiveResource::Base
  self.site = "https://website.com"
  @headers  = { ‘Authorization’ => "Basic (#{Base64.encode64(’barry@bjhess.com:password’).strip})" }
end

Technorati Tags: , ,

Memetape