Search

Chaps

Sweet sweet memories

Blather

Uptime verified by Wormly.com

27 May 2008

European Dates in Ruby on Rails

I found a solution to the problem of month/day ordering by overriding the autocasting code in ActiveRecord. However, that didn't solve the problem more generally. So I came up with a nicer solution that uses the existing Date::Format._parse_sla_eu method. It replaces the US year/month/day parsing method with the European one.

# Overrides the default Date::_parse() method for dates of format dd/mm/yyyy
# ParseDate does the typical American thing and assumes mm/dd/yyy and
# doesn't seem to be configurable

module Date::Format::EuropeanDates
  def self.included(base)
    base.class_eval do
      class << self
        alias_method :_parse_sla_us, :_parse_sla_eu
      end
    end
  end
end

Date.send(:include, Date::Format::EuropeanDates)

With thanks to Simon who showed me how to replace static methods. This is the kind of wacky stuff you could never do with PHP. Not that we should want to. It's kind of ridiculous.

13 May 2008

Rails autocasting date strings with wrong day month order

Update: I found a better solution that changes the date parsing code instead.

# Overrides the default AR date casting for dates of format dd/mm/yyyy
module ActiveRecord
  module ConnectionAdapters #:nodoc:
    class Column
      def self.fallback_string_to_date(string)
        string.gsub!(/([0-9]{2})\/([0-9]{2})\/([0-9]{4})/, '\3-\2-\1') # Convert to unambiguous date
        new_date *ParseDate.parsedate(string)[0..2]
      end
    end
  end
end

Rails ActiveRecord (or ParseDate at least) assumes that date strings with forward slashes are always in the form mm/dd/yyyy. That's all very well for silly countries like America, but not for a lot of the rest of the world.

This is my fairly shite attempt to transparently solve this problem. If you put this code in lib/autocast_date.rb for instance you can go require 'autocast_date' at the top of any model that needs it.

This will obviously break support for American style dates.

Changing human attribute labels in Rails validation messages

I've been frustrated by the lack of humanity in Rails so-called human names. So I wrote a little library, which was largely stolen from Change displayed column name in Rails validation messages. The library lets you do something a little like this...

require 'human_attributes'

class Puppy < ActiveRecord::Base
  humanize_attributes :breakfast => "Puppy's preferred breakfast"
  validates_presence_of :breakfast
end

It doesn't do anything very spectacular, but it took me a long time to work out.

# lib/human_attributes.rb

module ActiveRecord
  class Base
    # Humanize attributes
    def self.human_attribute_name(attr)
      @humanized_attributes ||= {}
      @humanized_attributes[attr.to_sym] || attr.humanize
    end

    def self.humanize_attributes(*args)
      @humanized_attributes = *args
    end
  end
end

ActiveRecord::Base#humanattributename is deprecated and will be replaced by proper string inflection. For those with fancy, modern humanizing Inflectors you might have to change it to something like this.

def self.humanize_attributes(*args)
  humanized_attributes = *args
  Inflector.inflections do |inflect|
    humanized_attributes.each do |attr, label|
      inflect.human attr.to_s, label
    end
  end
end

Although I couldn't get that to work, probably because my Rails isn't new enough.

0.072 seconds