Post Redirect Get in Rails

Post St.
Photo by Terry Bain

Post/Redirect/Get (PRG) is a web application design pattern used to supply users with nice, GET-generated results pages that bookmark and reload with ease.

Say you have a results page with a filtering form at the top. The user might alter filtering options, and submit a form to winnow down her results. This is a POST, meaning params will be hidden from the user (not in the URL), making direct bookmarks to the filtered results impossible. Also, reloading the page will result in a “POSTDATA” warning message (”Do you want to resubmit POST data or would you rather we do a hurkey-jerky dance to confuse you?”) to the user. These are not things people like to deal with. Post/Redirect/Get says that your application should accept the POST command, and redirect to the results page using a GET request.

This is really quite simple to implement in Rails. Take this example action filter for an expense report controller, reduced to its bare essentials:

class ExpenseReportsController < ApplicationController
  def filtered
    redirect_to fitered_expense_report_path(params) and return if request.post?
   
    # Actual action work here.
  end
end

Very easy - the trick is really knowing the pattern more than anything. There has been some discussion on adapting this to deal with validation failures. In my experience, I’ve only made use of this pattern in non-RESTful controllers. You are sure to do better with it than I.

Tumbling with Iridesco

It’s been officially announced - we at Iridesco are tumbling. Please visit often to peep the videos, photos, stories, and music getting us all abuzz.

Fixing slow rake on Leopard

Hay Rake Third Version
Photo by JBAT

In the past few months, as a result of my clumsiness, I’ve been working on a new, Leopard-enabled MacBook. When replacing my wet and dying Tiger MacBook of yore, my one hope was that my daily executions of rake to test Harvest would execute a little faster. A 20% increase in processor speed doesn’t buy one a whole lot when web programming. The one place I figured I’d see a bump is the constant processor use of rake.

Wrong. So, so, wrong.

After moving to a new MacBook with Leopard installed, I experienced a test suite that ran 2-3 times slower than on my old machine. This became the difference between testing frequently and hardly at all; the difference between using and not using autotest. Pain to the max.

This post is going to get long, so I’m going to reveal now. For me, the issue was resolved by leaving the canonical Hivelogic world and reverting to the default Leopard installation of Ruby. Test speed returned to better-than-normal, and all at the price of only 6 hours of troubleshooting!

Continued reading >

open_id_authentication plugin and remember me

Do you run a Rails website that allows traditional username/email/password login and OpenID authentication? Do you know for sure that your “remember me” feature is working? Please do check…I’ll wait…

Good, now that you realize your “remember me” feature is not working for the OpenID login on your site, I’ll show you an easy way to hack it into the latest version of the open_id_authentication plugin. My preferred method to hack plugins is the evil twin technique.

The basic problem here is that your login form’s parameter list is not being passed back to your application after authenticity is checked at the OpenID provider. You have a remember_me checkbox, and, dammit, you want that parameter passed through. (Program note: some say this is not proper technique. I’m just trying to get you a solution, however temporary that may be.)

We need to hack the opend_id_redirect_url method:

def open_id_redirect_url(open_id_request, return_to = nil)
  open_id_request.return_to_args[‘open_id_complete’] = ‘1′
  open_id_request.redirect_url(root_url, return_to || requested_url)
end

Using the evil twin technique, create an “open_id_authentication_hacks” folder in your vendor/plugins directory. Within this directory, create an “init.rb” file and add the following:

OpenIdAuthentication.module_eval do

private

  def open_id_redirect_url_with_remember_me(open_id_request, return_to = nil)
    open_id_request.return_to_args[‘remember_me’] = params[‘remember_me’]
    open_id_redirect_url_without_remember_me(open_id_request, return_to)
  end
  alias_method_chain :open_id_redirect_url, :remember_me

end

Now you have a nicely aliased method that includes the remember_me parameter upon returning to your app.

Presentation: an audience perspective

Baked NYC

