“Mad Libs” Style Forms

Luke Wroblewski, Chief Design Architect at Yahoo! and author of “Web Form Design“, published a very interesting post about “Mad Libs” Style Forms and how he improved the conversation of vast.com by 25-40%.

This is how Luke tweaked the contact form:

Read the full post: “Mad Libs” Style Form Increases Conversion 25-40%

I wondered whether there is an easy way to put the labels below the text fields as one knows it fromthe original Mad Libs. This is what I came up with:

The HTML and CSS is fairly easy:

Get the whole code from my Mad Libs Github repository.
Or see it in action

Obviously this is not a guarantor for a 40% conversion increase. But it smells like fun a/b testing, doesn’t it?

General

Code Readability vs Optimization

There are times when I debate whether to use one-liners or break them out into more readable blocks. Recently I had a situation where I needed to check certain fields on an object depending on the status of other fields.

Let’s say I have a Book object and I wanted to see if it’s condition is good only if the book is checked in.

Here’s an example:

Book=book.first
def is_ok?()
if book.checked_in?
book.good? && book.barcode.nil?
else
book.barcode.nil?
end
end
require 'benchmark'
bools=[true,true,true,true,true]
l_times=[]
c_times=[]
0.upto(bools.size) do |pos1|
0.upto(bools.size) do |pos2|
logic_time=Benchmark.realtime { 1000.times { bools[0] && bools[1] && bools[2] && (bools[3] && bools[4] || !bools[2]) } }
puts "logic realtime: " + logic_time.to_s
control_time=Benchmark.realtime { 1000.times { bools[3] ? bools[0] && bools[1] && bools[2] && bools[3] : bools[0] && bools[1] && bools[2] } }
puts "control realtime: " + control_time.to_s
l_times << logic_time
c_times << control_time
bools[pos1]=false
bools[pos2]=true
end
end
puts "average logic time: #{eval('('+ l_times.join('+').to_s + ')/'+l_times.size.to_s)}"
puts "average control time: #{eval('('+ c_times.join('+').to_s + ')/'+c_times.size.to_s)}"

Here’s the result of one run:
average logic time: 0.00086206080866795
average control time: 0.000861808365466548

I know this test doesn’t go through every boolean case, I just wanted to whip up something fast to give myself a piece of mind. After running this a serveral times, the average times varied, sometimes control would be faster, sometimes logic would be faster. The time difference is basically nil.

Conclusion: Go for readability in a case like this, because the performance differences are not noticeable and readers of your code won’t have to build a boolean table to figure out what’s going on.

General

Duck it.

Ruby is not a strongly typed language so we sometimes need to check types explicitly. In a ducktyped world this might be less obvious than you might think. In particular, testing code that is testing input types explicitly can be harder than needed. This morning I came to work with a bunch of spec failures in some of our code.

The method being tested looked something like this:


def devour(candy)
  if candy.is_a?(SourCandy)
    SourDevouringEngine.new(candy)
  elsif candy.is_a?(Chocolate)
    ChocolateDevouringEngine.new(candy)
  end
end

If I send in a mock(‘SourCandy’) to the above I get nil back. Most probably not what I meant and surely defying the purpose of testing it.

It’s actually a tricky issue to solve properly. The standard answer you’d get on ruby-talk is to use :respond_to? instead of :is_a? (or the uglier cousin “candy.class == SourCandy”) along with some sassy comment on how ruby is ducktyped yada yada.
I personally feel that is kinda clunky as it relies on SourCandy having some distinct method Chocolate does not have.
Using respond_to?(:fun_fun_fun) also means that I as a developer implicitly state that SourCandy#fun_fun_fun shall always be around and that Chocolate shall never have fun_fun_fun.

That feels wrong too.

So what’s the right way? I don’t have a catch-all answer to that but I think that having to test for type is a slight code smell and an indication that the class structure is not correct.
The code above should be refactored in such a way that I can call devour in the example above directly on the candy object, letting Ruby take care of the distinction. Like so:


def devour(candy)
  candy.devour_engine
end

There are situations where I feel testing for an explicit type is ok. Argument checking in an #initialize method for instance:


class Candy
  def initialize(color, taste)
    raise ArgumentError, "Bacon is not ok." if taste.is_a?(Bacon)
    @color = color
    @taste = taste
  end
end

Another example where it’s sometimes ok is when a method tries to be flexible in input (always good thing) by allowing, say, a String instead of a single-element Array. Like so:


class Dude
  def friends=(persons)
   persons = [persons] if persons.is_a?(Person)
   @friends = persons
  end
end
me = Dude.new
# Both works
me.friends = some_person
me.friends = [some_person, some_persons_brother]

The above is acceptable although I’d prefer using the splat operator to ensure a flat Array: “@friends = [*persons]“.

The take-away here is:

  • explicit type checking is almost never needed: check and double check if you really need it
  • don’t bend over backwards to accomodate crazy calling patterns, requiring you to typecheck; often it’s simply not worth it and it makes your code harder to read and test
  • prefer is_a? to “.class == ‘SomeClass’”
Article

The state of Rails plugins

Plugins are great, they help you dry up your code, add features, etc. quickly and easily. But how do you know if a plugin is going to be good, or if it’s outdated completely…..

I usually check the following sites to find out:

http://railsplugins.org/ and http://www.ruby-toolbox.com/

The latter is mostly an overview of gems categorized by what they do, very helpful. What’s even more helpful is railsplugins.org since it lists compatibility with ruby 1.9, rails 3.0 and also has a user upmod system to gather results from people actually using the plugins.

General

Using will_paginate in sinatra

Want some sweet pagination on your sinatra app? I know it’s a loaded question with sinatra’s methodology of keeping things slim, but here goes.

There is a framework agnostic branch of mislav-will_paginate on github. What I did was pull that into vendor/gems and added the following code to make it work.

$LOAD_PATH.unshift File.dirname(__FILE__) + '/vendor/gems/will_paginate/lib' # using agnostic branch

require File.dirname(__FILE__) + '/vendor/gems/will_paginate/lib/will_paginate'
require File.dirname(__FILE__) + '/vendor/gems/will_paginate/lib/will_paginate/view_helpers/link_renderer'
require File.dirname(__FILE__) + '/vendor/gems/will_paginate/lib/will_paginate/view_helpers/base'
include WillPaginate::ViewHelpers::Base

Array.class_eval do
  def paginate(opts = {})
    opts  = {:page => 1, :per_page => 15}.merge(opts)
    WillPaginate::Collection.create(opts[:page], opts[:per_page], size) do |pager|
      pager.replace self[pager.offset, pager.per_page].to_a
    end
  end
end

WillPaginate::ViewHelpers::LinkRenderer.class_eval do
  protected
  def url(page)
    url = @template.request.url
    if page == 1
      # strip out page param and trailing ? if it exists
      url.gsub(/page=[0-9]+/, '').gsub(/\?$/, '')
    else
      if url =~ /page=[0-9]+/
        url.gsub(/page=[0-9]+/, "page=#{page}")
      else
        url + "?page=#{page}"
      end
    end
  end
end

The above code does a couple things, let’s you call paginate on an array, and have access to the will_paginate view helpers. It works as easy as this:

get 'posts' do
  @posts = Post.all.paginate
end

And then in whatever template engine you’re using just call:

will_paginate @posts
Article