Peter Harkins's blog

Add Feed Discovery Links Easily

I'm working on discussion forums for NearbyGamers and I'm building the first feeds into the site. I worked up a clean way to add them from my controllers similar to my tidy stylesheets code. Here's how to do it.

In the <head> of your app/views/layouts/application.rhtml call the auto_discovery_link_tag to print the tags:

  <%- @feeds.each do |feed| -%>
    <%= auto_discovery_link_tag(:atom, *feed) %>
  <%- end -%>

In app/controllers/application.rb:

  def initialize
    @feeds = []
  end

  def add_feed title, options={}
    @feeds << [ { 
      :controller => self.controller_name, 
      :action => self.action_name, 
      :format => 'atom' 
    }.update(options), { :title => title } ] 
  end

And you're all set up. Where you want an action to present feeds, call add_feed. After title, it takes options for url construction.

Rails 1.2.1 Impression

I'm updating NearbyGamers to Rails 1.2.1. Nothing broke except my use of assert_tag in my tests; it's been long-regarded as squicky and has been replaced with assert_select. As I'm tidying up some deprecated code, it occurs to me that this makes for an interesting example of how I feel Rails is changing.

Rails is growing inwards and upwards, not just outwards. They're finding better, terser, more Rails-ish ways to express things. They're not piling on features, they're condensing. I've mentioned that this is what coding in Rails continually feels like: sometimes it just feels off even though it works and is nicer than other languages, and soon I realize a beautiful Right Way to do it.

Where Rails gained new features, the developers have redesigned functionality to make me think, "Wow, of course, that's obviously much nicer" and it does more because it's better-designed. Let me give you an example using assert_tag.

Barking Stapler

Barking Stapler logo
I've left Cambrian House to work full-time on my own company, Barking Stapler.

Over the next few months, I'm going to grow NearbyGamers into a business that can support me. Yes, I know it's not a pretty site. The graphic designer who did the Barking Stapler site, Gilles Maes, is now working on a facelift while I work on adding a great many features.

I expect entrepreneurship is going to be quite a ride, so I expect to start writing about it in addition to my usual technical posts. As usual, let me know if there's any topics you'd like me to cover.

GET and POST variable hashes in Ruby on Rails

In Rails, you access GET, POST, and routing variables through the params hash. This works almost all the time, except when you duplicate a variable name: routing overwrites GET overwrites POST.

For an app I'm working on I actually had to care where a variable comes from, so I dug for a while to find out how to access the raw hashes. It ain't pretty, but here it is in case anyone else ends up needing it:

get = CGIMethods.parse_query_paremeters(@request.query_string)
post = CGIMethods.parse_query_parameters(@request.raw_post) 
# you'd think you could use @request.query_parameters and
# @request.request_parameters, but they're update()d by route vars
route = @request.path_parameters

(Also, don't ask about this in #rubyonrails -- you'll just get lectured on how you don't really want to access the hashes, how you should rename all your variables and URLs, and how it simply isn't possible. This will be very frustrating and totally unproductive.)

Rails Makes Valid XHTML Easier

I'm working on a Rails site in my Copious Free Time and I wanted to share a little way that Ruby made my life easier. I'm making my pages valid XHTML 1.0 Transitional because it makes life easier to find bugs and it just feels good to know I'm meeting the spec.

The W3C Validator complained that I didn't have the rows and cols attributes on my <textarea> tags. My code for them looked like:

<%= text_area_tag :message, params[:message] %>

And I don't want to add the :size option because I use CSS to style all of them, it'd be confusing to see an unused size there. So I extended the text_area_tag method in my app/helpers/application_helper.rb to fill in a default:

module ApplicationHelper
  def text_area_tag(name, content=nil, options={})
    super(name, content, { :size => "40x10" }.update(options))

Tidy Stylesheets in Rails

It's very easy for a site's CSS to grow a single giant, brittle stylesheet. It becomes impossible to change anything because of bizarre interactions between elements, unexpected interactions, and simply because it's just too big for anyone to understand. Much of programming is managing complexity, and I'll share a nice technique in that vein.