This weekend I attended RailsConf. This was my first multi-day conference. It was a great experience that I’m sure to repeat over the coming years. Met a lot of great Rails developers, working on interesting and disparate projects. Met a good number of Harvest users who spoke to me using words like “enjoy,” “love,” and, most surprisingly, “famous.” Even met people doing Important Stuff ™ who didn’t particularly care to hear about my story.

Watching speaker after speaker is terribly motivating. Soon the realization that this blog has pretty well been dormant in 2008 came to mind. The realization that I’ve not prepared a proper presentation…ever…entered my thoughts. As I sat in sessions, I found myself, with a wide sliver of irony, writing down presentation techniques that pleased and bothered me.

Humor

You have to include humor in your talk. Most presenters are aware of this. However, many presenters front-load their humor. It’s difficult to lace the entire flow of information with engaging humor, but this is one of the most outstanding ways to provide a positive experience for the audience - one that causes them to pursue the topic after the fact.

In the case of technical talks, one must be careful not to make the humor the focus. But generally speaking, presenters tend to err on the opposite end of the spectrum.

A consistent metaphor

Several sessions included an interesting, nerdy metaphor. Don’t meticulously introduce the Star Wars comparison and then drop it for the rest of the presentation. Lace that damn B-wing throughout the slides.

Know your environment

Your super-sexy, light-on-dark TextMate theme is most likely going to cause the audience fits. They will yell at you, especially if it is the cranky third day.

Greater than 15 lines of code is unlikely to be readable by the audience. Know how to zoom or bigify your code or think of other creative ways around the problem.

Slide titles should be mid-screen or higher. Cool MTV banner titles along the bottom of the screen are likely difficult for most of the audience to read, save for the most ideal conference situations.

Unless the presentation calls for frequent interaction with your computer, stand up. Give yourself the air of authority and the confidence that you are qualified to share information with the group. Don’t pace, and get yourself some sleep the day before.

Timing

Don’t hope your talk will fit into the given time slot, know it will fit. Err on the side of too short, please. Don’t promise time for questions unless you’re certain you can deliver. Plan for interruptions (technical issues, in-presentation questions, rambling, etc). You will be refreshing and set yourself apart if you deliver a well-tuned, concise message.

Tell them what they want to hear

Or Pander to the crowd.

Or Tell them what they already know, in a new way.

Or Inspire them to pursue what you know they want to pursue.

Littering your presentation with known community mores will give you at least a knee-jerk positive reaction. The audience wants to laugh, nod, clap, and feel assured in their own choices. Be a catalyst.

Ideally your whole presentation shouldn’t be comprised of such a message. But if you don’t have anything nice to say, reflecting your audience is probably your safest option.

If all else fails, blow their minds

Announce a product, process, tuning, enhancement, iteration or whatever that carries along with it jaw-dropping statistics. The nice thing about this is you don’t have to necessarily give the product in question to anyone to prove your statements - at least not right away. Plan on delivering something within a few months, and deliver something within 50% of the improvements originally touted, or you will be blasted.

This talk can be combined with telling people what they want to hear to make a powerful concoction. It is workable to describe utopian worlds where downfalls are leveled with a Sim-City-like ease. Again, any improvements will be welcomed, and the army of supporters from announcement-time will do all of you defense for you when the rubber meets the road.

It’s not about you

Indeed, some speakers enjoy well-attended presentations due to their niche fame. Still, it is not about them. It is about what the speaker can do for me, the audience member. How do you help me to relate to you? How do you help me fit your perhaps only tangentially applicable message into my situation? How can you generalize the information you have for public consumption? How can you make it all about me?

Technorati Tags: , ,

RailsConf ‘08

Just wanted to drop a note in my blog, here, that I will be attending RailsConf from Friday through Sunday. If any lurkers out there are gonna be in attendance, do drop me a note. Let’s meet each other!

If you want to stay up-to-date on any Barry-meets-RailsConf information, please check me out on Twitter.

Technorati Tags: ,

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.