Peel me a Grape :: We make things work

We Make Things Work :: Blog

Yesterday I deployed some reasonably well tested code to a rails app I’m working on.

I was adding an experimental version of an existing page to get early feedback. My mistake was how I edited my routes.rb. I dupped a line and ended up with something like

map.explore 'explore', :controller => 'interesting', :action => 'explore'
map.explore 'doraexplore', :controller => 'interesting', :action => 'dora'

The problem is I accidentally eclipsed my intended named route with this experimental one. So when I used explore_path in my views, it generated /doraexplore instead of /explore.

I tested both pages side by side in my browser and they did as expected, but unfortunately I didn’t click where the page is linked from.

This has happened me before, but won’t happen again!

I’ve written a little initializer that extends rails routing to raise an error if these clashes are introduced.

Place the following code in /RAILS_ROOT/config/initializers/detect_named_route_clashes.rb (available here on gist.github)

module IGOpeople
  module Routing
    module BorkOnNamedRouteClash
      def self.included(base)
        base.alias_method_chain :add_named_route, :checking_clash
      end

      def add_named_route_with_checking_clash(name, path, options = {})
        if named_routes[name.to_sym].nil?
          add_named_route_without_checking_clash(name,path,options)
        else
          raise('clashing named route: '+ name.to_s)
        end
      end
    end
  end
end

if ['development','test'].include?(RAILS_ENV)
  ActionController::Routing::RouteSet.send(:include, 
      IGOpeople::Routing::BorkOnNamedRouteClash)
end

Now when I run my app, it raises an error clashing named route: explore.

I hope this will help others avoid the mistake I made.

I’m part of the recently formed Web Development Working Group within the IIA.

We aim to provide useful information and no nonsense advice to help businesses make smarter decisions when it comes to web development.

At our first meeting we decided it would be wise to collect some information to help us to decide what to focus on.

Please fill out this short survey.

Chat to one of us this week at FOWA Dublin, or Bizcamp Dublin.

How can we help you make smarter decisions? Where do you struggle when it comes to web projects? What single bit of advice helped you most so far? What projects will you be starting this year?

Push for cheese
creative commons attribution/sharealike photo credit: Vidiot

Developing and releasing a product is hard. Effectively promoting it, even harder.

The Tuesday push is here to help. You are here to help.

Every second tuesday, a growing community within the irish tech scene coordinate an effort to promote and provide feedback for a particular product.

This week the push is on the tuesday push itself.

One measure of success, will be the size of the next one.

Take part next time. Follow @TuesdayPush on twitter and subscribe to www.tuesdaypush.com to keep in the loop. Put your product forward.

One snippet of feedback: with the aim of more people taking the time to contribute – warn us earlier about who will be pushed and when.

PS. The cheese is not free.

I’m looking forward to Future of Web Apps (FOWA) in Dublin on the 6th March and BizCamp Dublin (a user generated business conference) the day after.

I’m not the worlds most natural networker. Who is?

For fun, I created some business cards (using moo.com of course) specially for the two events. I’d love to chat about what YOU do. Please say hi and take one of these:

Carsonified always put on a good event. It’s great to have some local talent in the mix of superheroes that will speak.

Long URL Please started as a hobby project to learn a bit about app engine, and scratch an itch I have with short urls.

A few days ago I emailed the Ajaxian guys asking for help to promote it a little bit. Ben Galbraith emailed me earlier today saying he’d just posted on Ajaxian about longurlplease. I’m so chuffed to be mentioned on such a well known blog.

It was amazing to see first hand just how much footfall a site like Ajaxian can drive. Figures from my app engine dashboard indicate over 5000 hits on www.longurlplease.com and 1250 on the api in the last 16 hours. I suspect the number of uniques is quite a bit lower, but impressive nonetheless. I’ll post more usage information soon on the longurlplease blog.

Follow up posts by the Threat Chaos security blog, technologizer, a discussion on ycombinator hacker news, a mention on digg amongst others have helped spread the word even further. Thanks to Aidan Finn who posted about longurlplease last week – it helped encourage me to publicise the app further.

A massive thanks to all those who’ve tweeted about it – a subset of which are easily found at search.twitter.com/search?q=longurlplease and search.twitter.com/search?q=long+url+please. It’s overwhelming just how many people went as far as actually tweeting about it or following longurlplease updates. You rock!

Thanks to all those who’ve installed the firefox plugin, and those who’ve taken the time to give me feedback in the reviews.

