Development Tools

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

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

PostgreSQL, MySQL and Ruby Drivers with MacPorts

If you’re on MacOS X and you’re developing database aware applications you certainly want to have installed locally one or both of those populars RDBMS : PostgreSQL or MySQL.

My prefered way of doing it is through MacPorts (previously known as DarwinPorts), a package manager designed initially for Darwin and now focusing on MacOS X.

I assume you already have installed MacPorts as explain on their website.

So let’s open a console with your favorite application (I tend to prefer iTerm over Terminal.app) and enter those commands :

sudo port install mysql5 +server

this will install MySQL 5.x database and the launchd script needed to start it (on-demand or at startup).
When the installation is done you’ll be asked to install the launchd script, just ignore this part and jump to the initialization part.

To initialize MySQL and secure access to it, just enter those commands

sudo -u mysql mysql_install_db5
sudo -u mysql /opt/local/lib/mysql5/bin/mysqld_safe &
/opt/local/lib/mysql5/bin/mysqladmin -u root password 'your_password'

You should now have a shinny new MySQL 5 installation with a password for your root account.

Then PostgreSQL, let’s type in :

sudo port install postgresql81-server

this will install PostgreSQL 8.1.x database and its launchd script.
When the installation is done, as with MySQL skip the launchd part and go to the initialization by issuing those commands :

sudo mkdir -p /opt/local/var/db/postgresql81/defaultdb
sudo chown postgres81:postgres /opt/local/var/db/postgresql81/defaultdb
sudo su postgres81 -c '/opt/local/lib/postgresql81/bin/initdb -D /opt/local/var/db/postgresql81/defaultdb'

PostgreSQL access authorization is something beyond this article, so I’ll don’t cover it.

If all goes well you should now have 2 working installations, but no simple way to start/stop them. A simple and powerful way of handling this (and launchd scripts, create/edit/load/unload) is Lingon. Just download the last version and go to the “Users Daemons” tab and you will see your two launchd scripts are there waiting for you to load/unload/enable/disable them.

To finish this installation, if you’re a Ruby kind of guy you probably want to access those databases from it. There are two ways to install the needed libraries : MacPorts or RubyGems.

For MySQL, there is no problem with MacPorts just type :

sudo port install rb-mysql

If you prefer the RubyGems solution the command is little more tricky :

sudo gem install mysql -- --with-mysql-config=/opt/local/bin/mysql_config5

[Update]
For MacOS X.5 (Leopard) stock Ruby 1.8.6 :

sudo env ARCHFLAGS="-arch i386" gem install mysql -- --with-mysql-config=/opt/local/bin/mysql_config5

For PostgreSQL, you can’t do it through MacPorts unless you choose to install postgresql8 (and not postgresql81), because of the dependencies. But you can install the library through RubyGems with :

 sudo gem install postgres -- --with-pgsql-include-dir=/opt/local/include/postgresql81/ --with-pgsql-lib-dir=/opt/local/lib/postgresql81/ 

[Update]
For MacOS X.5 (Leopard) stock Ruby 1.8.6 :

 sudo env ARCHFLAGS="-arch i386" gem install postgres -- --with-pgsql-include=/opt/local/include/postgresql81/ --with-pgsql-lib=/opt/local/lib/postgresql81/ 

This is a simple and yet functional setup to work.

Published on Sun, 19 Nov 2006 13:06

Subversion Automation : automate branching/tagging

I recently discovered a gem (no joke here) called Subversion Automation, it’s aimed to provide an unified layout to handle your projects branching/tagging in subversion and more importantly automate the process through a simple command : sc .

It currently handle some key aspects of a project management :

  • release :
Allows you to create a release branch (major.minor), or tag a release (macro). It creates a branch for the release and a tag for it.
  • bug
Allows you to work with release branch bug fixes, in fact it handle the creation of a unique branch based on a bug name/id and then the merge to the corresponding release branche and to the trunk. Really useful to track bug fix changes.
  • experimental
Allows you to work on some experimental code in a branch wich can be merge with the trunk in both direction.

Subversion Automation is really worth a try, even if it could be hard to use on existing project due to the subversion layout changes implied, but it’s up to you.

Be sure to watch the marvelous screencast on author website : Subversion Automation Screencast

Published on Wed, 15 Nov 2006 11:37

Introduction to distributed Version Control System with SVK

VCS such as Subversion or CVS are great but they have a major drawback : when working offline and your server is online, you can’t version your changes until you reach an internet access point.

Here’s where SVK come to your rescue, it’s a distributed (or decentralized as stated on its website) version control system. It works with a under-layer subversion filesystem improved with some useful features, but the interesting part is its ability to play with other VCSs (Subversion, Perforce and CVS) by mirroring them locally and letting you do offline operations on them. Those changes you’ll merge back to remote server when you gain access to an internet connection, but enough with meetings, let’s go to work !

