My Octopress Blog

A blogging framework for hackers.

Using Ruby to Cleanup

I had a problem with editors on one of my sites not conforming to the standards for url path formatting (all lowercase alphanumeric, hyphen instead of spaces) so I added a little validation to the page model:

validates_format_of :slug,
    :with => /\A[a-z0-9\-]+\Z/,
    :message => 'can only contain lowercase letters, numbers and hyphens'

Now, I had to update all of the pages that had been written to fit the new standard, but the real problem was updating inter-page links that had already been written. Luckily, script console came to the rescue:

Page.find(:all).each { |p|
  p.update_attribute(:slug,p.slug.downcase.gsub('_','-'))
};nil

Page.find(:all).each do |p|
  p.update_attribute(:body,
    p.body.gsub(/\/c\/([a-z0-9\_\-]+)/i) { |m|
      "/c/#{m.downcase.gsub('_','-')}"
    }
  )
};nil

I love Ruby. This would have been a pain in the ass in any other language.

Feeding the Homeless

This guy pretends to be a cop and gets some shop to take food to a couple of homeless “undercover agents” (via himshims)

Up and Be Doing, and Doing to the Purpose

If time be of all things the most precious, wasting time must be the greatest prodigality, since lost time is never found again; and what we call time-enough, always proves little enough: Let us then up and be doing, and doing to the purpose;
—Poor Richard, 1758

Serialized Multiple Select in Rails

In the current app i’m working on, I wanted to store multiple values in a single column. I know, violation of the first normal form.. blah blah blah. Save it.

Anyway, I wanted to have a multiple select box that would easily allow me to Manage and update the attributes of the model. Here is my solution.

Create the database table

create_table :tshirt, :force => true do |t|
  t.column :available_colors, :string
  t.column :available_sizes, :string
end

Create the Model

class Tshirt < ActiveRecord::Base
  serialize :available_colors, Array
  serialize :available_sizes, Array
end

Create the YAML Options Hash

I use an options.yml file in the config directory to setup the options for the object. A containing hash is created using the name of the object, and then the sub-hashes match the name of the column.

./config/options.yml

tshirt:
  available_colors:
    1: Red
    2: Blue
    3: Green
  available_sizes:
    1: Small
    2: Medium
    3: Large

Load the Options File into the App

In your environment.rb file you have to load the YAML parser and then parse the options.yml file:

require 'yaml'
OPTIONS = YAML::load(File.open("#{RAILS_ROOT}/config/options.yml"))

The Select Box

This is the hard part.

module ActionView
  module Helpers
    module FormOptionsHelper
      include ERB::Util

      def serialized_multiple_select(object, method, choices = {}, options = {}, html_options = {})
        html = []
        html << "<select id=\"#{object}_#{method}\" name=\"#{object}[#{method}]\" multiple=\"multiple\" size=\"5\">"
        html << options_for_select(OPTIONS[object].invert,self.instance_variable_get('@'+object).send(method).collect{|x| x.to_i })
        html << "</select>"
        return html
      end
    end
  end
end

Add the select box to your form

And this is the easy part:

<p>Colors: <%= serialized_multiple_select 'tshirt', 'available_colors' %></p>
<p>Sizes: <%= serialized_multiple_select 'tshirt', 'available_sizes' %></p>

I am pretty sure there are better way to do this, but this one worked for me.

Also, my serialized_multiple_select has options that it doesn’t even use. I should really use them. Please offer feedback if you have any. :)