I like to break down stylesheets so there's a site-wide stylesheet with global stylings like fonts, the site's template, and common elements. This is the file that metastasizes on you.

My solution is to break down stylesheets by controller and action, and Rails makes this quite easy:

# app/views/layout/application.rb
<%= stylesheet_link_tag *(['global'] + @stylesheets) %>
# app/controllers/application.rb
class ApplicationController < ActionController::Base
  before_filter :add_stylesheets

  def initialize
    @stylesheets = []
  end

  def add_stylesheets
    ["#{controller_name}/_controller", "#{controller_name}/#{action_name}"].each do |stylesheet|

Programming Is Like Sex

because...

  • One mistake and you have to support it for the rest of your life. (Michael Sinz)
  • Once you get started, you'll only stop because you're exhausted.
  • It often takes another experienced person to really appreciate what you're doing.
  • Conversely, there's some odd people who pride themselves on their lack of experience.
  • You can do it for money or for fun.
  • If you spend more time doing it than watching TV, people think you're some kind of freak.
  • It's not really an appropriate topic for dinner conversation.
  • There's not enough taught about it in public school.
  • It doesn't make any sense at all if you try to explain it in strictly clinical terms.
  • Some people are just naturally good.
  • But some people will never realize how bad they are, and you're wasting your time trying to tell them.
  • There are a few weirdos with bizarre practices nobody really is
    comfortable with.

Flintstoning Toasters

Flintstones Record Player
I picked up the term "flintstoning" from my visit to Cambrian House. It's the practice of substituting a little human work for functionality until there's enough demand for the feature that it's worth the coder time to implement. Let me give you an example.

You're a web coder for a bank whose promotion this month is a free toaster to everyone who deposits $10,000 to open a new account. The bank realizes that toaster manufacture and delivery is not their core competency, so they outsouce the task the lowest-bidding toaster fufillment processing agency. Your job is to write the code to get toasters to web customers. You have two options:

  • Spend painful hours attempting to reconcile the inconsistencies between the toaster pimp's documentation and their Java-powered full-stack WSDL automated toaster delivery processing gateway until XML angle brackets gouge your eyes out.
  • Building Clean URLs Into a Site

    I wrote about building a site with clean URLs, but that's useless to you. No, you've got a creaking hulking monster of a site that coughs up URLs like "render.php?action=list_mailbox&id=42189", was built "to meet an accelerated schedule", and eats summer interns whole.

    This article tells you how to put clean and human-usable URLs on top of the site without even editing your underlying scripts. All these examples mention PHP but it doesn't matter what you coded the site in, you just have to be running Apache and have a little familiarity with regular expressions.

    So we have two goals. First, requests for the new URL are internally rewritten to call the existing scripts without users ever knowing they exist. Second, requests for the old URLs get a 301 redirect to the new URLs so that search engines and good bookmarks immediately switch to the new URLs.

    Let's work through an example .htaccess file. We take apart the new URLs and map them internally to the old URLs:

    Building a Site With Clean URLs

    As an aside in my post about Cambrian House I posted some code for making pretty URLs. A few people (no, not CH) have asked for a little more info, so I've written up an explanation of that code.

    PHP makes it very easy to create bad URLs like /member.php?id=8. Those are bad because web spiders don't like to crawl URLs with GET variables, some browsers don't cache any GET URLs, they expose that you use PHP (when the visitor should never even know), and they're just downright ugly and hard to remember. I'm going to present a way to build a PHP/Apache site with clean URLs.

    Let's look, line-by-line, at the contents of .htaccess. While writing this article I found a more elegant equivalent in the Wordpress code, so I'll present that here:

    # Tell Apache to load mod_rewrite.
    RewriteEngine On
    # Rewrite URLs for the location starting at /
    # Note this is URL location, not a path to your web root.
    RewriteBase /