[Windows reminder] IE default editor

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\View Source Editor\Editor Name]

PS : I think this is the first post of a long list.

Published on Mon, 27 Aug 2007 11:03

Date, Time and old days

Not so long ago a bug emerged on my current application, a vicious one.
Let’s say you have a user and store its bithday date in database (say MySQL) as a DateTime (yep I know, it’s a little to precise for this kind of data).
Rails conveniently retrieve this field as a Time, but as you probably do not be aware of is the range limitation of Time’s dates. In fact the Time class is often used because it’s faster than Date or DateTime, but the tradeoff is it handle date based on epoch time (01-01-1970), where Date/DateTime use Complex class and as such can handle a broader range of date.

Well, my user’s birthday date was somewhere in 60s and so can’t be handle by a the Time class. But it’s not as simple, Rails fallback to DateTime if parsing MySQL datetime field does not work with Time.parse. This results in an object perfectly valid when using it, the problem arise when you try to update the corresponding record in database.

Remember my initial datetime field was fetched as a DateTime ruby object and as Rails include all fields from the record on update it tries to translate the birthday to something MySQL recognize. ActiveSupport include some convenients methods to do that : Time#to_s and Date#to_s takes a parameter allowing us to do something like Time.today.to_s(:db) as well as some convenient Date to Time conversion. Unfortunately, no out of range detection is done in Date#to_time which leads me to the first headache. Then ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS hash does not contains a :db key so calling Date#to_s(:db) results in an erroneous string for the db. (this is corrected in rails edge but not in 1.2-stable branch).

All in all :

  1. be aware of Time class limitation
  2. ruby open classes are wonderful : just drop this code in your lib directory and that should make it until rails is patched.
module ActiveSupport
  module CoreExtensions
    module Date
      module Conversions
        # Add db and rfc822 format
        DATE_FORMATS.merge!({
          :db       => "%Y-%m-%d %H:%M:%S",
          :rfc822   => "%a, %d %b %Y %H:%M:%S %z"
        })
      end
    end
  end
end 
Published on Thu, 23 Aug 2007 16:07

Ruby 1.8.6 and Date

If you have a localized application and use Gettext, you probably use some method to handle localized Date.
Mine was a widely used approach consisting of redefining various Date.rb constants (Date::ABBR_DAYNAMES, Date::MONTHNAMES, etc.) to use the Gettext Object#_() method.

Recently I was forced to use Windows™® as my primary work OS, so I installed latest Ruby One-Click Installer which comes with Ruby 1.8.6. (I’m running 1.8.5 on all other machines).

This is where I was bitten by the Ruby 1.8.6 Date change, all my lovely constants are now frozen and I can’t localized them anymore (at least so simply).

So stick with 1.8.5 as long as you don’t really need to upgrade, there are also some threads issues with this release… so you also have weird issues if you use backgroundrb.

Published on Wed, 01 Aug 2007 10:14

Graticule, Google and UTF8 are in a boat

I faced a problem recently using Graticule with Google geocoder api. Whenever I check for locations whose name contains accentuated chars (like “Orléans”), I was rewarded with a nice REXML exception telling me google xml was not correct (some tags ending missing).

After about an hour of fight with Graticule, then Open-URI, then Net::HTTP, then StringIO and finally google I discovered the problem : Google Geocoder API send xml response with iso-8859-1 unless you fake being…say “Mozilla/5.0”. No matter you specify Accept or Accept-Charset headers the only way to have the xml as utf8 is sending “User-Agent: Mozilla/5.0”.

In fact it works with different versions :“Mozilla/5.0”, “Mozilla 5.0”, “Mozilla 5.0 (give me utf8 please)”, etc.

So if you want to use Graticule to geolocalize locations with accentuated chars change in graticule’s “rest.rb” (around line 80) :

url.open do |response|

to

url.open('User-Agent' => 'Mozilla 5.0 (Some utf8 please)') do |response|

UPDATE :
Brandon Keepers tackles on this lightning fast and release Graticule 0.2.3, one bug down !!

Published on Fri, 27 Apr 2007 13:12

Gettext and Rails

I encountered some problems with gettext rails integration recently, so here they are with explanation and resolution (if I found it).

Localization of ActiveRecordHelper error messages :

I choose to change the error message as explained by the gettext tutorial :

in application.rb

ActionView::Helpers::ActiveRecordHelper::L10n.set_error_message_title(Nn_("An error is occured", "%{num} errors are occured"))  
ActionView::Helpers::ActiveRecordHelper::L10n.set_error_message_explanation(Nn_("The error is:", "The errors are:"))