Eagle eye attention to detail from Steve Quinlan and Jerry Kiely helped me quickly improve early versions of the app. I look forward to being able to return the favor.

I hope this is just the start of a long story for Long URL Please. Please get in touch if I can help you integrate the API with your website or application.

The last word goes out to AjaxianRespect!

content_for is the unsung hero of rails templating system! It allows you to define multiple placeholders in your layout from which you can render content from your views. It’s simple in both concept and implementation. It is the rails equivalent of tiles (for java) except it’s good!

If content_for is totally new to you, then get a quick overview in this railscast about rails layouts

Read the src: actionpack/lib/action_view/helpers/capture_helper.rb
def content_for(name, content = nil, &block)
  existing_content_for = instance_variable_get("@content_for_#{name}").to_s
  new_content_for      = existing_content_for + (block_given? ? capture(&block) : content)
  instance_variable_set("@content_for_#{name}", new_content_for)
  nil
end
Two things are interesting here:
  1. content is easily accessible via an instance variable
  2. consecutive calls result in content being concatenated, not overwritten.
Simplistically, rails layout looks like this:
<html>
  <body>
    <%= yield %>
    <div id="footer">
       <%= yield :footer %>
    </div>
  </body>
</html>

content in your view will be rendered where <%= yield %> is, except pieces within content_for which will be rendered by name within the layout. eg. :footer

Taking advantage of content_for concatenation

content_for concatenation helps you to easily render multiple items into the same piece of your layout.

My favorite use of this is for rendering javascript at the bottom of my pages. The aim is to include javascript as late as possible in your page (so that it doesn’t slow down page rendering on load).

In my layout, I have a <%= yield :js_footer %> just before the closing <body> tag. I use content_for :js_footer, often multiple times for one page, without worrying they’ll overwrite eachother.

The big win, is that it allows me to keep the js behhaviours right beside where the markup is defined in my partials, yet have it rendered at the bottom of the page.

Henrik Nyh points out that you can also make repeat calls to yield which is another handy trick to keep up your sleeve.

Taking advantage of the instance variable

Since I know that content_for :name will be captured into @content_for_name I can check if it’s been set in my layout, and act accordingly.

Say for example you’ve got a yield :gmaps_footer, you may attach an unload event to the body tag if gmaps is being used on the page

<body <%= 'onunload="GUnload()"' unless @content_for_gmaps_footer.blank?>...

With this small patch I proposed for rails it would become:

<body <%= 'onunload="GUnload()"' if content_for?(:gmaps_footer.blank)>...

Knowing exactly how content_for is implemented helped me improve the maintainability/readability of my view code. I hope it helps you too!

URL shorteners (tinyurl.com, bit.ly, is.gd, reallytinyurl.com etc.) take one URL and give you a shorter one that redirects to the original. eg.
http://maps.google.co.uk/maps?f=q&hl=en&
q=Upper+Fitzwilliam+St,+Dublin+2,+Republic+of+Ireland&
sll=53.800651,-4.064941&sspn=9.676196,28.564453&ie=UTF8&
cd=1&geocode=0,53.336060,-6.249863&z=16

shortens to

http://is.gd/4hlC

Incredibly useful, incredible usage (tinyurl.com gets over 1.5billion hits/month), but increasingly misused.

