RubyOnRails

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

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

Capistrano tips

If you use (and you definitely should) Capistrano to handle your Rails application deployement, you should have faced some troubles to handle passwords for svn + database, at least if you’re like me and don’t want to put those production passwords in your subversion repository.

My first concern was to have a different user/password to checkout code from subversion, ssh to the server and connect to the database.

So here’s some tricks which allows you to avoid puting passwords in subversion and use different passwords for each part of the process (ssh, svn, db), put those in your config/deploy.rb.

Use whatever SVN User/Password you want :

[UPDATE] A little update to this part to avoid remote svn user/password to be cached locally.

Old :

 set :svn_user, ENV['svn_user'] || "jonathan"
 set :svn_password, Proc.new { Capistrano::CLI.password_prompt('SVN Password: ') }
 set :repository,
  Proc.new { "--username #{svn_user} " +
             "--password #{svn_password} " +
             "http://your.domain.tld/path/to/svn/#{application}/trunk/" }

New :

 set :svn_user, ENV['svn_user'] || "jonathan"
 set :svn_password, Proc.new { Capistrano::CLI.password_prompt('SVN Password: ') }
 set :repository,
  Proc.new { "--username #{svn_user} " +
             "--password #{svn_password} " +
             "--no-auth-cache " +
             "http://your.domain.tld/path/to/svn/#{application}/trunk/" }

So you can now do things like :

  svn_user=your_name cap deploy

and the svn checkout will use ‘your_name’ as svn username, prompt you for the subversion password (remember, you’re using ssh, so no clear password transit) and then do the checkout normaly.

Generate config/database.yml on-the-fly

Just like passwords, it’s a good idea to avoid having your database configuration in subversion if you’re more than one developer to commit code. So why not generate it locally and put it through our lovely ssh connection, at deployement time ?

  desc "After updating code we need to populate a new database.yml"
task :after_update_code, :roles => :app do
  require "yaml"
  set :production_database_password, proc { Capistrano::CLI.password_prompt("Production database remote Password : ") }

  buffer = YAML::load_file('config/database.yml.template')
  # get ride of uneeded configurations
  buffer.delete('test')
  buffer.delete('development')
  
  # Populate production element
  buffer['production']['adapter'] = "postgresql"
  buffer['production']['database'] = "vms_production"
  buffer['production']['username'] = "you_db_username
  buffer['production']['password'] = production_database_password
  buffer['production']['host'] = "localhost"
  
  put YAML::dump(buffer), "#{release_path}/config/database.yml", :mode => 0664
end

This code uses the config/database.yml.template file (it’s up to you to have one, I don’t think this one is hard :D), to generate a simple database.yml containing only the production database configuration. Additionnaly it prompts you for the database connection password.

Isn’t this great ?

Published on Sat, 15 Jul 2006 16:33

Enhanced Localization Plugin for Rails

For a project I had at work, I need to have a website in different languages. I assumed this was a common task nowadays, but I quickly found the limits of current solutions in Rails or at least I didn’t found one which matched my criteras for this project : lightweight, allows texts localizations and more importantly permits URLs localizations.

So I took one of the simpler plugins for localization tasks : Localization from Thomas Fuchs. Then I tweaked it a little bit to make it fits my needs and here comes the result : Localization Enhanced. It allows you to easily translate your texts using simple hashes loaded at startup, have as many languages as you want and have controllers/actions translations as well, all using the standards Rails methods (link_to, url_for, etc.). Additionally, I added a little refinement to ActionView::Helpers::AssetTagHelper#image_tag which allows you to use different images based on the current languages where you need it (images-based menu bar, …), by passing :loc => true as an option to image_tag. This one results in image tag generating an url prefixed by the current language (EN_en, FR_fr, etc.) unless the current language is the default one.

If you want to give it a try here’s the subversion repository url to get it :

http://projects.tron.name/svn/railsplugins/localization_enhanced/

or directly install it with :

./script plugin install http://projects.tron.name/svn/railsplugins/localization_enhanced/

License is the same as the original one : MIT Licence (at least I think it is this one as I didn’t find any mention of one in the source).

Published on Sun, 09 Jul 2006 16:09

RSS