this works great, the error message displayed by the helper is the good one… except it only appears in the base language (English in my case). And the text never appears in my .pot file. After some searches in the gettext files, I found the problem : the textdomain for the helper is ‘rails’, which is great because you got validations and errors localized by gettext team for free. But it means you can’t set your own message without modifying the rails.pot in gettext package, which is not a solution because you need to maintain your own gettext gem or apply modifications to all you servers installs, and no you can’t install gettext as a rails plugin as gettext gem compile a gettext.so|.dylib on install which depends of your system.

The solution ? I didn’t find any satisfying one, if you force the textdomain to your app’s one then you need to duplicate and update all the rails translations strings from gettext package.

Gettext#updatepo and models with observers :

One of gettext nifty feature is its ability to extract your model columns names for translation. But the implementation cause some trouble when you have declared some observers in your environment.rb.

To accomplish its tasks, gettext first load rails environment. Then each files are parsed by Gettext::ActiveRecordParser#parse where you have :

old_constants = Object.constants
begin
  eval(open(file).read, TOPLEVEL_BINDING)
rescue
  $stderr.puts _("Ignored '%{file}'. Solve dependencies first.") % {:file => file}
  $stderr.puts $! 
end
loaded_constants = Object.constants - old_constants

This code try to catch the constants the current file add to Object.constants and then parse them either as ruby or ActiveRecord subclass. But if you declared an observer in your environment.rb, the model and its observer is already in the Object.constants and are just ignored by the gettext active record parser.

Solution ? Comment the config.observers line in your environment.rb each time you need to run gettext:updatepo task, not really sexy but it works.

Published on Fri, 30 Mar 2007 10:49

RSpec On Rails and HAML

As my incursion into RSpec continue, I encountered a strange problem on my CC machine. I switched my default layout (aka application.rhtml) to HAML, so the file became application.haml. No problem on my development machine running specs either with spec command or with rake. But the CC machine start sending me error in my specs, telling me application.rhtml does not exists.

I searched some looooong minutes which stack generates this error, four possibilities : RoR, RSpec, Gettext, HAML plugin.

The last thing I did before the specs breaks was to switch a controller spec from view isolation to view integration. So I looked more closely to RSpec On Rails plugin and found something interesting, to run in isolation mode, RSpec on rails stub those methods :

@template.stub!(:file_exists?).and_return(true)
@template.should_receive(:render_template).any_number_of_times.and_return(true) { |*args|
  @first_render ||= args[2]
}
@template.stub!(:find_template_extension_for).and_return("rhtml")
@template.stub!(:read_template_file).and_return("this is fake content generated by rspec")

So it faint Rails about an existing application.rhtml which in fact does not. Rails in its great willingness cache the different template/template extension lookups even in test mode. Then when mixing view integration and view isolation in specs, if those with view integration run after those in isolation, it breaks… or it should, as I can’t reproduce this in my development machine nor can I reproduce this on my CC machine when launching the specs by hand with the spec command (it does occurs only with rake).

About the Rails choice to cache, I fully understand why it is as it is, there should be no template rename during test as it is possible in development mode. So it’s not Rails fault.

But what can we do about this, the simplest solution I came to was to set the template extension caching to off in config/environments/test.rb :

config.action_view.cache_template_extensions         = false

Hope this helps someone else using RSpecOnRails with a custom template system.

[Update]
The difference between my two machine was revealed to me in just after I post this. The rake task on the CC machine, does not sort the controller spec files as my development machine, the problematic file is called addresses_controller_spec.rb so it was the first one evaluate in my development machine and is drowned between others in my CC machine.

Published on Sat, 24 Feb 2007 13:21

How to use a custom RDoc template from a rake task

I just need to do that, use a custom rdoc template to generate a documentation for a Rails project.

My main concern, regarding the different solutions I found on the web, was I didn’t want to have a template in the ruby installation directory but one that resides in a subdirectory of my rails application.

In fact it’s not a problem … when you find the good command. Here’s my rake task to generate the documentation (I put the Jamis Buck customized template in RAILS_ROOT/doc/rdoc_template/jamis.rb)

namespace :doc do 
  desc "Generate documentation for the application"
  Rake::RDocTask.new("app_jamis") { |rdoc|
    rdoc.rdoc_dir = 'doc/app_jamis'
    rdoc.title    = "My Website Documentation"
    rdoc.template = "doc/rdoc_template/jamis.rb"
    rdoc.options << '--line-numbers' << '--inline-source'
    rdoc.rdoc_files.include('doc/README_FOR_APP')
    rdoc.rdoc_files.include('app/**/*.rb')
    rdoc.rdoc_files.include('lib/**/*.rb')
  }
end

The important part is :

rdoc.template = "doc/rdoc_template/jamis.rb"

I tried to use the —template= and -T options in rdoc.options but it didn’t work… then I found that the RDocTask appends its template variable to the options passed to RDoc bypassing mine.