Only use when necessary.

  • Do use them in print – BUT only if the original URL is too long or too ugly to print (eg http://www.example.com/Something.aspx?_stupidParam1=stupidValue)
  • Do use them in email – BUT only if you are worried about the URL wrapping over lines.
  • Do use them when tweeting – BUT only if you can’t fit in the full URL. (unfortunately many twitter clients and perhaps twitter itself automatically shortens URLs, even when there’’s enough space)
  • Do use them in spoken word (eg podcasting) – BUT only if you’re linking to a very long, un googleable, or hard to spell URL. If you linking to mycoolnewwebsite.com then say that not is.gd/tkDn.
  • Do use them when IM’ing BUT only if you know you’re IM system mangles or doesn’t hyperlink them.
  • Don’t use them in blog comments.
  • Don’t use them on a website or blog post. (no excuses!!!)
  • Don’t link to a tinyurl without describing what you are linking to – it’s rude!

Why?

URL’s do so much more than locate resources.
  • They reinforce a brand (eg amazon.com).
  • They describe the resource they link to (eg. http://flickr.com/explore/interesting/24hours)
  • Users can distinguish sites they are familiar with vs those they aren’t.
  • Unless you’ve clicked the very same tinyurl before – they’ve no way to know if they’ve visited the site before – made worse by the ever growing number of shortener services.

When you send someone a URL or publish a URL somewhere – you are suggesting people visit it. By obscuring it behind a redirect – they’ve no way to know where they’ll end up. Curiosity will often click the link you’d otherwise ignore.

This isn’t as bad with people you know and trust, at worst just a waste of time. When dealing with untrustworthy or mischievous sources, beware, Rickrolling is one thing, more dangerous is the possibility of visiting a site that tries to exploit a security vulnerability in your browser.

Eye tracking studies (Microsoft Nielsen) of search engine use measured 24% of time was spent gazing at URLs. This emphasizes the importance of a URL, and the information and significance it carries, all lost when a shortener is used.

We’ve launched twitsnear.me. It shows what people nearby are saying on twitter.

Away From Home? Find new twitter buddies wherever you are. Bored at work? Make new friends and go meet them for coffee.

Dip in to local conversations without following the world

I hope you like it! I’d love your feedback.

I’ll often clone the db from production to staging to reproduce bugs or performance issues. The staging site is not visible to the public, so emails with links to it will confuse/annoy people. Today I accidentally sent emails to people from our staging setup.

To stop this happening again – I’ve a quick monkeypatch to only send emails to recipients in our domain. I placed this in config/environments/staging.rb.

class ActionMailer::Base
  def perform_deliveries
    @mail.header['to'].to_s =~ /@example.com$/
  end
end

Replace example.com with your particular domain

Downloadmusic.ie helps Irish independent/unsigned musicians to sell their music online and over SMS, get paid, and get chart hits. Johnny Beirne and Gareth McDaid are the people behind it. This week they’re getting the push they deserve, Tuesday style!

11 out of 10 for heart!, plenty of room for polish.

SMS ‘Music 1053’ to 57501 is all it takes for a supporter at a gig, to download a DRM free copy of a song, the artist to get paid, and be tracked as a purchase on the Irish charts. That’s neat. Making it really easy for bands to start doing what most of them are really bad at (Selling).

The Gig Guide Feed helps keep people up to date on who’s playing, where and when. (Helping Bands promote).

Their facebook app and an iGoogle widget (requires login) – giving you, amongst other things, gig listings, news and unlimited listening access to Irish indie music.

It would have been nice to see downloadmusic.ie shortlisted for this years Irish Web Awards. They’re no where near the peak of their ambition or capability, when they are, getting shortlisted will be just a formality.

I want to automate editing crontabs. I often create or edit identical cron entries on different projects or machines, so automating this will save me time.

Quick overview of cron – the manual way

Each line in your crontab is a command to run and configuration for when to run it. Example: the following will clear the apache error log at one minute past midnight each day.
01 00 * * * echo "" > /www/apache/logs/error_log
A common gotcha with cron is that it doesn’t share the same environment as you do when running your shell – in particular the PATH may be different and commands available to you in your shell may be missing on cron’s default PATH. To help with this, cron allows you to add lines to set environment variables. eg.
PATH=/usr/bin:/usr/local/bin

crontab -l outputs the current users cron entries

crontab -e opens the current users crontab for edit (configure editor with EDITOR environment variable)

Add -u user to your crontab commands to avoid accidentally installing as root for example. (eg crontab -u app_user -e)

crontab - allows us to pipe content into the current users crontab, which is allows us to run commands like this, to manipulate crontab using sed.
crontab -l | sed s/PATH=.*/PATH=\\/new\\/vvvpath/ | crontab -

Introducing cronedit

cronedit is a small ruby library that allows us to manipulate crontab using ruby.

gem install cronedit
Here’s a quick taste of what you can do.
cm = CronEdit::Crontab.new 'app_user'
cm.add 'job1', "5,35 0-23/2 * * * echo 'hello world'" 
cm.add 'job2', {:minute=>5, :command=>'echo 42'}
cm.remove 'job3'
cm.commit

Add jobs, either using familiar standard crontab syntax, or using a ruby hash, perhaps easier to read. An interesting thing to note is how it adds labels to your tasks, using comments in crontab. This is used to identify jobs for removal/replacement.

##__job1__
5,35 0-23/2 * * * echo 'hello world'
One shortcoming of cronedit is that it doesn’t provide a mechanism for adding environment variables (eg. PATH). So either take the hit, and add PATH manually, or take another approach, perhaps something like:
current = %x(crontab -l -u app_user)    
%x(echo "PATH=/usr/bin:/usr/local/bin\n#{cron}" | crontab -)

or more robustly – check first whether it is there already.

def update_cron_environment(user, key,value)
  cron = %x(crontab -l -u #{user})
  pattern = Regexp.new("^#{key}.*")
  if cron =~ pattern
    cron.gsub!(pattern, "#{key}=#{value}" 
  else
   cron = "#{key}=#{value}\n#{cron}" 
  %x(echo "#{cron}" | crontab -)
end

This gives a toolbox to automate editing my crontabs. But what about….

Something Simpler

I’m deploying a rails application, it’s running as a user, used for no other purposes. This works for me.

Keep a file in source control with the app, and on deploy overwrite the current crontab, with the latest version, included with the app. With a crontab file in RAILS_ROOT/config/crontab.txt we can add a simple capistrano task to update the crontab on every deploy.

namespace :cron do
  task :update do
    run "cat #{release_path}/config/crontab.txt | crontab -" 
  end
end
after "deploy:symlink", "cron:update"

If you really can’t stand the crontab syntax, you could combine use this approach, in combination with crondle, a dsl for cron.

Put overly tight trousers on someone with a belly and you get Muffin Top. Put vertical scrollbars on some (but not all) pages of a website – you get a similar effect.

Image courtesy of National Cancer Institute

Some browsers hide the vertical scrollbar when a page isn’t longer than the screen. When you move between tall and short pages the page moves position underneath your mouse – links you may have been hovering on, (or avoiding) are now shifted sideways by about 10 pixels. Your eye has to follow – curves follow easier than foldovers.

A simple bit of CSS will trick some browsers to show a scrollbar all of the time.

html {
  height:100%;
  margin-bottom:1px;
}

As a follow up to my post about converting a date to words like 5 hours ago, using javascript.

Here’s how you can use it.

Markup your dates something like this.

<span class="gmttime" title="Aug, 29 2008 22:44:41 GMT">29th Aug 2008</span>

Then at bottom of your document add this script

<script>TimeInWordsHelper.convertBySelector('.gmttime');</script>

and viola – your span will be converted to something like:

<span class="gmttime" title="29th Aug 2008">2 days ago</span>

Here’s an example, some tests and the source for you to reuse/fork

Some things to think about:

  • consider this as overkill/inappropriate – and just use plain dates! Less is more…
  • restrict how far in the past you convert dates. 2 minutes ago is useful, perhaps when it’s months ago, knowing the specific date is more valuable.
  • convert the date in a different way, eg 99designs – 5 days, 4 hours
  • use a PeriodicalExecutor to re refresh the dates, useful on an interface that keeps user on the same view for a long time.
  • when dates are converted they will take up a different amount of space on the screen – avoid your layout changing drastically by careful use of css.
  • avoid flickering as dates get converted, perhaps keep them hidden until converted, or use effects to make a smoother transition

via Google Code Bloggoogle.loader.ClientLocation tells you the city, country, region, longitude and latitude based on the IP address of the client.

The gist is:

curl -i -s http://www.google.com/jsapi | grep ClientLocation

google.loader.ClientLocation = {"latitude":53.333,"longitude":-6.249,"address":
  {"city":"Dublin","region":"Dublin City","country":"Ireland","country_code":"IE"}};

Use http://www.google.com/jsapi and you get location information for free.

Nice!.

The default error pages with a rails app are quite ugly.

It’s nice to have your error pages use the same layout as your app. It’s a good idea to have them as static files – in case your app is catastrophically hosed. But it’s also nice to use your app layouts, so that you’re not manually editing your error pages.

I pretty much followed this guys approach using rake to pre-generate the pages. I made small changes so that the task works without work without having to change routes or add a controller to my app.

task :generate_static_pages => :environment do
  class PreGenerateController < ApplicationController
    def show
      render :action => params[:id]
    end
  end
  require 'action_controller/integration'
  ActionController::Routing::Routes.add_route 'pre_generate/:id', 
                                 :controller => 'pre_generate', :action => 'show'
  app = ActionController::Integration::Session.new
  ['404', '500'].each do |action|
    app.get "/pre_generate/#{action}" 
    File.open("public/#{action}.html", "w") { |f| f.write app.response.body }
  end
end

and I added this to my cap deploy.rb

namespace :deploy do
  task :generate_static_pages do
    invoke_command "cd #{release_path} && rake generate_static_pages RAILS_ENV=#{rails_env}" 
  end
end

after "deploy:finalize_update", "deploy:generate_static_pages" 

Using rails integration testing library does seem like the most convenient, in this way I can generate the page without starting http server.