First you need to have a working installation of svk, but I don’t cover this part as it’s specific to each OS, just point you favorite browser to SVK Installation Page and follow the steps corresponding to your environment.

Choose your local layout :

Once you’re done with the installation part, you should start by creating a local svk repository. You have two choices :

  1. A single default repository
  2. Multiple named repository

I choose to go with the first choice, it’s enough hassle to play with multiple remote repositories without having to suffer the pain of searching to which local repository your remote repository belongs. But feel free to choose your way.

Initialize local repository :

svk depotmap --init

This will create the default repository in ~/.svk/local.

As I choose to go with the default repository, it has no explicit name, this assumption will make sense later.

Create an initial layout :

This step is not mandatory, but as I like to keep things as clean as possible, we will create some directories in the default svk repository.

svk mkdir //mirrors -m 'Creating directory for mirrored projects trees'

This line will create a directory called mirrors in root of default svk repository where we’ll put mirrored remote projects trees. Here’s where the no explicit name assumption come to play : the root of default svk repository is access using //, if we had chosen to go with multiple named repository, it’d be /repository_name/.

svk mkdir //local -m 'Create directory for local projects changes'

Let’s create another directory, this time to store local changes, be it local branches of some mirrored projects or simply local projects you want to put under version control.

Mirror your first remote project :

I’ll use a remote subversion repository accessible through Apache’s mod_dav_svn module, but SVK works well with others svn access schemes svn:// or svn+ssh://, without mentioning perforce and cvs.

svk mirror http://projects.tron.name/svn/blogmarks/trunk //mirrors/blogmarks -m 'mirror of blogmarks trunk repository'

This line will instruct SVK it has to handle a mirror of the remote repository at http://projects.tron.name/svn/blogmarks/trunk in the //mirrors/blogmarks local repository.

Then to checkout the entire tree of the mirrored project in local repository :

svk sync -all

or

svk sync //mirrors/blogmarks

The last commands start a synchronization between all mirrored remote repository (--all) or a specific one only (//mirrors/blogmarks) and the local repository.
Wait for svk to be done and you’ll have a copy of the remote tree in your local machine.

Make a branch for local work

This part is especially useful for mirrored repositories where you don’t have commit rights, but it’s a good habit for repositories where you have rights access too.

svk cp //mirrors/blogmarks //local/blogmarks -m 'create a local dev branch'

Now your repository would looks like :


/
|-/mirrors/blogmarks
|-/local/blogmarks

Checkout a copy :

Now we’re able to checkout a copy of the new branch to handle our development.

svk co //local/blogmarks BlogMarks

This give us a BlogMarks directory in the current folder which is a working-copy of //local/blogmarks

Now let’s hack your code !!

Commit modifications :

When you’ve implemented you’re next killer feature and want to track the modifications to go on with the next one, in the working-copy directory, issue a :

svk ci -m 'Implements a killer feature'

Merge your changes back to the main remote repository :

If you have write access to the repository, you’ll surely want to send your modifications to the remote server when you gain access to internet. This is another great added feature of SVK.
First be sure to have the latest version for your mirrored project :

svk sync -all

or

svk sync //mirrors/blogmarks/

Then issue a smerge :

svk smerge -Il //local/blogmarks/ //mirrors/blogmarks

... Follow direction provided on screen by svk ...

Options -Il ensure each modifications you did will be committed individually to the repository (I) using commit log provided when committing to svk (l).

Generate a patch :

In case you don’t have write access to remote repository, perhaps do you want to send developers a patch with your modifications. SVK to the rescue(be sure to re-sync your mirrored repository before generating the patch).

As always there a numerous ways to do that, but I found the Scott Laird ‘s way is really clean, so we’ll go with that.

Create a new directory to handle patch-set :

svk mdir //patchsets

Then copy your project trunk (or branch) :

svk cp //mirrors/blogmarks //patchsets/blogmarks-withkillerfeature

Now merge your change to the patch-set, let’s assume we had changes about our killer feature in changeset 110, 119 and 120 :

svk merge -l -c 110 //local/blogmarks //patchsets/blogmarks-withkillerfeature
svk merge -l -c 119 //local/blogmarks //patchsets/blogmarks-withkillerfeature
svk merge -l -c 120 //local/blogmarks //patchsets/blogmarks-withkillerfeature

Then generate the patch :

svk diff //mirrors/blogmarks/ //patchsets/blogmarks-withkillerfeature

Here it is, a shiny patch ready to be send to developers with write access.

Here it is for this introduction.

Published on Sat, 04 Mar 2006 16:00

RSS