Published on Thu, 15 Feb 2007 13:35

FUSE and SSHFS for MacOS X

FUSE is a library initially developed for Linux then ported to FreeBSD and now on MacOS X, allowing implementation of a filesystem in a userspace program.

There are already numerous implementations going on from nfs to bittorent filesystem (see Filesystems on Fuse Wiki).

Yesterday, google employee Amit Singh announced the release of a MacFuse version including, amongst other things, a Virtual file system kernel extension and a patch to sshfs.

So, we now have all elements needed to use sshfs on MacOS X, YEAHH !!!
But wait… what can we do with sshfs ?

The big things about sshfs is it allows you to mount on your local machine a remote directory through ssh. On Mac it means you see the remote directory as an external mount point (on your desktop for example, just like an external hard drive).

Currently (at least on my configuration) the finder does not allow to copy file to the mounted filesystem as it does not recognize correctly the available free space, but it works beautifully with other apps (text editor, etc.) or in the console.

Installation is a little bit fastidious for now, but if you follow carefully the MacFuse installation How-To it should not be infeasible.

When installation is complete, just got to you console and type :

mkdir /Users/yourusername/Desktop/RemoteFS
sshfs remote_username@remotehost:/your/remote/directory /Users/yourusername/Desktop/RemoteFS

This mount the /your/remote/directory on your Desktop as RemoteFS.

To unmount it just use :

umount /Users/yourusername/Desktop/RemoteFS
Published on Fri, 12 Jan 2007 12:04

RSpec on Rails : RESTful Authentication

For a new Rail project I’m working on, I decided to try to use RSpec.

The main problem I see with this solution is that not so many plugins out there have RSpec tests and so it can be boring to have to run autotest and rspec_autotest in parralel to be sure both RSpec and Test::Unit tests passes.

Helped by a recent post of Yurii Rashkovskii : RSpec on Rails: acts_as_authenticated , I adapted and add a few specifications to be compatible with restful_authentication plugin.

Here are the files :

Just put those in spec/{models,controllers}, copy users.yml fixtures from test/fixtures to spec/fixtures/ and you’re done.

Note I did not spec the UserObserver for now.

[Update]

I refactored a little bit my previous files, add some specs and try to spec user_notifier and user_observer models as well.

You should also add :

def set_mailer_in_test
 ActionMailer::Base.delivery_method = :test
 ActionMailer::Base.perform_deliveries = true
 ActionMailer::Base.deliveries = []
end

to Spec::Rails::EvalContext class in your spec_helper.rb.

I’m waiting for your comments on notifier/observer specs, I didn’t see any examples of them in rspec and I’m not sure of the best way to spec them. For example, UserNotifier is an ActionMailer and resides in models directory, but it acts more like a controller (render views), well you see the point.

[Update]

For those of you who switch to RSpec 1.0.x, Jonathan Linowes has updated my files to make them compatible with the new syntax (thanks). You can grab them at : Rspec 1.0 and Restful Authentication

Published on Tue, 02 Jan 2007 14:27

Installing PostGIS 1.2.0 with MacPorts PostgreSQL 8.1

In the previous post I detailed how to install PostgreSQL with MacPorts. This time we will see how to get the latest PostGIS (version 1.2.0 as of this writing) installed.

MacPorts provide PostGIS 1.1.1 but it depends on postgresql8 and we decided to go for the postgresql81 version last time. So we’ll have some handwork to get all run together.

First install proj and geos from MacPorts

sudo port install proj
sudo port install geos

then download, extract, compile and install PostGIS 1.2.0 :

curl -O http://postgis.refractions.net/download/postgis-1.2.0.tar.gz
tar xvzf postgis-1.2.0.tar.gz
cd postgis-1.2.0
./configure --libdir=/opt/local/lib/postgresql81/ --datadir=/opt/local/share/postgis --with-pgsql=/opt/local/lib/postgresql81/bin/pg_config --with-geos=/opt/local/bin/geos-config --with-prog=/opt/local/
make
sudo make install

Here we are, PostGIS 1.2.0 installed on a PostgreSQL 8.1.

Now every time you need to use PostGIS functions you need to configure your database (every new database need an “enabling phase”. You can use a template, but I will not cover this part) as follow :

createlang plpgsql yourdatabase
psql -f /opt/local/share/postgis/lwpostgis.sql -d your_database
psql -f /opt/local/share/postgis/spatial_ref_sys.sql -d your_database

[Update (04/01/2008) : Add missing /share/ in paths. thanks Galen]

If you already had an old version of PostGIS installed and want to upgrade your databases, follow the “UPGRADING EXISTING SPATIAL DATABASES” parts of PostGIS README.postgis.

Published on Wed, 20 Dec 2006 12:47

RSS