Ruby et Merb inside : initialisation

Publié le 10 janvier 2009 par Olivier Duval

Préambule

Cette année, parmi mes bonnes résolutions, j'ai décidé de me mettre (réellement) à Ruby, tant qu'au niveau personnel que professionnel. Pourquoi ? tout simplement qu'apprendre un langage c'est sympa, d'autant plus si ce dernier est prometteur.

Parmi les langages dits interprétés, dans ma vie professionnelle, j'ai pu m'exercer au développement PHP ou Perl (encore maintenant, cela peut m'arriver de taper quelques lignes), que ce fût pour le développement Web ou tout simplement le développement de scripts. Aussi, regarder vers d'autres langages- dynamiques (ie : vs. C#) - me paraît une démarche toute naturelle.

En plus d'apprendre un nouveau langage, Ruby semble être un candidat tout approprié, tant pour son élégance que pour sa puissance. A une époque, Python me titillait les doigts, mais, décision toute personnelle, la syntaxe me déplaisait, injuste et totalement partial, oui je sais - même si Django est en vogue comme framework MVC ou encore Google app engine ou encore ...Zope...non je plaisante , mais la syntaxe Python, non, vraiment, non, c'était au-dessus de mes forces. Un langage est souvent une affaire de coup de cœur.

Le meilleur moyen de prendre en main un langage est de mettre en application ce dernier - soit dans du scripting, soit dans une application Web, j'essaierai les deux.

Le réflexe serait de se diriger vers Rails. Bien qu'avoir lu le fameux Ruby on Rails et m'avoir testé à quelques essais Web, le framework m'a semblé extrême dans sa démarche.

Je m'explique :

  • c'est un tout (ou rien), pas réellement le choix des briques logiciels utilisées : ORM, Javascript, moteur de rendu, bref un bloc monolithique,
  • tout est convention (over configuration) et donc beaucoup d'implicite, notamment avec ActiveRecord, cela devient difficile avec un existant, même si on peut désactiver certaines choses,
  • trop complexe à appréhender pour un novice malgré sa toute relative simplicité affichée, les erreurs affichées sont une catastrophe,

même si toutes ces objections paraissent être des mythes. Anyway, je pense que Rails reste trop uniforme, voire monoculture et ne donne pas suffisamment de liberté de choix au développeur...mais je changerai peut-être d'avis.

Installation de Ruby et de Merb

Procédons à l'installation de Ruby et de Merb. Il est évident que dans la vraie vie, tout ne se passe pas comme on le souhaiterait, voyons ce qu'il faut faire pour que cela se passe - à peu près - bien.

sous Linux

Ruby et Merb

Les versions installées :

  • Ruby : 1.8.6
  • Merb : 1.0.7.1, DataMapper : 0.9.9

L'environnement :

  • Debian Etch
  • Apache 2.x

Sous Linux, on préférera Ruby Entreprise Edition à la version officielle (sous Debian Etch, il demande au moins les paquet zlib1g-dev, libssl-dev). Pour les Debianiste, la version proposée de Ruby dans les sources officielles est la 1.8.5, autant dire trop vieille, on pourra passer par un backport pour obtenir une version plus récente.

REE est installé avec le répertoire racine /usr/local, tous les binaires seront donc installés sous /usr/local/bin

Installer les librairies sqlite et mysql pour Ruby : cela demande au préalable les entêtes pour chacun (SQLite 3 et MySQL 5) :

$ apt-get install libsqlite3-dev libmysqlclient15-dev

puis les gems :

$ gem install mysql sqlite3-ruby

on installe Merb :

$ gem install merb

Création d'une application pour test : $ merb-gen app test

lors de l'installation de Merb (1.0.7), la dépendance vers DataMapper semble être erronée, il faut modifier le fichier de l'application, test/config/dependencies.rb pour faire pointer vers la bonne version installée : dm_gems_version = "0.9.8" => dm_gems_version = "0.9.9"

In fine, on obtient l'environnement suivant :

$ gem environment

RubyGems Environment:
 - RUBYGEMS VERSION: 1.3.1
 - RUBY VERSION: 1.8.6 (2008-08-08 patchlevel 286) [i686-linux]
 - INSTALLATION DIRECTORY: /usr/local/lib/ruby/gems/1.8
 - RUBY EXECUTABLE: /usr/local/bin/ruby
 - EXECUTABLE DIRECTORY: /usr/local/bin
 - RUBYGEMS PLATFORMS:
   - ruby
   - x86-linux
 - GEM PATHS:
    - /usr/local/lib/ruby/gems/1.8
    - /home/od/.gem/ruby/1.8
 - GEM CONFIGURATION:
    - :update_sources => true
    - :verbose => true
    - :benchmark => false
    - :backtrace => false
    - :bulk_threshold => 1000
 - REMOTE SOURCES:
    - http://gems.rubyforge.org/

Serveur Web

Pour Merb, il nous faut un serveur Web, j'ai sélectionné Passenger du même éditeur que REE. Comme toujours, on fait simple :

les entêtes Apache2 sont nécessaires : $ apt-get install apache2-dev

$ gem install passenger

$ passenger-install-apache2-module

puis création d'un module passenger pour Apache2 dans /etc/apache2/mods-available/ :

cat > /etc/apache2/mods-available/passenger.load << EOF
LoadModule passenger_module /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.6/ext/apache2/mod_passenger.so

PassengerRoot /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.6
PassengerRuby /usr/local/bin/ruby
EOF

on l'active :

$ a2enmod passenger & /etc/init.d/apache2 force-reload

L'exécution du site demande le rewriting d'URL : $ a2enmod rewrite

Sinon, à la place de Passenger ou en complément, il y a aussi le serveur mongrel que l'on installera avec gem install mongrel. Cela peut-être intéressant de l'installer car Merb a un mode interactif, pour debugguer une application, cela pourra aider.

sous Windows

Sous Windows, on installera Ruby avec la version RubyOn-Click Installer.

Installation de SQLite 3 :

$ gem install --version 1.2.3 sqlite3-ruby

Télécharger sur http://rubyforge.org/projects/dorb, le provider DM pour do_sqlite3 prendre la version x86-mswin32 puis l'installer :

$ gem install do_sqlite3-0.9.10.1-x86-mswin32.gem --local

En effet, le paquet par défaut sur rubyforge ne s'installe pas sous Windows car il demande une compilation de celui-ci :

$ gem install do_sqlite3

Building native extensions.  This could take a while...
ERROR:  Error installing do_sqlite3:
       ERROR: Failed to build gem native extension.

d:/ruby/bin/ruby.exe extconf.rb install do_sqlite3
checking for sqlite3.h... no
*** extconf.rb failed ***

Il faudra également téléchargé la DLL sur le site de SQLite pour le mettre dans le répertoire d'installation de Ruby (d:\ruby\bin).

Au niveau serveur Web, choisissons Mongrel :

$ gem install mongrel

Testons notre installation

$ merb-gen app test
$ cd test
$ merb

devrait lancer le serveur Web sur le port 4000, cliquez sur http://localhost:4000

Testons un programme ruby

Je veux rechercher une URL dans des mails stockés sous forme de fichier, pour des mails en provenance d'une adresse précise. L'URL trouvée sera stockée dans un cache distribué memcached.

Nous avons besoin de 2 librairies : une pour lire un mail, une autre pour le client memcached.

TMail : $ gem install tmail

Memcached : téléchargement sur http://www.deveiate.org/projects/RMemCache du gem puis installation :

$ gem install Ruby-MemCache-0.0.4.gem

ou sinon il y a aussi http://tangent.org/552/libmemcached.html mais cela nécessite la librairie libmemcache qu'il faut compiler & co, pour ensuite installer le gem : $ gem install memcached

Le script maintenant :

#!/usr/local/bin/ruby
 
require 'rubygems'
require 'tmail'
require 'memcache'
 
spooldir = "/home/od/spool/*"
from = "no-reply\@dummy.net";
expire = 4*60*60
 
memcache_options = { :c_threshold => 10_000, :compression => true, :debug => false, :readonly => false, :urlencode => false }
CACHE = MemCache.new('localhost:11211', memcache_options)
 
Dir.glob(spooldir).sort.each do |f|
   mail = TMail::Mail.load(f)
   if mail.from.include?(from)
      (prefix,domain) = mail.to[0].split(/\@/)
      url = mail.body.match(/(http:\/\/.+)/i)
      CACHE.set(prefix.downcase,url[0],expire) if url
   end
end

c'est un réel plaisir ce langage, tellement expressif et naturel.

Astuces

Ne pas hésiter à utiliser le mode verbose de Merb : merb -V, cela permet de savoir les éventuelles erreurs lors du lancement.

Merb -i lancera l'application en mode interactif, ce qui signifie qu'on pourra taper des commandes directement pour simuler les accès ou obtenir des informations sur l'instance en cours.

Ressources

Installation de Passenger pour Merb.

Livres gratuits en PDF sur Ruby : Livre de 400 pages avec exemples à l'appui et solution Visual Studio SLN (pour une utilisation sous Ruby In Steel avec IronRuby) ou bien un livre de 80 pages du même éditeur.

Pour les développeurs C#, une série pour appréhender Ruby au travers de C# / IronRuby