<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>algo::rithmique</title>
	<atom:link href="http://www.algorithmique.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.algorithmique.net</link>
	<description>[Why not]</description>
	<lastBuildDate>Sat, 19 Dec 2009 15:54:27 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Si vous lisez ceci&#8230;</title>
		<link>http://www.algorithmique.net/2009/12/19/si-vous-lisez-ceci/</link>
		<comments>http://www.algorithmique.net/2009/12/19/si-vous-lisez-ceci/#comments</comments>
		<pubDate>Sat, 19 Dec 2009 15:54:27 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Projets]]></category>
		<category><![CDATA[Algo::rithmique]]></category>

		<guid isPermaLink="false">http://www.algorithmique.net/?p=825</guid>
		<description><![CDATA[&#8230; c&#8217;est que vous utilisez encore l&#8217;ancienne adresse de flus RSS d&#8217;algorithmique.net. Il est temps de vous mettre à jour : http://algorithmique.net/atom.xml. Et si en plus vous voulez comprendre les raisons de ce changement, lisez donc ceci.
]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.algorithmique.net/wp-content/uploads/2009/10/projets.png" alt="" title="projets" width="67" height="72" class="alignleft size-full wp-image-556" />&#8230; c&#8217;est que vous utilisez encore l&#8217;ancienne adresse de flus RSS d&#8217;algorithmique.net. Il est temps de vous mettre à jour : <a href="http://algorithmique.net/atom.xml">http://algorithmique.net/atom.xml</a>. Et si en plus vous voulez comprendre les raisons de ce changement, lisez donc <a href="http://algorithmique.net/Site/2009/12/18/bye-bye-wordpress-bonjour-jekyll.html">ceci</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.algorithmique.net/2009/12/19/si-vous-lisez-ceci/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Server side Faye&#8217;s client ou le protocole Bayeux</title>
		<link>http://www.algorithmique.net/2009/11/24/server-side-fayes-client-ou-le-protocole-bayeux/</link>
		<comments>http://www.algorithmique.net/2009/11/24/server-side-fayes-client-ou-le-protocole-bayeux/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 17:41:33 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[Bayeux]]></category>
		<category><![CDATA[Capcode]]></category>
		<category><![CDATA[Comet]]></category>
		<category><![CDATA[Rack]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.algorithmique.net/?p=769</guid>
		<description><![CDATA[Dans mon précédent article, je vous ai montré comment mettre en place un Comet avec Capcode. J&#8217;ai découvert que certains d&#8217;entre vous lisent ce que j&#8217;écris1 par le biais de quelques mails dans ma boite aux lettres. L&#8217;un d&#8217;entre vous m&#8217;a même demandé comment faire pour envoyer des évènements sur le bus Comet sans passer [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.algorithmique.net/wp-content/uploads/2009/09/dev.png" alt="dev" title="dev" width="72" height="72" class="alignleft size-full wp-image-562" />Dans mon <a href="http://www.algorithmique.net/2009/11/21/notification-comet-capcode/">précédent article</a>, je vous ai montré comment mettre en place un <a href="http://en.wikipedia.org/wiki/Comet_(programming)">Comet</a> avec <a href="http://github.com/glejeune/Capcode">Capcode</a>. J&#8217;ai découvert que certains d&#8217;entre vous lisent ce que j&#8217;écris<small><sup>1</sup></small> par le biais de quelques mails dans ma boite aux lettres. L&#8217;un d&#8217;entre vous m&#8217;a même demandé comment faire pour envoyer des évènements sur le bus Comet sans passer par l&#8217;application Web. Bonne question, sachant qu&#8217;en effet, <a href="http://github.com/jcoglan/faye">faye</a> ne propose aucune solution pour cela. Et bien je me suis amusé à en développer une&#8230;</p>
<h3>Faye</h3>
<p>Pour comprendre ce que nous allons faire, il faut prendre le temps de regarder comment fonctionne <tt>faye</tt>. Mais avant, nous devons choisir la solution à adopter pour écrire notre librairie. En effet, nous avons deux choix possibles : soit nous pouvons <i>parler</i> directement au serveur <tt>faye</tt>, soit nous pouvons <i>simuler</i> le comportement d&#8217;un client. En fonction de ce choix, nous regarderons telle ou telle partie du code de <tt>faye</tt>. Bon et puisque c&#8217;est moi qui choisis<small><sup>2</sup></small>, j&#8217;opte pour la seconde solution.</p>
<p>Avant de décortiquer le code, rappelons le cheminement par l&#8217;utilisateur lors de l&#8217;utilisation de <tt>soapbox</tt>. Avant tout nous démarrons l&#8217;application<small><sup>3</sup></small>. Nous donnons notre <i>username</i>. Ensuite nous indiquons qui nous voulons suivre. Enfin nous racontons notre vie. Ces deux dernières étapes pouvant se faire dans n&#8217;importe quel ordre, et autant de fois que nous voulons.</p>
<p>Regardons maintenant le code. Lors de l&#8217;accès à l&#8217;application (route <tt>/</tt>) nous recevons la page mise en place par la vue <tt>views/index.rhtml</tt>. Dans cette vue, ce qui nous intéresse ce sont les lignes suivantes :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>40
41
42
43
44
45
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;script</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    Comet = new Faye.Client('/comet');
    Comet.connect();
&nbsp;
    Soapbox.init(Comet);
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Nous créons un client Comet (ligne 41) pour le bus accessible via la route <tt>/comet</tt> puis nous établissons la connexion (ligne 42). Ensuite nous initialisons l&#8217;application (ligne 44).  Si nous regardons à quoi correspondent la création et la connexion du client Comet, il faut se plonger dans le code du script <tt>comet.js</tt>. Ce fichier est généré lors de la création du gem <tt>faye</tt> à partir de l&#8217;ensemble des fichiers contenus dans le répertoire <a href="http://github.com/jcoglan/faye/tree/master/client/">client</a> des sources. Le fichier qui nous intéresse principalement ici est <a href="http://github.com/jcoglan/faye/blob/master/client/client.js">client/client.js</a>. Dans ce fichier vous trouverez le code correspondant à la connexion entre les lignes <a href="http://github.com/jcoglan/faye/blob/master/client/client.js#L75-L113">75 et 113</a>.</p>
<p>Si nous regardons maintenant le fichier <a href="http://github.com/glejeune/Capcode/blob/master/examples/soapbox/public/soapbox.js">soapbox.js</a> nous pouvons étudier ce qui se passe lors de l&#8217;initialisation de l&#8217;application. Nous voyons dans ce code que <tt>soapbox</tt> <a href="http://github.com/glejeune/Capcode/blob/master/examples/soapbox/public/soapbox.js#L20-L24">attend que l&#8217;utilisateur saisisse son <i>username</i></a>. Une fois ceci fait, l&#8217;application <a href="http://github.com/glejeune/Capcode/blob/master/examples/soapbox/public/soapbox.js#L34"><i>souscrit</i> au channel <tt>/mentioning/&lt;username&gt;</tt></a>, <a href="http://github.com/glejeune/Capcode/blob/master/examples/soapbox/public/soapbox.js#L37-L39">elle masque la zone de saisie du <i>username</i> et affiche les zones de saisie des personnes à suivre et des messages</a>. Elle met ensuite en place les actions correspondantes pour ces deux zones de saisie. La première de ces actions se traduit par <a href="http://github.com/glejeune/Capcode/blob/master/examples/soapbox/public/soapbox.js#L43-L50">la souscription au channel <tt>/from/&lt;follow&gt;</tt> avec comme callback : <tt>accept</tt>. La seconde <a href="http://github.com/glejeune/Capcode/blob/master/examples/soapbox/public/soapbox.js#L55">revoie vers la méthode <tt>post</tt></a> dont le rôle principal est de <a href="http://github.com/glejeune/Capcode/blob/master/examples/soapbox/public/soapbox.js#L84">publier le message sur le channel <tt>/from/&lt;username&gt;</tt></a>.</p>
<p>Outch !</p>
<p>Ce qui est important ici c&#8217;est de voir ce dont nous avons besoin pour faire cela. Nous en retiendrons donc la nécessité de développer une méthode de connexion, une méthode de souscription et une méthode de publication. Pour comprendre comment ces méthodes agissent, il suffit de regarder ce qui est fait dans les méthodes correspondantes de <a href="http://github.com/jcoglan/faye/blob/master/client/client.js">Faye.Client</a>.</p>
<p>Je ne vais pas pouvoir, au risque de perdre plus de monde que ceux qui ont déjà lâché prise avant la fin du dernier paragraphe, entrer plus dans les détails. Il va donc falloir me croire sur parole ;) En fait, ce que nous allons faire c&#8217;est mettre en place une version cliente du protocole des échanges Comet appelé protocole Bayeux. Je vous engage donc à en lire <a href="http://svn.cometd.com/trunk/bayeux/bayeux.html">la documentation</a> si vous souhaitez approfondir le sujet.</p>
<h3>Messages</h3>
<p>Les échanges entre le client Comet et le bus peuvent se faire de deux façons, soit en <tt>long-polling</tt> soit en <tt>callback-polling</tt>. Dans notre cas, nous utilisons la première solution en faisant un envoie en <tt>POST</tt> du paramètre <tt>message</tt>, ce dernier ayant pour valeur une chaine JSON.</p>
<p>Mettons cela en place :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Faye
  <span style="color:#9966CC; font-weight:bold;">class</span> Client
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span> uri_or_string <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@uri</span> = uri_or_string
      <span style="color:#0066ff; font-weight:bold;">@uri</span> = <span style="color:#CC00FF; font-weight:bold;">URI</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>@uri<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@uri</span>.<span style="color:#9966CC; font-weight:bold;">class</span> == <span style="color:#CC0066; font-weight:bold;">String</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    private
    <span style="color:#9966CC; font-weight:bold;">def</span> send<span style="color:#006600; font-weight:bold;">&#40;</span> message <span style="color:#006600; font-weight:bold;">&#41;</span>
      res = <span style="color:#6666ff; font-weight:bold;">Net::HTTP</span>.<span style="color:#9900CC;">post_form</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#0066ff; font-weight:bold;">@uri</span>, <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;message&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> message.<span style="color:#9900CC;">to_json</span> <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> JSON.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span> res.<span style="color:#9900CC;">body</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Je place cette méthode en <tt>private</tt> car elle n&#8217;a d&#8217;intérêt que pour les méthodes que nous allons écrire ensuite.</p>
<p>Comme vous pouvez le voir, le retour est également une structure JSON.</p>
<h3>&laquo;&nbsp;Handshake&nbsp;&raquo;</h3>
<p>Si vous regardez précisément ce qui se passe lors de l&#8217;initialisation de la connexion du client Comet, vous verrez qu&#8217;en fait, il n&#8217;y a pas de connexion véritable, mais un <i>handshake</i>. Cela consiste en fait à se présenter au bus Comet et à obtenir de sa part, un identifiant. Nous devrons, par la suite toujours, utiliser cet identifiant pour communiquer avec le bus.</p>
<p>Le message du <i>handshake</i> doit contenir au moins les champs suivants :</p>
<ul>
<li><tt>channel</tt> : le channel.</li>
<li><tt>version</tt> : la version du protocole.</li>
<li><tt>supportedConnectionTypes</tt> : les types de connexions supportées.</li>
</ul>
<p>Un <tt>channel</tt> est représenté comme un chemin sous la forme <tt>/foo/bar/...</tt> et doit systématiquement commencer par un <tt>/</tt>. Il en existe deux types : ceux définis par l&#8217;application et ceux réservés par le protocole. Ces derniers commencent toujours par <tt>/meta/</tt>. Dans le cas du <i>handshake</i>, le channel doit être <tt>/meta/handshake</tt>.</p>
<p>La version doit correspondre au numéro de version du protocole. 1.0 ici.</p>
<p>Le paramètre <tt>supportedConnectionTypes</tt> contient la liste des types de transports supportés. Bien que nous ayons dit plus haut que nous emploierons du <tt>long-polling</tt>, nous positionnerons la valeur <tt>["long-polling", "callback-polling"]</tt>. Ceci simplement parce que si nous souhaitons implémenter le <tt>callback-polling</tt> nous n&#8217;aurons pas de modification à faire ;)</p>
<p>Voici donc à quoi ressemblera la méthode de <i>handshake</i> :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Faye
  <span style="color:#9966CC; font-weight:bold;">class</span> Client
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span> uri_or_string <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@uri</span> = uri_or_string
      <span style="color:#0066ff; font-weight:bold;">@uri</span> = <span style="color:#CC00FF; font-weight:bold;">URI</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>@uri<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@uri</span>.<span style="color:#9966CC; font-weight:bold;">class</span> == <span style="color:#CC0066; font-weight:bold;">String</span>
      <span style="color:#0066ff; font-weight:bold;">@clientId</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
      <span style="color:#0066ff; font-weight:bold;">@interval</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> handshake
      id = Faye.<span style="color:#9900CC;">random</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">32</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      message = <span style="color:#006600; font-weight:bold;">&#123;</span>
        <span style="color:#996600;">&quot;channel&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">Faye::Channel::HANDSHAKE</span>,
        <span style="color:#996600;">&quot;version&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">Faye::BAYEUX_VERSION</span>,
        <span style="color:#996600;">&quot;supportedConnectionTypes&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#996600;">&quot;long-polling&quot;</span>, <span style="color:#996600;">&quot;callback-polling&quot;</span> <span style="color:#006600; font-weight:bold;">&#93;</span>,
        <span style="color:#996600;">&quot;id&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> id
      <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
      response = send<span style="color:#006600; font-weight:bold;">&#40;</span> message <span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> response<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;successful&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">and</span> response<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;id&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> == id
        <span style="color:#0066ff; font-weight:bold;">@clientId</span> = response<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;clientId&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
        <span style="color:#0066ff; font-weight:bold;">@interval</span> = response<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;advice&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;interval&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        <span style="color:#CC0066; font-weight:bold;">raise</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Dans cette méthode j&#8217;utilise <tt>Faye::Channel::HANDSHAKE</tt> et <tt>Faye::BAYEUX_VERSION</tt>, deux constantes déclarées dans <tt>faye</tt>. Si vous souhaitez être indépendant de ce dernier, vous pouvez remplacer ces valeurs par celle que j&#8217;ai indiquée. Vous noterez également que j&#8217;ai ajouté dans le message le paramètre optionnel <tt>id</tt>. Ce paramètre permettra de valider, dans certains cas, que la réponse que nous recevons est bien celle attendu. En effet, si en retour nous retrouvons ce même ID c&#8217;est que, à priori tout va bien. Je dis bien &laquo;&nbsp;à priori&nbsp;&raquo;&#8230;</p>
<p>Je vous ai indiqué que la raison d&#8217;être de ce <t>handshake</i> était de récupérer un identifiant client. C&#8217;est ce que nous faisons en parsant la réponse. Cette réponse peut avoir deux structures différentes en fonctions ou non de la présence d&#8217;erreur. Je ne détaillerai pas la structure complète, retenez seulement quand dans le cas présent nous devons avoir récupéré les données suivantes :</p>
<ul>
<li><tt>successful</tt> : suffisament parlant je pense ;)</li>
<li><tt>id</tt> : qui doit correspondre à l&#8217;ID envoyé.</li>
<li><tt>clientId</tt> : le clientId a utiliser par la suite.</li>
</ul>
<p>Je ne parlerai pas de la valeur <tt>interval</tt> que je récupère simplement en pensant à une prochaine évolution de ce petit développement&#8230;</p>
<h3>Connexion</h3>
<p>La connexion se fait en envoyant un message contenant les données suivantes :</p>
<ul>
<li><tt>channel</tt> : dans le cas d&#8217;une connexion nous utiliserons <tt>/meta/connect</tt> qui sera ici récupéré via la constante <tt>Faye::Channel::CONNECT</tt>.</li>
<li><tt>clientId</tt> : est la valeur récupérée lors du <i>handshake</i></li>
<li><tt>connectionType</tt> : je n&#8217;y reviens pas, mais vous l&#8217;avez compris, nous faisons du <tt>long-polling</tt>.</li>
<li><tt>id</tt> : là encore, ce n&#8217;est que mimétisme.</li>
</ul>
<p>Voici donc comment nous pouvons implémenter cela :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Faye
  <span style="color:#9966CC; font-weight:bold;">class</span> Client
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span> uri_or_string <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@uri</span> = uri_or_string
      <span style="color:#0066ff; font-weight:bold;">@uri</span> = <span style="color:#CC00FF; font-weight:bold;">URI</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>@uri<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@uri</span>.<span style="color:#9966CC; font-weight:bold;">class</span> == <span style="color:#CC0066; font-weight:bold;">String</span>
      <span style="color:#0066ff; font-weight:bold;">@clientId</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
      <span style="color:#0066ff; font-weight:bold;">@interval</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> connect
      id = Faye.<span style="color:#9900CC;">random</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">32</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      message = <span style="color:#006600; font-weight:bold;">&#123;</span>
        <span style="color:#996600;">&quot;channel&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">Faye::Channel::CONNECT</span>,
        <span style="color:#996600;">&quot;clientId&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@clientId</span>,
        <span style="color:#996600;">&quot;connectionType&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;long-polling&quot;</span>,
        <span style="color:#996600;">&quot;id&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> id
      <span style="color:#006600; font-weight:bold;">&#125;</span>
      r = send<span style="color:#006600; font-weight:bold;">&#40;</span> message <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>A ce niveau, si vous faites un petit test, vous vous rendrez compte que la connexion attend une réponse de la part du serveur. En effet cette connexion attend que le bus Comet envoie des données. C&#8217;est ainsi que nous simulons le push ! Ce sont ces données que nous devrons donc traiter en fonction des souscriptions.</p>
<p>Pour savoir si le retour est exact, nous devons retrouver dans la structure JSON le champ <tt>successful</tt> à <tt>true</tt> et le champ <tt>id</tt> avec la même valeur que celle envoyée.</p>
<p>Si tout se passe bien, alors nous pouvons récupérer les données du message dans la structure <tt>data</tt> :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Faye
  <span style="color:#9966CC; font-weight:bold;">class</span> Client
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span> uri_or_string <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@uri</span> = uri_or_string
      <span style="color:#0066ff; font-weight:bold;">@uri</span> = <span style="color:#CC00FF; font-weight:bold;">URI</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>@uri<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@uri</span>.<span style="color:#9966CC; font-weight:bold;">class</span> == <span style="color:#CC0066; font-weight:bold;">String</span>
      <span style="color:#0066ff; font-weight:bold;">@clientId</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
      <span style="color:#0066ff; font-weight:bold;">@interval</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> connect
      id = Faye.<span style="color:#9900CC;">random</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">32</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      message = <span style="color:#006600; font-weight:bold;">&#123;</span>
        <span style="color:#996600;">&quot;channel&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">Faye::Channel::CONNECT</span>,
        <span style="color:#996600;">&quot;clientId&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@clientId</span>,
        <span style="color:#996600;">&quot;connectionType&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;long-polling&quot;</span>,
        <span style="color:#996600;">&quot;id&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> id
      <span style="color:#006600; font-weight:bold;">&#125;</span>
      r = send<span style="color:#006600; font-weight:bold;">&#40;</span> message <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">if</span> r<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;id&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> == id <span style="color:#9966CC; font-weight:bold;">and</span> r<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;successful&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#0000FF; font-weight:bold;">true</span>
&nbsp;
        <span style="color:#008000; font-style:italic;"># traitement du message contenu dans r[1][&quot;data&quot;] pour la souscription au channel r[1][&quot;channel&quot;]</span>
        <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">elsif</span> r<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;successful&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#0000FF; font-weight:bold;">false</span>
&nbsp;
        <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Nous verrons au paragraphe souscription comment traiter le message de réponse. Avant cela, détaillons ce que nous devons faire en cas d&#8217;échec. Le protocole Bayeux nous indique que dans un tel cas, il faut refaire un <i>handshake</i> puis refaire la connexion. Cependant, comme la connexion elle-même est bloquante, dans le sens où elle attend une réponse, il serait bon de l&#8217;isoler dans un thread afin de permettre le déroulement de notre programme. De plus, si la connexion est un succès, une fois le message traité, il faut en rouvrir une de façon à se remettre en attente d&#8217;un nouveau <i>push</i> du serveur. Pour cela nous pouvons placer la connexion dans une boucle infinie. </p>
<p>Voici donc comment nous allons gérer cela :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Faye
  <span style="color:#9966CC; font-weight:bold;">class</span> Client
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span> uri_or_string <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@uri</span> = uri_or_string
      <span style="color:#0066ff; font-weight:bold;">@uri</span> = <span style="color:#CC00FF; font-weight:bold;">URI</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>@uri<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@uri</span>.<span style="color:#9966CC; font-weight:bold;">class</span> == <span style="color:#CC0066; font-weight:bold;">String</span>
      <span style="color:#0066ff; font-weight:bold;">@clientId</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
      <span style="color:#0066ff; font-weight:bold;">@interval</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
      <span style="color:#0066ff; font-weight:bold;">@connection</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> connect
      <span style="color:#0066ff; font-weight:bold;">@connection</span>.<span style="color:#9900CC;">kill</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@connection</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>?
      <span style="color:#0066ff; font-weight:bold;">@connection</span> = <span style="color:#CC00FF; font-weight:bold;">Thread</span>.<span style="color:#9900CC;">new</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
        faild = <span style="color:#0000FF; font-weight:bold;">false</span>
        <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#0000FF; font-weight:bold;">true</span>
          id = Faye.<span style="color:#9900CC;">random</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">32</span><span style="color:#006600; font-weight:bold;">&#41;</span>
          message = <span style="color:#006600; font-weight:bold;">&#123;</span>
            <span style="color:#996600;">&quot;channel&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">Faye::Channel::CONNECT</span>,
            <span style="color:#996600;">&quot;clientId&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@clientId</span>,
            <span style="color:#996600;">&quot;connectionType&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;long-polling&quot;</span>,
            <span style="color:#996600;">&quot;id&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> id
          <span style="color:#006600; font-weight:bold;">&#125;</span>
          r = send<span style="color:#006600; font-weight:bold;">&#40;</span> message <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
          <span style="color:#9966CC; font-weight:bold;">if</span> r<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;id&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> == id <span style="color:#9966CC; font-weight:bold;">and</span> r<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;successful&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#0000FF; font-weight:bold;">true</span>
&nbsp;
            <span style="color:#008000; font-style:italic;"># traitement du message contenu dans r[1][&quot;data&quot;] pour la souscription au channel r[1][&quot;channel&quot;]</span>
            <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
          <span style="color:#9966CC; font-weight:bold;">elsif</span> r<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;successful&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#0000FF; font-weight:bold;">false</span>
            faild = <span style="color:#0000FF; font-weight:bold;">true</span>
            <span style="color:#9966CC; font-weight:bold;">break</span>
          <span style="color:#9966CC; font-weight:bold;">end</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
        <span style="color:#9966CC; font-weight:bold;">if</span> faild
          handshake<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
          connect<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3>Souscription</h3>
<p>La souscription se fait pour un ou plusieurs channels avec, en second paramètre, la méthode qui doit être utilisée pour traiter les massages venant de ces channels. Nous avons déjà parlé des channels. Bien entendu dans le cas présent il s&#8217;agira de channels spécifiques à l&#8217;application. Concernant le callback, nous utiliserons un block.</p>
<p>Le message envoyé au bus Comet doit contenir les informations suivantes :</p>
<ul>
<lI><tt>channel</tt> : il ne s&#8217;agit pas, ici, du channel auquel nous souhaitons souscrire, mais celui utilisé par le protocole pour déclarer une souscription : <tt>/meta/subscribe</tt>, ou, dans notre cas ou nous utilisons <tt>faye</tt> : <tt>Faye::Channel::SUBSCRIBE</tt>. </li>
<li><tt>clientId</tt> : le client ID récupéré lors du <i>handshake</i>.</li>
<li><tt>subscription</tt> : ce paramètre prend en valeur un tableau des channels auxquels nous souhaitons souscrire.</li>
<li><tt>id</tt> : l&#8217;id du message.</li>
</ul>
<p>Comme vous pouvez le voir, nulle part nous ne stockons le callback à utiliser pour traiter les messages renvoyés. C&#8217;est normal puisque le bus Comet n&#8217;en à que faire puisqu&#8217;il seront exécutés côté client. Il nous appartient donc de les stocker. Nous ferons cela en mettant en place un hashage ayant pour clé le channel et comme valeur le block.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Faye
  <span style="color:#9966CC; font-weight:bold;">class</span> Client    
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span> uri_or_string <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@uri</span> = uri_or_string
      <span style="color:#0066ff; font-weight:bold;">@uri</span> = <span style="color:#CC00FF; font-weight:bold;">URI</span>.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>@uri<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@uri</span>.<span style="color:#9966CC; font-weight:bold;">class</span> == <span style="color:#CC0066; font-weight:bold;">String</span>
      <span style="color:#0066ff; font-weight:bold;">@clientId</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
      <span style="color:#0066ff; font-weight:bold;">@interval</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
      <span style="color:#0066ff; font-weight:bold;">@connection</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
      <span style="color:#0066ff; font-weight:bold;">@subscriptions</span> = <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> subscribe<span style="color:#006600; font-weight:bold;">&#40;</span> channels, <span style="color:#006600; font-weight:bold;">&amp;</span>block <span style="color:#006600; font-weight:bold;">&#41;</span>
      channels = <span style="color:#006600; font-weight:bold;">&#91;</span>channels<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> channels.<span style="color:#9966CC; font-weight:bold;">class</span> == <span style="color:#CC0066; font-weight:bold;">Array</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> block
        channels.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>c<span style="color:#006600; font-weight:bold;">|</span>
          <span style="color:#0066ff; font-weight:bold;">@subscriptions</span><span style="color:#006600; font-weight:bold;">&#91;</span>c<span style="color:#006600; font-weight:bold;">&#93;</span> = block
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
      message = <span style="color:#006600; font-weight:bold;">&#123;</span>
        <span style="color:#996600;">&quot;channel&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">Faye::Channel::SUBSCRIBE</span>,
        <span style="color:#996600;">&quot;clientId&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@clientId</span>,
        <span style="color:#996600;">&quot;subscription&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> channels,
        <span style="color:#996600;">&quot;id&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> Faye.<span style="color:#9900CC;">random</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">32</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
      r = send<span style="color:#006600; font-weight:bold;">&#40;</span>message<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Je ne prends pas la peine de gérer le retour. Ce n&#8217;est pas bien !</p>
<h3>Connexion</h3>
<p>Nous pouvons maintenant revenir sur la connexion afin de traiter les messages. Il suffit donc de passer le message au block correspond au channel qui l&#8217;a poussé :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> connect
      <span style="color:#0066ff; font-weight:bold;">@connection</span>.<span style="color:#9900CC;">kill</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@connection</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>?
      <span style="color:#0066ff; font-weight:bold;">@connection</span> = <span style="color:#CC00FF; font-weight:bold;">Thread</span>.<span style="color:#9900CC;">new</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
        faild = <span style="color:#0000FF; font-weight:bold;">false</span>
        <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#0000FF; font-weight:bold;">true</span>
          id = Faye.<span style="color:#9900CC;">random</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">32</span><span style="color:#006600; font-weight:bold;">&#41;</span>
          message = <span style="color:#006600; font-weight:bold;">&#123;</span>
            <span style="color:#996600;">&quot;channel&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">Faye::Channel::CONNECT</span>,
            <span style="color:#996600;">&quot;clientId&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@clientId</span>,
            <span style="color:#996600;">&quot;connectionType&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;long-polling&quot;</span>,
            <span style="color:#996600;">&quot;id&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> id
          <span style="color:#006600; font-weight:bold;">&#125;</span>
          r = send<span style="color:#006600; font-weight:bold;">&#40;</span> message <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
          <span style="color:#9966CC; font-weight:bold;">if</span> r<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;id&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> == id <span style="color:#9966CC; font-weight:bold;">and</span> r<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;successful&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#0000FF; font-weight:bold;">true</span>
            <span style="color:#0066ff; font-weight:bold;">@subscriptions</span><span style="color:#006600; font-weight:bold;">&#91;</span>r<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;channel&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span> r<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;data&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
          <span style="color:#9966CC; font-weight:bold;">elsif</span> r<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;successful&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#0000FF; font-weight:bold;">false</span>
            faild = <span style="color:#0000FF; font-weight:bold;">true</span>
            <span style="color:#9966CC; font-weight:bold;">break</span>
          <span style="color:#9966CC; font-weight:bold;">end</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
        <span style="color:#9966CC; font-weight:bold;">if</span> faild
          handshake<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
          connect<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span></pre></div></div>

<h3>Publication</h3>
<p>La publication se fait par l&#8217;envoi d&#8217;un message contenant les champs suivants :</p>
<ul>
<li><tt>channel</tt> : le channel destinataire du message.</li>
<li><tt>data</tt> : les données, sous forme d&#8217;une structure JSON.</li>
<li><tt>clientId</tt> : le fameux client ID.</li>
<li><tt>id</tt> : par habitude ;)</li>
</ul>
<p>Ceci nous donne donc le code suivant :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Faye
  <span style="color:#9966CC; font-weight:bold;">class</span> Client
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> publish<span style="color:#006600; font-weight:bold;">&#40;</span> channel, data <span style="color:#006600; font-weight:bold;">&#41;</span>
      message = <span style="color:#006600; font-weight:bold;">&#91;</span>
        <span style="color:#006600; font-weight:bold;">&#123;</span>
          <span style="color:#996600;">&quot;channel&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> channel,
          <span style="color:#996600;">&quot;data&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> data, 
          <span style="color:#996600;">&quot;clientId&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@clientId</span>,
          <span style="color:#996600;">&quot;id&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> Faye.<span style="color:#9900CC;">random</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">32</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#006600; font-weight:bold;">&#93;</span>
      r = send<span style="color:#006600; font-weight:bold;">&#40;</span>message<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Encore une fois, je ne prends pas le temps de traiter la réponse&#8230; Encore une fois, ce n&#8217;est pas bien !!!</p>
<h3>&#8230; et leur contraire</h3>
<p>Là où il y a connexion, il y a forcement &laquo;&nbsp;déconnexion&nbsp;&raquo;, de même la où il y a souscription, il y a désabonnement. Je pense que vous avez compris le principe, et je me permets donc de vous livrer sans autre explication les méthodes correspondantes :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Faye
  <span style="color:#9966CC; font-weight:bold;">class</span> Client
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> disconnect
      <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0066ff; font-weight:bold;">@connection</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>?
        <span style="color:#0066ff; font-weight:bold;">@connection</span>.<span style="color:#9900CC;">kill</span> 
        message = <span style="color:#006600; font-weight:bold;">&#123;</span>
          <span style="color:#996600;">&quot;channel&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">Faye::Channel::DISCONNECT</span>,
          <span style="color:#996600;">&quot;clientId&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@clientId</span>,
          <span style="color:#996600;">&quot;id&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> Faye.<span style="color:#9900CC;">random</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">32</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#006600; font-weight:bold;">&#125;</span>
        r = send<span style="color:#006600; font-weight:bold;">&#40;</span> message <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> unsubscribe<span style="color:#006600; font-weight:bold;">&#40;</span> channels <span style="color:#006600; font-weight:bold;">&#41;</span>
      channels = <span style="color:#006600; font-weight:bold;">&#91;</span>channels<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> channels.<span style="color:#9966CC; font-weight:bold;">class</span> == <span style="color:#CC0066; font-weight:bold;">Array</span>
      channels.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>c<span style="color:#006600; font-weight:bold;">|</span>
        <span style="color:#0066ff; font-weight:bold;">@subscriptions</span>.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span>c<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
      message = <span style="color:#006600; font-weight:bold;">&#123;</span>
        <span style="color:#996600;">&quot;channel&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">Faye::Channel::UNSUBSCRIBE</span>,
        <span style="color:#996600;">&quot;clientId&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@clientId</span>,
        <span style="color:#996600;">&quot;subscription&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> channels,
        <span style="color:#996600;">&quot;id&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> Faye.<span style="color:#9900CC;">random</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">32</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
      r = send<span style="color:#006600; font-weight:bold;">&#40;</span>message<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3>Let&#8217;s play !</h3>
<p>Maintenant que nous avons notre librairie cliente, nous pouvons développer un petit client en ligne de commande pour <tt>soapbox</tt>.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">x = <span style="color:#6666ff; font-weight:bold;">Faye::Client</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">'http://localhost:3000/comet'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;-- handshake&quot;</span>
x.<span style="color:#9900CC;">handshake</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;-- subscriptions&quot;</span>
x.<span style="color:#9900CC;">subscribe</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;/mentioning/daemon&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
x.<span style="color:#9900CC;">subscribe</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;/from/greg&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>r<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;#{r[&quot;</span>user<span style="color:#996600;">&quot;]} : #{r[&quot;</span>message<span style="color:#996600;">&quot;]}&quot;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;-- connect&quot;</span>
x.<span style="color:#9900CC;">connect</span>
&nbsp;
msg = <span style="color:#996600;">&quot;&quot;</span>  
<span style="color:#9966CC; font-weight:bold;">while</span> msg != <span style="color:#996600;">&quot;quit&quot;</span>
  msg = <span style="color:#ff6633; font-weight:bold;">$stdin</span>.<span style="color:#CC0066; font-weight:bold;">readline</span>.<span style="color:#CC0066; font-weight:bold;">chomp</span>
  <span style="color:#9966CC; font-weight:bold;">unless</span> msg == <span style="color:#996600;">&quot;quit&quot;</span>
    channel = <span style="color:#996600;">&quot;/from/daemon&quot;</span>
    data = <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;user&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;daemon&quot;</span>, <span style="color:#996600;">&quot;message&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> msg <span style="color:#006600; font-weight:bold;">&#125;</span>
    r = x.<span style="color:#9900CC;">publish</span><span style="color:#006600; font-weight:bold;">&#40;</span> channel, data <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">unless</span> r<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;successful&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;=&gt; Message not send !&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
x.<span style="color:#9900CC;">disconnect</span></pre></div></div>

<p>Bon, OK, c&#8217;est très très rudimentaire, mais vous avez compris ! Et le principal c&#8217;est que cela fonctionne :</p>
<p><img src="http://www.algorithmique.net/wp-content/uploads/2009/11/soapbox-console.png" alt="soapbox-console" title="soapbox-console" width="100%" class="alignnone size-full wp-image-809" /></p>
<h3>A+</h3>
<p><b>Attention</b>, n&#8217;oubliez pas la remarque faite sur la page du projet faye : <i>it&#8217;s a toy</i>. Donc, tout comme ce qui précède, n&#8217;utilisez pas cela en production<small><sup>4</sup></small>. Et bien cela s&#8217;applique, à plus forte raison, à ce qui est écrit ci-dessus. Maintenant, si vous êtes joueur, vous pouvez récupérer cela dans les sources de <tt>Capcode</tt> ou <a href="http://gist.github.com/241065">ici</a>.</p>
<p>Notez que si je me suis attaché à <tt>faye</tt>, ce petit client devrait pouvoir fonctionner avec toute solution Comet respectant le protocole Bayeux. </p>
<p><small><sup>1</sup> Merci !</small><br />
<small><sup>2</sup> :P</small><br />
<small><sup>3</sup> Ca peut paraitre idiot, cela n&#8217;en reste pas moins vrai !</small><br />
<small><sup>4</sup> On vous aura prévenu !</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.algorithmique.net/2009/11/24/server-side-fayes-client-ou-le-protocole-bayeux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notification, Comet, &#8230; Capcode</title>
		<link>http://www.algorithmique.net/2009/11/21/notification-comet-capcode/</link>
		<comments>http://www.algorithmique.net/2009/11/21/notification-comet-capcode/#comments</comments>
		<pubDate>Sat, 21 Nov 2009 13:29:18 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[Capcode]]></category>
		<category><![CDATA[Comet]]></category>
		<category><![CDATA[Rack]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.algorithmique.net/?p=738</guid>
		<description><![CDATA[Depuis que nous développons des sites Web, nous avons pris l&#8217;habitude du mode connecté imposé par le protocole HTTP. Rien ne nous surprend plus quand nos serveurs ne répondent qu&#8217;à des demandes explicites. Et nous vivons avec l&#8217;habitude de ce dialogue de sourds ou le serveur répond à une requête en oubliant totalement ce qu&#8217;il [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.algorithmique.net/wp-content/uploads/2009/09/dev.png" alt="dev" title="dev" width="72" height="72" class="alignleft size-full wp-image-562" />Depuis que nous développons des sites Web, nous avons pris l&#8217;habitude du <i>mode connecté</i> imposé par le protocole HTTP. Rien ne nous surprend plus quand nos serveurs ne répondent qu&#8217;à des demandes explicites. Et nous vivons avec l&#8217;habitude de ce <i>dialogue de sourds</i> ou le serveur répond à une requête en oubliant totalement ce qu&#8217;il a <i>dit</i> à la demande précédente. Nous pallions généralement à ce problème en utilisant des principes de session et autre cookie, mais n&#8217;oublions pas que ces artefacts sont en fait gérés par le client à qui le serveur demande de stocker des <i>souvenirs</i>. Depuis l&#8217;apparition des frameworks JavaScript comme Dojo, prototype, jQuery et consorts, nous mettons de plus en plus de mécanismes dans les pages Web qui évitent de reloader toute une page. Là encore, cela ne fait plus rêver personne et nous restons toujours dans un mode <i>requête/réponse</i>. Là où nous écarquillons un peu plus les yeux, c&#8217;est quand une page Web affiche, sans que nous n&#8217;ayons rien demandé, de nouvelles informations. C&#8217;est tout le principe des <i>notifications</i> et c&#8217;est ce que nous allons mettre en place ici.</p>
<h3>Notifications ?</h3>
<p>Une notification intervient quand un serveur envoie des données au client <i>quand il en a envie</i>, et donc sans aucune demande du client. En dehors du Web, tous les systèmes de messagerie instantanés, par exemple, fonctionnent sur ce principe. Mais de par son côté <i>stateful</i>, le protocole HTTP ne permet pas ce genre de chose. <i><b>Faux !</b></i> me direz-vous. La preuve par Google, ou plutôt Google Mail qui non seulement ne nous oblige pas à reloader sa page pour découvrir de nouveaux messages, mais qui en plus propose un service de messagerie instantanée aussi efficace que n&#8217;importe quel Skype ou MSN ! Et bien malheureusement, c&#8217;est vrai. Et si nous arrivons à faire de la notification via le Web ce n&#8217;est que par le truchement de bidouillages plus ou moins subtils qui vont permettre de le simuler. Depuis plusieurs années, nous désignons les mécanismes permettant de <i>faire du push</i> HTTP sous le terme <a href="http://en.wikipedia.org/wiki/Comet_(programming)">Comet</a>, inventé par <a href="http://alex.dojotoolkit.org/2006/03/comet-low-latency-data-for-the-browser/">Alex Russell</a>.</p>
<h3>Comet</h3>
<p>Comet est une désignation peu claire. En effet, personne ne sait très bien ce que recouvre ce terme. Globalement on lui attribut tous les mécanismes permettant de faire de la notification.</p>
<p>Oui mais comment faire cela justement ?</p>
<p>Dans son fonctionnement classique, un serveur HTTP attend une requête du client et renvoie une réponse :</p>
<p><center><img src="http://www.algorithmique.net/wp-content/uploads/2009/11/ClassicHTTP.png" alt="ClassicHTTP" title="ClassicHTTP" width="463" height="279" class="alignnone size-full wp-image-744" /></center></p>
<p>Avec AJAX, nous avons rajouté, côté client, une couche entre l&#8217;utilisateur et le serveur. C&#8217;est elle qui reçoit les demandes du client, qui les transmet au serveur, qui reçoit la réponse, et elle se charge de mettre à jour la page. Ceci fait que les chargements sur la page ne sont pas forcement synchronisés avec les échanges qui ont lieu entre le moteur AJAX et le serveur : </p>
<p><center><img src="http://www.algorithmique.net/wp-content/uploads/2009/11/AJAXHTTP.png" alt="AJAXHTTP" title="AJAXHTTP" width="464" height="359" class="alignnone size-full wp-image-745" /></center></p>
<p>Cela permet ainsi de mettre à jour des informations dans la page sans tout recharger. Avec AJAX, nous pouvons déjà simuler un comportement de notifications. En effet, il suffit de demander au moteur AJAX d&#8217;envoyer une requête, à intervalle régulier au serveur, et si ce dernier à une nouvelle information, de l&#8217;afficher. Mais ce n&#8217;est pas du Comet. En effet, dans ce cas, ce n&#8217;est pas le serveur qui est à l&#8217;initiative de l&#8217;envoi de données. De plus, l&#8217;envoi de données par le serveur est rythmé par les demandes du client. Et même si elles peuvent être très rapprochées, elles ne donneront pas toujours le même sentiment de fluidité que nous retrouverons avec un Comet bien fait.</p>
<p>Avec Comet, nous allons remplacer le serveur AJAX pas un client Comet qui se placera entre le client et le serveur. Côté serveur, nous allons placer un <i>bus Comet</i> chargé de communiquer avec le <i>service</i> :</p>
<p><center><img src="http://www.algorithmique.net/wp-content/uploads/2009/11/CometHTTP.png" alt="CometHTTP" title="CometHTTP" width="514" height="435" class="alignnone size-full wp-image-746" /></center></p>
<p>Côté client, la connexion Comet est initialisée. A partir de là, le service enverra des évènements au bus Comet qui se chargera d&#8217;envoyer les informations nécessaires au client Comet qui à son tour mettra à jour la page Web. Bien entendu le client peut lui même envoyer de l&#8217;information au service par l&#8217;intermédiaire du client puis du bus Comet. Vous l&#8217;aurez compris, nous utilisons aussi de l&#8217;AJAX. Quant au service, cela peut être <i>n&#8217;importe quoi</i> : un service de messagerie instantané, un serveur de données, &#8230; bref n&#8217;importe quel service capable lui-même de pousser des données.</p>
<h3>Capcode</h3>
<p>Avec <a href="http://github.com/glejeune/Capcode">Capcode</a> nous pouvons <i>faire du Comet</i> en utilisant un middleware <a href="http://rack.rubyforge.org/">Rack</a>. Personnellement j&#8217;en ai trouvé 2 : <a href="http://github.com/macournoyer/pusher/">Pusher</a> et <a href="http://github.com/jcoglan/faye/">faye</a>. Bien qu&#8217;un peu moins aboutit que le premier, je vous propose d&#8217;utiliser <tt>faye</tt>.</p>
<p><tt>faye</tt> arrive avec <a href="http://github.com/jcoglan/faye/tree/master/examples/soapbox/">un exemple</a> sous forme de messagerie instantanée <i>à la Twitter</i>. Pour valider le fonctionnement de <tt>faye</tt> avec <tt>Capcode</tt>, je vous propose d&#8217;adapter cet exemple.</p>
<p><tt>soapbox</tt> est écrit comme une application <a href="http://www.sinatrarb.com/">Sinatra</a>. Le code de l&#8217;application est minimaliste :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'sinatra'</span>
&nbsp;
get <span style="color:#996600;">'/'</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  <span style="color:#0066ff; font-weight:bold;">@server</span> = env<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'faye.server'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  erb <span style="color:#ff3333; font-weight:bold;">:index</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>La seule chose remarquable ici est le fait que lors de l&#8217;accès à la racine de l&#8217;application, le serveur et modifié pour devenir le serveur <tt>faye</tt> et que nous renvoyons la page <tt>index.erb</tt>. Transformer cela en code <tt>Capcode</tt> est ultra simple :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode/render/erb'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> Capcode
  set <span style="color:#ff3333; font-weight:bold;">:erb</span>, <span style="color:#996600;">&quot;views&quot;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> Index <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      <span style="color:#0066ff; font-weight:bold;">@server</span> = env<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'faye.server'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      render <span style="color:#ff3333; font-weight:bold;">:erb</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:index</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Pour respecter ce qui est fait, nous créons un répertoire <tt>views</tt> dans lequel nous placerons les templates <tt>Erb</tt>, tout cela sans oublié de le déclarer (ligne 6).</p>
<p>Si nous regardons maintenant le fichier de configuration pour <tt>Rack</tt>, nous avons cela :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">dir = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">dirname</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">__FILE__</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">require</span> dir <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">'/../../lib/faye'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> dir <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">'/app'</span>
&nbsp;
use <span style="color:#6666ff; font-weight:bold;">Faye::RackAdapter</span>, <span style="color:#ff3333; font-weight:bold;">:mount</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'/comet'</span>
run <span style="color:#6666ff; font-weight:bold;">Sinatra::Application</span></pre></div></div>

<p>Ajouter cela dans <tt>Capcode</tt> est là encore trivial :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode/render/erb'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'faye'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> Capcode
  set <span style="color:#ff3333; font-weight:bold;">:erb</span>, <span style="color:#996600;">&quot;views&quot;</span>
  use <span style="color:#6666ff; font-weight:bold;">Faye::RackAdapter</span>, <span style="color:#ff3333; font-weight:bold;">:mount</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'/comet'</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> Index <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      <span style="color:#0066ff; font-weight:bold;">@server</span> = env<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'faye.server'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      render <span style="color:#ff3333; font-weight:bold;">:erb</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:index</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>  
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Si maintenant nous regardons le template <tt>Erb</tt> nous voyons qu&#8217;il utilise une CSS et trois fichiers JavaScript :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #00bbdd;">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0 Transitional//EN&quot;&gt;</span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;html<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;head<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;meta</span> <span style="color: #000066;">http-equiv</span>=<span style="color: #ff0000;">&quot;Content-type&quot;</span> <span style="color: #000066;">content</span>=<span style="color: #ff0000;">&quot;text/html; charset=utf-8&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Faye demo: chat client<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;link</span> <span style="color: #000066;">rel</span>=<span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;/style.css&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">media</span>=<span style="color: #ff0000;">&quot;screen&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;script</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;/jquery.js&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;script</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;/comet.js&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;script</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;/soapbox.js&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/head<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;container&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
...</pre></div></div>

<p>Les fichiers <tt>style.css</tt>, <tt>jquery.js</tt> et <tt>soapbox.js</tt> se trouvent dans le répertoire <tt>public</tt>. Nous devons donc créer ce même répertoire et déclarer son existence dans <tt>Capcode</tt> :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode/render/erb'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'faye'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> Capcode
  set <span style="color:#ff3333; font-weight:bold;">:erb</span>, <span style="color:#996600;">&quot;views&quot;</span>
  set <span style="color:#ff3333; font-weight:bold;">:static</span>, <span style="color:#996600;">&quot;public&quot;</span>
  use <span style="color:#6666ff; font-weight:bold;">Faye::RackAdapter</span>, <span style="color:#ff3333; font-weight:bold;">:mount</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'/comet'</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> Index <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      <span style="color:#0066ff; font-weight:bold;">@server</span> = env<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'faye.server'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      render <span style="color:#ff3333; font-weight:bold;">:erb</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:index</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>  
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Puis nous modifions le template <tt>Erb</tt> :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #00bbdd;">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0 Transitional//EN&quot;&gt;</span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;html<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;head<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;meta</span> <span style="color: #000066;">http-equiv</span>=<span style="color: #ff0000;">&quot;Content-type&quot;</span> <span style="color: #000066;">content</span>=<span style="color: #ff0000;">&quot;text/html; charset=utf-8&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Faye demo: chat client<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;link</span> <span style="color: #000066;">rel</span>=<span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;/public/style.css&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">media</span>=<span style="color: #ff0000;">&quot;screen&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;script</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;/public/jquery.js&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;script</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;/comet.js&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;script</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;/public/soapbox.js&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/head<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;container&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
...</pre></div></div>

<p>Oui, mais le fichier <tt>comet.js</tt> ??? Et bien si vous regardez la documentation de <tt>faye</tt>, vous verrez que le simple fait de déclarer l&#8217;utilisation du middleware <tt>faye</tt> met automatiquement en place un bus Comet accessible via la route <tt>/comet</tt> et met à disposition la librairie JavaScript cliente via la route <tt>/comet.js</tt>. Donc, nous n&#8217;avons rien de plus à faire pour ce fichier.</p>
<p>Vous pouvez maintenant démarrer l&#8217;application et tester :</p>
<p><center><img src="http://www.algorithmique.net/wp-content/uploads/2009/11/comet-example.png" alt="comet-example" title="comet-example" width="547" height="800" class="alignnone size-full wp-image-758" /></center></p>
<p>Cet exemple a été <a href="http://github.com/glejeune/Capcode/tree/master/examples/soapbox/">ajouté dans les sources de Capcode</a>. </p>
<p>Toute l&#8217;intelligence de l&#8217;exemple se trouve non seulement fans <tt>faye</tt> mais également dans le fichier <tt>soapbox.js</tt> que je vous engage vivement à regarder, tout comme la documentation de <tt>faye</tt>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.algorithmique.net/2009/11/21/notification-comet-capcode/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sequel sans&#8230; séquelle ;)</title>
		<link>http://www.algorithmique.net/2009/11/12/sequel-sans-sequelle/</link>
		<comments>http://www.algorithmique.net/2009/11/12/sequel-sans-sequelle/#comments</comments>
		<pubDate>Thu, 12 Nov 2009 17:37:06 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[Capcode]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Sequel]]></category>

		<guid isPermaLink="false">http://www.algorithmique.net/?p=716</guid>
		<description><![CDATA[Il y a quelques jours, je vous proposais une solution pour utiliser ActiveRecord sans Rails. Comme je vous l&#8217;avais indiqué, cette idée n&#8217;avait pour seul but que de permettre une utilisation d&#8217;Active Record dans Capcode. C&#8217;est maintenant au tour de Sequel&#8230;
Contrairement à ActiveRecord, Sequel n&#8217;a pas été développé pour un framework. Ce n&#8217;est pas non [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.algorithmique.net/wp-content/uploads/2009/08/ruby.png" alt="ruby" title="ruby" width="72" height="72" class="alignleft size-full wp-image-566" />Il y a quelques jours, je vous proposais une solution pour utiliser <a href="http://www.algorithmique.net/2009/11/07/activerecord-sans-rails/">ActiveRecord sans Rails</a>. Comme je vous l&#8217;avais indiqué, cette idée n&#8217;avait pour seul but que de permettre une utilisation d&#8217;Active Record <a href="http://github.com/glejeune/Capcode/blob/master/lib/capcode/base/ar.rb">dans</a> <a href="http://github.com/glejeune/Capcode">Capcode</a>. C&#8217;est maintenant au tour de <a href="http://sequel.rubyforge.org/">Sequel</a>&#8230;</p>
<p>Contrairement à <tt>ActiveRecord</tt>, <tt>Sequel</tt> n&#8217;a pas été développé <i>pour</i> un framework. Ce n&#8217;est pas non plus (<i>initialement</i>) un ORM, mais une librairie d&#8217;accès pour des bases de données, un peu comme <a href="http://ruby-dbi.rubyforge.org/">DBI</a>. Cependant, contrairement à ce dernier, il se rapproche de <tt>DataMapper</tt> ou <tt>ActiveRecord</tt> par sont côté <i>SQL dissimulé</i>. Bref, <tt>Sequel</tt> se situe entre <tt>DBI</tt> et <tt>ActiveRecord</tt>/<tt>DataMapper</tt>.</p>
<p>Voici un petit exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;rubygems&quot;</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;sequel&quot;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Connection à une base SQLite </span>
DB = Sequel.<span style="color:#9900CC;">connect</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;sqlite://test.db&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Création d'une table </span>
DB.<span style="color:#9900CC;">create_table</span> <span style="color:#ff3333; font-weight:bold;">:users</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  primary_key <span style="color:#ff3333; font-weight:bold;">:id</span>
  <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:login</span>
  <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:password</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Ajout de données dans la table</span>
DB<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:users</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">insert</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:login</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Muriel'</span>, <span style="color:#ff3333; font-weight:bold;">:password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'leiruM'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
DB<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:users</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">insert</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:login</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Greg'</span>, <span style="color:#ff3333; font-weight:bold;">:password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'gerG'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Affichage du contenu de la table </span>
DB<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:users</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">all</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>record<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;#{record[:login]} : #{record[:password]}&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>J&#8217;ai dit un peu plus haut que <tt>Sequel</tt> n&#8217;était pas un ORM. Ce n&#8217;est pas tout à fait vrai. En effet, il offre la possibilité d&#8217;être utilisé comme tel :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;rubygems&quot;</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;sequel&quot;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Connection à une base SQLite </span>
DB = Sequel.<span style="color:#9900CC;">connect</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;sqlite://test.db&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Création d'une table </span>
DB.<span style="color:#9900CC;">create_table</span> <span style="color:#ff3333; font-weight:bold;">:users</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  primary_key <span style="color:#ff3333; font-weight:bold;">:id</span>
  <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:login</span>
  <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:password</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Mapping</span>
<span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Sequel::Model</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Ajout de données dans la table</span>
User.<span style="color:#9900CC;">insert</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:login</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Muriel'</span>, <span style="color:#ff3333; font-weight:bold;">:password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'leiruM'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
User.<span style="color:#9900CC;">insert</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:login</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Greg'</span>, <span style="color:#ff3333; font-weight:bold;">:password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'gerG'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Affichage du contenu de la table </span>
User.<span style="color:#9900CC;">all</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>record<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;#{record.login} : #{record.password}&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Bon, mais quel est l&#8217;objectif recherché me demanderez-vous ? Et bien simplement de palier à certains petits défauts de conception qui me dérange dans <tt>Sequel</tt>. </p>
<h3>Déclaration des modèles</h3>
<p>Il est impossible dans <tt>Sequel</tt> de déclarer un modèle si la table correspondante n&#8217;existe pas, ou, tout au moins, si la connexion à la base n&#8217;a pas été faite avant cette déclaration. Ainsi, faire ceci provoque une erreur :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Mapping</span>
<span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Sequel::Model</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Connection à une base SQLite </span>
DB = Sequel.<span style="color:#9900CC;">connect</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;sqlite://test.db&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
DB.<span style="color:#9900CC;">create_table</span> <span style="color:#ff3333; font-weight:bold;">:users</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  primary_key <span style="color:#ff3333; font-weight:bold;">:id</span>
  <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:login</span>
  <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:password</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># =&gt; Sequel::Error: No database associated with Sequel::Model</span></pre></div></div>

<p>Si par contre nous faisons la connexion avant, cela semble fonctionner :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Connection à une base SQLite </span>
DB = Sequel.<span style="color:#9900CC;">connect</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;sqlite://test.db&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Mapping</span>
<span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Sequel::Model</span> <span style="color:#008000; font-style:italic;">#:users</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
DB.<span style="color:#9900CC;">create_table</span> <span style="color:#ff3333; font-weight:bold;">:users</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  primary_key <span style="color:#ff3333; font-weight:bold;">:id</span>
  <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:login</span>
  <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:password</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Je dis bien <i>semble</i>, car en fait le comportement de la classe <tt>User</tt> n&#8217;est pas le même si la table existe avant la déclaration du modèle. Ainsi, si vous faites ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Connection à une base SQLite </span>
DB = Sequel.<span style="color:#9900CC;">connect</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;sqlite://test.db&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
DB.<span style="color:#9900CC;">create_table</span> <span style="color:#ff3333; font-weight:bold;">:users</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  primary_key <span style="color:#ff3333; font-weight:bold;">:id</span>
  <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:login</span>
  <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:password</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Mapping</span>
<span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Sequel::Model</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Vous pourrez utiliser la classe <tt>User</tt> en considérant les champs de la table <tt>users</tt> comme des accesseurs de cette classe :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">User.<span style="color:#9900CC;">all</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>user<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> user.<span style="color:#9900CC;">login</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> user.<span style="color:#9900CC;">password</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Si par contre vous créez la table <i>après</i> avoir déclaré le modèle, votre classe <tt>User</tt> n&#8217;a plus le même comportement et vous devez passer par la méthode <tt>values</tt> de la classe <tt>User</tt> qui renvoie un hashage des données :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Connection à une base SQLite </span>
DB = Sequel.<span style="color:#9900CC;">connect</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;sqlite://test.db&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Mapping</span>
<span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Sequel::Model</span> <span style="color:#008000; font-style:italic;">#:users</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
DB.<span style="color:#9900CC;">create_table</span> <span style="color:#ff3333; font-weight:bold;">:users</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  primary_key <span style="color:#ff3333; font-weight:bold;">:id</span>
  <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:login</span>
  <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:password</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Affichage du contenu de la table </span>
User.<span style="color:#9900CC;">all</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>record<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> record.<span style="color:#9900CC;">values</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:login</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> record.<span style="color:#9900CC;">values</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:password</span><span style="color:#006600; font-weight:bold;">&#93;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Tout cela n&#8217;est pas très <i>rigoureux</i> et pas réellement exploitable.</p>
<h3>Création de table et migration</h3>
<p>Pour la création des tables, là encore j&#8217;ai un problème. En effet, comme vous avez pu le constater, la méthode <tt>create_table</tt> est une méthode d&#8217;instance de <tt>Sequel::Database</tt> récupérée via une connexion (<tt>Sequel.connect</tt>). Ceci implique que nous ne pouvons <i>proposer</i> un schéma de table qu&#8217;après avoir initialisé la connexion à la base. Si cela semble tout à fait logique, cela peut entrainer pas mal de contraintes dans certains cas. <i>Oui, mais pas avec Capcode !</i> Effectivement, les méthodes <tt>Capcode.run</tt> et <tt>Capcode.application</tt> prenant en paramètre un bloc, il est possible de créer les tables dans ce bloc. Cependant, cela rompt avec la philosophie souhaitée pour l&#8217;utilisation de ce bloc<small><sup>1</sup></small> qui veut que l&#8217;on réserve ce bloc pour y placer des éléments de configuration de l&#8217;application (remplissage de table, &#8230;) et non pas du code pour l&#8217;application.</p>
<p>Si vous avez l&#8217;habitude d&#8217;utiliser <tt>ActiveRecord</tt> ou <tt>DataMapper</tt> ce type de problème ne vous aura jamais dérangé parce que dans le premier cas vous utilisez les migrations, et donc vous générez le schéma à priori, et dans le second, le schéma fait partie intégrante du modèle et il est donc créé <i>automatiquement</i><small><sup>2</sup></small>.</p>
<p>Heureusement<small><sup>3</sup></small> <tt>Sequel</tt> offre la possibilité d&#8217;utiliser des <a href="http://sequel.rubyforge.org/rdoc/classes/Sequel/Migration.html">migrations</a>. Pour cela, vous avez plusieurs solutions. Soit définir vos migrations dans des fichiers et utiliser l&#8217;option <tt>-m</tt> de l&#8217;outil <tt>sequel</tt>, soit utiliser la méthode <tt>apply</tt> de <tt>Sequel::Migration</tt>. Grâce à cette dernière possibilité, nous pouvons résoudre le problème évoqué en décrivant le schéma dans une migration et en faisant la migration juste après la connexion :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;rubygems&quot;</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;sequel&quot;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Chargement de l'extension permettant les migrations</span>
Sequel.<span style="color:#9900CC;">extension</span> <span style="color:#ff3333; font-weight:bold;">:migration</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Migration</span>
<span style="color:#9966CC; font-weight:bold;">class</span> CreateUser <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Sequel::Migration</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> up
    create_table <span style="color:#ff3333; font-weight:bold;">:users</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      primary_key <span style="color:#ff3333; font-weight:bold;">:id</span>
      <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:login</span>
      <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:password</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> down
    drop_table <span style="color:#ff3333; font-weight:bold;">:users</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Connection à une base SQLite </span>
DB = Sequel.<span style="color:#9900CC;">connect</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;sqlite://test.db&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Mise en place du schéma</span>
CreateUser.<span style="color:#9900CC;">apply</span><span style="color:#006600; font-weight:bold;">&#40;</span> DB, <span style="color:#ff3333; font-weight:bold;">:up</span> <span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<h3>So what ?</h3>
<p>Avec tout ce que nous venons de voir, nous sommes en mesure de mettre en place une classe mimant ce que nous <a href="http://www.algorithmique.net/2009/11/07/activerecord-sans-rails/">avons fait</a> avec <tt>ActiveRecord</tt> mais pour <tt>Sequel</tt>. Donc nous pouvons repartir d&#8217;un exemple similaire<small><sup>4</sup></small> :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'sq'</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Mise en place des migrations (versionnées)</span>
<span style="color:#9966CC; font-weight:bold;">class</span> CreateUsers <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">SQ::Schema</span> <span style="color:#006666;">1.0</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> up
    create_table <span style="color:#ff3333; font-weight:bold;">:users</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:login</span>
      <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:password</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> down 
    drop_table <span style="color:#ff3333; font-weight:bold;">:users</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> CreatePosts <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">SQ::Schema</span> <span style="color:#006666;">1.1</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> up
    create_table <span style="color:#ff3333; font-weight:bold;">:posts</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:title</span>
      <span style="color:#CC0066; font-weight:bold;">String</span> <span style="color:#ff3333; font-weight:bold;">:body</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> down 
    drop_table <span style="color:#ff3333; font-weight:bold;">:posts</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Création des modèles</span>
<span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">SQ::Model</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Connexion</span>
SQ.<span style="color:#9900CC;">db_connect</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;test.yml&quot;</span>, <span style="color:#996600;">&quot;test.log&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Utilisation</span>
User.<span style="color:#9900CC;">insert</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:login</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Muriel'</span>, <span style="color:#ff3333; font-weight:bold;">:password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'leiruM'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
User.<span style="color:#9900CC;">insert</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:login</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Greg'</span>, <span style="color:#ff3333; font-weight:bold;">:password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'gerG'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
User.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>d<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> u<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:login</span><span style="color:#006600; font-weight:bold;">&#93;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>La mise en place des schémas est quasiment identique à ce que nous avons fait avec <tt>ActiveRecord</tt> et nous allons encore une fois déclarer une méthode de classe qui renverra une classe qui sera, dans le cas présent, de type <tt>Sequel::Migration</tt>. Par la suite, dans la méthode de connexion (<tt>SQ.db_connect</tt>), nous suivrons exactement le même procédé que celui imaginé pour <tt>ActiveRecord</tt>, en s&#8217;adaptant juste au comportement de <tt>Sequel</tt> :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> SQ
  <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#0000FF; font-weight:bold;">self</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> Schema<span style="color:#006600; font-weight:bold;">&#40;</span> n <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@final</span> = <span style="color:#006600; font-weight:bold;">&#91;</span>n, <span style="color:#0066ff; font-weight:bold;">@final</span>.<span style="color:#9900CC;">to_f</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">max</span>
      m = <span style="color:#006600; font-weight:bold;">&#40;</span>@migrations <span style="color:#006600; font-weight:bold;">||</span>= <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">Class</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">Sequel::Migration</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
        meta_def<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> n <span style="color:#006600; font-weight:bold;">&#125;</span>
        meta_def<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:inherited</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>k<span style="color:#006600; font-weight:bold;">|</span> m <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> k <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> db_connect<span style="color:#006600; font-weight:bold;">&#40;</span> dbfile, logfile <span style="color:#006600; font-weight:bold;">&#41;</span>
      dbconfig = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>dbfile<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">keys_to_sym</span>
      dbconfig<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:adapter</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;sqlite&quot;</span> <span style="color:#9966CC; font-weight:bold;">if</span> dbconfig<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:adapter</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#996600;">&quot;sqlite3&quot;</span>
      version = dbconfig.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:schema_version</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>_<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#0066ff; font-weight:bold;">@final</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
      db = Sequel.<span style="color:#9900CC;">connect</span><span style="color:#006600; font-weight:bold;">&#40;</span>@cnx<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@migrations</span>
        db.<span style="color:#9900CC;">create_table</span>? <span style="color:#ff3333; font-weight:bold;">:schema_table</span> <span style="color:#9966CC; font-weight:bold;">do</span>
          <span style="color:#CC0066; font-weight:bold;">Float</span> <span style="color:#ff3333; font-weight:bold;">:version</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
        si = db<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:schema_table</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">first</span> <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#006600; font-weight:bold;">&#40;</span>db<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:schema_table</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">insert</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>; <span style="color:#006600; font-weight:bold;">&#123;</span>:version <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#0066ff; font-weight:bold;">@migrations</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>k<span style="color:#006600; font-weight:bold;">|</span>
          k.<span style="color:#9900CC;">apply</span><span style="color:#006600; font-weight:bold;">&#40;</span>db, <span style="color:#ff3333; font-weight:bold;">:up</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> si<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:version</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&lt;</span> k.<span style="color:#9900CC;">version</span> <span style="color:#9966CC; font-weight:bold;">and</span> k.<span style="color:#9900CC;">version</span> <span style="color:#006600; font-weight:bold;">&lt;</span>= version
          k.<span style="color:#9900CC;">apply</span><span style="color:#006600; font-weight:bold;">&#40;</span>db, <span style="color:#ff3333; font-weight:bold;">:down</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> si<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:version</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&gt;</span>= k.<span style="color:#9900CC;">version</span> <span style="color:#9966CC; font-weight:bold;">and</span> k.<span style="color:#9900CC;">version</span> <span style="color:#006600; font-weight:bold;">&gt;</span> version
        <span style="color:#9966CC; font-weight:bold;">end</span>
        db<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:schema_table</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">where</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> si<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:version</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">update</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> version<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Nous allons cependant devoir faire quelques adaptations mineures dans ce code pour régler le cas des modèles. Il n&#8217;est en effet pas possible d&#8217;utiliser les modèles proposés par <tt>Sequel</tt>, mais ceci ne nous empêche pas de les mimer. Pour cela nous allons créer de toutes pièces la classe <tt>SQ::Model</tt> et nous ferons en sorte qu&#8217;elle réponde, via ses méthodes de classe, aux mêmes méthodes que <a href="http://sequel.rubyforge.org/rdoc/classes/Sequel/Dataset.html">Sequel::Dataset</a>. Par example la classe <tt>User</tt> répondra aux même méthodes que DB[:users]. Or <tt>:users == User.to_s.tableize.to_sym</tt>, ce qui rende la mise en place de la classe <tt>SQ::Model</tt> extrêmement simple :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> SQ
  <span style="color:#9966CC; font-weight:bold;">class</span> Model
    <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">method_missing</span><span style="color:#006600; font-weight:bold;">&#40;</span> name, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>block <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> block_given?
        SQ::db<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">to_s</span>.<span style="color:#9900CC;">tableize</span>.<span style="color:#9900CC;">to_sym</span><span style="color:#006600; font-weight:bold;">&#93;</span>.__send__<span style="color:#006600; font-weight:bold;">&#40;</span>name.<span style="color:#9900CC;">to_sym</span>, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        SQ::db<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">to_s</span>.<span style="color:#9900CC;">tableize</span>.<span style="color:#9900CC;">to_sym</span><span style="color:#006600; font-weight:bold;">&#93;</span>.__send__<span style="color:#006600; font-weight:bold;">&#40;</span>name.<span style="color:#9900CC;">to_sym</span>, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Le seul élément vraiment remarquable dans ce code est l&#8217;utilisation de <tt>SQ::db</tt> sensé représenter la connexion. Et c&#8217;est là que nous devons modifier le code de la partie schéma pour permettre de partager la connexion au sein du module <tt>SQ</tt>. Pour cela nous mettons en place la méthode suivante :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> SQ
  <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#0000FF; font-weight:bold;">self</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> db
      <span style="color:#0066ff; font-weight:bold;">@db</span> <span style="color:#006600; font-weight:bold;">||</span>= Sequel.<span style="color:#9900CC;">connect</span><span style="color:#006600; font-weight:bold;">&#40;</span>@dbconfig<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Puis nous supprimons la ligne <tt>db = Sequel.connect(@cnx)</tt> dans <tt>SQ::db_connect</tt>, nous remplaçons partout l&#8217;utilisation de la variable <tt>db</tt> par <tt>SQ::db</tt> et nous modifions la variable <tt> dbconfig</tt> en la passant en variable d&#8217;instance. Finalement, le code complet est le suivant :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">begin</span>
  <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'sequel'</span>
  Sequel.<span style="color:#9900CC;">extension</span> <span style="color:#ff3333; font-weight:bold;">:migration</span>
  Sequel.<span style="color:#9900CC;">extension</span> <span style="color:#ff3333; font-weight:bold;">:inflector</span>
<span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">LoadError</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e
  <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">LoadError</span>, <span style="color:#996600;">&quot;Sequel ne doit pas être installé : #{e.message}&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC00FF; font-weight:bold;">Object</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> meta_def<span style="color:#006600; font-weight:bold;">&#40;</span>m,<span style="color:#006600; font-weight:bold;">&amp;</span>b<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#006600; font-weight:bold;">&#40;</span>class<span style="color:#006600; font-weight:bold;">&lt;&lt;</span>self;self <span style="color:#9966CC; font-weight:bold;">end</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:define_method</span>,m,<span style="color:#006600; font-weight:bold;">&amp;</span>b<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC00FF; font-weight:bold;">Hash</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> keys_to_sym
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>k, v<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span>k<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">self</span><span style="color:#006600; font-weight:bold;">&#91;</span>k.<span style="color:#9900CC;">to_s</span>.<span style="color:#9900CC;">to_sym</span><span style="color:#006600; font-weight:bold;">&#93;</span> = v
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> SQ
  <span style="color:#9966CC; font-weight:bold;">class</span> Model
    <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">method_missing</span><span style="color:#006600; font-weight:bold;">&#40;</span> name, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>block <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> block_given?
        SQ::db<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">to_s</span>.<span style="color:#9900CC;">tableize</span>.<span style="color:#9900CC;">to_sym</span><span style="color:#006600; font-weight:bold;">&#93;</span>.__send__<span style="color:#006600; font-weight:bold;">&#40;</span>name.<span style="color:#9900CC;">to_sym</span>, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        SQ::db<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">to_s</span>.<span style="color:#9900CC;">tableize</span>.<span style="color:#9900CC;">to_sym</span><span style="color:#006600; font-weight:bold;">&#93;</span>.__send__<span style="color:#006600; font-weight:bold;">&#40;</span>name.<span style="color:#9900CC;">to_sym</span>, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#0000FF; font-weight:bold;">self</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> db
      <span style="color:#0066ff; font-weight:bold;">@db</span> <span style="color:#006600; font-weight:bold;">||</span>= Sequel.<span style="color:#9900CC;">connect</span><span style="color:#006600; font-weight:bold;">&#40;</span>@dbconfig<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> Schema<span style="color:#006600; font-weight:bold;">&#40;</span> n <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@final</span> = <span style="color:#006600; font-weight:bold;">&#91;</span>n, <span style="color:#0066ff; font-weight:bold;">@final</span>.<span style="color:#9900CC;">to_f</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">max</span>
      m = <span style="color:#006600; font-weight:bold;">&#40;</span>@migrations <span style="color:#006600; font-weight:bold;">||</span>= <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">Class</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">Sequel::Migration</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
        meta_def<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> n <span style="color:#006600; font-weight:bold;">&#125;</span>
        meta_def<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:inherited</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>k<span style="color:#006600; font-weight:bold;">|</span> m <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> k <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> db_connect<span style="color:#006600; font-weight:bold;">&#40;</span> dbfile, logfile <span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@dbconfig</span> = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>dbfile<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">keys_to_sym</span>
      <span style="color:#0066ff; font-weight:bold;">@dbconfig</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:adapter</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;sqlite&quot;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@dbconfig</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:adapter</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#996600;">&quot;sqlite3&quot;</span>
      version = dbconfig.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:schema_version</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>_<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#0066ff; font-weight:bold;">@final</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@migrations</span>
        SQ::db.<span style="color:#9900CC;">create_table</span>? <span style="color:#ff3333; font-weight:bold;">:schema_table</span> <span style="color:#9966CC; font-weight:bold;">do</span>
          <span style="color:#CC0066; font-weight:bold;">Float</span> <span style="color:#ff3333; font-weight:bold;">:version</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
        si = SQ::db<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:schema_table</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">first</span> <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#006600; font-weight:bold;">&#40;</span>SQ::db<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:schema_table</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">insert</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>; <span style="color:#006600; font-weight:bold;">&#123;</span>:version <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#0066ff; font-weight:bold;">@migrations</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>k<span style="color:#006600; font-weight:bold;">|</span>
          k.<span style="color:#9900CC;">apply</span><span style="color:#006600; font-weight:bold;">&#40;</span>SQ::db, <span style="color:#ff3333; font-weight:bold;">:up</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> si<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:version</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&lt;</span> k.<span style="color:#9900CC;">version</span> <span style="color:#9966CC; font-weight:bold;">and</span> k.<span style="color:#9900CC;">version</span> <span style="color:#006600; font-weight:bold;">&lt;</span>= version
          k.<span style="color:#9900CC;">apply</span><span style="color:#006600; font-weight:bold;">&#40;</span>SQ::db, <span style="color:#ff3333; font-weight:bold;">:down</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> si<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:version</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&gt;</span>= k.<span style="color:#9900CC;">version</span> <span style="color:#9966CC; font-weight:bold;">and</span> k.<span style="color:#9900CC;">version</span> <span style="color:#006600; font-weight:bold;">&gt;</span> version
        <span style="color:#9966CC; font-weight:bold;">end</span>
        SQ::db<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:schema_table</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">where</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> si<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:version</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">update</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> version<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Notez que nous utilisons l&#8217;extension <tt>inflector</tt> afin de pouvoir utiliser la méthode <tt>String.tableize</tt> et que nous prenons en compte (ligne 51) le fait que <tt>Sequel</tt> permet d&#8217;utiliser SQLite en nommant sont adaptateur <tt>sqlite</tt> là ou les <i>autres</i> utilisent <tt>sqlite3</tt>.</p>
<p>Voilà, tout ceci a été <a href="http://github.com/glejeune/Capcode/blob/master/lib/capcode/base/sq.rb">mis en place</a> dans <tt>Capcode</tt> et un <a href="http://github.com/glejeune/Capcode/blob/master/examples/blog-sq.rb">petit example</a> illustre comment l&#8217;utiliser.</p>
<p><small><sup>1</sup> Laquelle ?</small><br />
<small><sup>2</sup> Tout ceci est extrêmement schématique, je sais, mais je ne m&#8217;étendrais pas plus sur le sujet.</small><br />
<small><sup>3</sup> Faudrait savoir ! Un coup on aime, un coup on aime pas les migrations !</small><br />
<small><sup>4</sup> Pour des questions de bonne compréhension, nous placerons notre code dans le module <tt>SQ</tt> là ou nous utilisions <tt>AR</tt>&#8230;</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.algorithmique.net/2009/11/12/sequel-sans-sequelle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Happy happymapper</title>
		<link>http://www.algorithmique.net/2009/11/09/happy-happymapper/</link>
		<comments>http://www.algorithmique.net/2009/11/09/happy-happymapper/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 20:01:04 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[HappyMapper]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Vidal]]></category>

		<guid isPermaLink="false">http://www.algorithmique.net/?p=700</guid>
		<description><![CDATA[Si vous suivez ce blog, vous savez que je travaille1 depuis plusieurs mois sur un outil permettant de montrer la puissance des APIs développées dans la boite dans laquelle je travaille. L&#8217;outil en question, outre sont côté fonctionnel spécifique, présente la particularité de fonctionner avec l&#8217;ensemble des bases de données médicamenteuses proposées par VIDAL. J&#8217;entends [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.algorithmique.net/wp-content/uploads/2009/09/dev.png" alt="dev" title="dev" width="72" height="72" class="alignleft size-full wp-image-562" />Si vous suivez ce blog, vous savez que je <a href="http://www.algorithmique.net/2009/04/10/cappuccino-capcode-vidal/">travaille</a><small><sup>1</sup></small> depuis plusieurs mois sur un outil permettant de montrer la puissance des APIs développées dans la <a href="http://www.vidal.fr">boite</a> dans laquelle je travaille. L&#8217;outil en question, outre sont côté fonctionnel spécifique, présente la particularité de fonctionner avec l&#8217;ensemble des bases de données médicamenteuses proposées par VIDAL. J&#8217;entends par là le fait que les données étant diffusées à <a href="http://www.vidal.fr/actualites/44-cap-a-linternational">l&#8217;international</a>, il existe, non seulement une version Française, mais également une version pour les Emirats Arabes Unis, pour l&#8217;Espagne, le Portugal, &#8230; Et alors ?</p>
<p>Et alors, ce besoin a des impacts non négligeables sur le développement de certaines fonctions. Je ne vais pas entrer dans les détails de la sécurisation d&#8217;une prescription, mais juste vous dire que pour la prise en compte de l&#8217;état pathologique d&#8217;un patient, nous codons cet état via la <a href="http://fr.wikipedia.org/wiki/Classification_internationale_des_maladies">CIM</a>. Or l&#8217;utilisation de cette classification, et plus fortement sa diffusion, est soumise à une licence payante pour chaque pays. Or VIDAL n&#8217;ayant acquis qu&#8217;une licence pour la France, les versions internationales de la base n&#8217;intègrent pas les libellés de la CIM. Tout mon problème était de savoir comment permettre de travailler avec ces libellés quand la démo se fait à l&#8217;international ? Plus précisément, comment faire en sorte qu&#8217;une personne ayant acquis la licence puisse utiliser mon outil avec <i>sa</i> CIM.</p>
<p>Initialement, j&#8217;avais opté pour une solution consistant à déporter la classification dans une base <a href="http://www.sqlite.org/">SQLite</a> ne contenant qu&#8217;une seule table avec trois colonnes :</p>
<p><center><img src="http://www.algorithmique.net/wp-content/uploads/2009/11/cim10.png" alt="cim10" title="cim10" width="99" height="99" class="aligncenter size-full wp-image-705" /></center></p>
<p>Par défaut cette base ne contenait que les codes CIM sans les libellés. Il suffisait, localement, de remplacer le fichier SQLite pour pouvoir accéder aux libellés.</p>
<p>Tout cela était sans compter sur le fait que les personnes qui ont besoin de cet outil ont souvent une approche technique proche de l&#8217;état larvaire, et que leur demander de créer un fichier SQLite, aussi simple soit-il, tient du roman de science-fiction chez certains<small><sup>2</sup></small>. J&#8217;ai donc dû chercher du côté des outils plus <i>classiques</i> de cette population chez qui Excel est un prolongement synaptique. J&#8217;ai alors découvert que ce merveilleux outil est <a href="http://dj.joss.free.fr/xml.htm">capable de générer des fichiers XML</a>. Sauvé<small><sup>3</sup></small> !</p>
<p>Maintenant que nous savons que nous pouvons utiliser du XML, un simple fichier formaté comme ce qui suit suffit :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;cims<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;cim10<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>A00.-<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;parent<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/parent<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;label<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Cholera<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/label<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/cim10<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;cim10<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>A00.0<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;parent<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>A00.-<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/parent<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;label<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Choléra classique<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/label<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/cim10<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
  ...
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/cims<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Parcourir un fichier XML est une chose relativement facile avec Ruby. Il existe un grand nombre de modules pour nous y aider. Dans le cas présent, j&#8217;ai choisis <a href="http://github.com/jnunemaker/happymapper">HappyMapper</a>. Ce dernier permet mapper du XML dans des objets. Ainsi, avec le fichier XML des codes CIM, il suffit de créer l&#8217;objet suivant :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Cim10
  <span style="color:#9966CC; font-weight:bold;">include</span> HappyMapper
&nbsp;
  element <span style="color:#ff3333; font-weight:bold;">:code</span>, <span style="color:#CC0066; font-weight:bold;">String</span>
  element <span style="color:#ff3333; font-weight:bold;">:parent</span>, <span style="color:#CC0066; font-weight:bold;">String</span>
  element <span style="color:#ff3333; font-weight:bold;">:label</span>, <span style="color:#CC0066; font-weight:bold;">String</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Si ensuite nous parsons le contenu du fichier XML (via <tt>Cim10.parser</tt> nous obtenons un tableau d&#8217;objets <tt>Cim10</tt> :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">cims = Cim10.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;cim10-fr.xml&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Tout le problème maintenant c&#8217;est de pouvoir faire des recherches dans ce tableau. Pour cela je me suis amusé à transformer le tableau de sortie en utilisant une nouvelle classe : <tt>HappyArray</tt> :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;rubygems&quot;</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;active_record/dynamic_finder_match&quot;</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> HappyArray <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC0066; font-weight:bold;">Array</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> find<span style="color:#006600; font-weight:bold;">&#40;</span> h <span style="color:#006600; font-weight:bold;">&#41;</span>
    r = HappyArray.<span style="color:#9900CC;">new</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>cim<span style="color:#006600; font-weight:bold;">|</span>
      keep = <span style="color:#0000FF; font-weight:bold;">true</span>
      h.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>k, v<span style="color:#006600; font-weight:bold;">|</span>
        term = v
        term = v.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'|'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> v.<span style="color:#9966CC; font-weight:bold;">class</span> == <span style="color:#CC0066; font-weight:bold;">Array</span>
        keep = keep <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> !<span style="color:#006600; font-weight:bold;">&#40;</span>cim.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span>k<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">downcase</span>.<span style="color:#9900CC;">match</span><span style="color:#006600; font-weight:bold;">&#40;</span>term.<span style="color:#9900CC;">downcase</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>?<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
      r <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> cim <span style="color:#9966CC; font-weight:bold;">if</span> keep
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> r
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> method_missing<span style="color:#006600; font-weight:bold;">&#40;</span>method_name, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> match = <span style="color:#6666ff; font-weight:bold;">ActiveRecord::DynamicFinderMatch</span>.<span style="color:#9900CC;">match</span><span style="color:#006600; font-weight:bold;">&#40;</span> method_name <span style="color:#006600; font-weight:bold;">&#41;</span>
      finder = <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
      match.<span style="color:#9900CC;">attribute_names</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span>
        finder<span style="color:#006600; font-weight:bold;">&#91;</span>f.<span style="color:#9900CC;">to_sym</span><span style="color:#006600; font-weight:bold;">&#93;</span> = args.<span style="color:#9900CC;">shift</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> find<span style="color:#006600; font-weight:bold;">&#40;</span> finder <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> HappyMapper.<span style="color:#9900CC;">new</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Cette classe me permet ainsi de faire ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">cims = Cim10.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;cim10-fr.xml&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
happyCims = HappyArray.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>cims<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
results = happyCims.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:label</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;choléra&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#008000; font-style:italic;"># =&gt; Tableau des objets Cim10 dont le libellé contient le terme &quot;choléra&quot;</span>
&nbsp;
results = happyCims.<span style="color:#9900CC;">find_by_label_and_code</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;choléra&quot;</span>, <span style="color:#996600;">&quot;vaccin&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#996600;">&quot;A00&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#008000; font-style:italic;"># =&gt; Tableau des objets Cim10 dont le libellé contient &quot;choléra&quot; ou &quot;vaccin&quot; et dont le code contient &quot;A00&quot;</span></pre></div></div>

<p>Je n&#8217;ai pas voulu ajouter les méthodes de la classe <tt>HappyArray</tt> à la classe <tt>Array</tt> car finalement elles ne peuvent servir que dans le cas d&#8217;une utilisation avec <tt>HappyMapper</tt>. La question maintenant c&#8217;est de savoir si je sécurise un peu ce code et le propose comme patch pour <tt>HappyMapper</tt> ou pas ?</p>
<p><small><sup>1</sup> Vous pouvez aussi regarder <a href="http://www.algorithmique.net/2009/09/18/carte-heuristique-et-base-de-donnees/">ceci</a> ;)</small><br />
<small><sup>2</sup> <a href="http://www.algorithmique.net/2009/10/06/semaine-23/">Suivez mon regard&#8230;</a></small><br />
<small><sup>3</sup> Enfin presque&#8230; Le problème, maintenant, va être d&#8217;expliquer comment faire :(</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.algorithmique.net/2009/11/09/happy-happymapper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ActiveRecord sans Rails</title>
		<link>http://www.algorithmique.net/2009/11/07/activerecord-sans-rails/</link>
		<comments>http://www.algorithmique.net/2009/11/07/activerecord-sans-rails/#comments</comments>
		<pubDate>Sat, 07 Nov 2009 10:23:00 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Dev]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Capcode]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.algorithmique.net/?p=678</guid>
		<description><![CDATA[Si vous recherchez sur Google comment utiliser ActiveRecord sans Rails, vous verrez qu&#8217;il existe pas mal de pages sur le sujet. Le problème est que l&#8217;on vous y raconte toujours la même histoire, à savoir comment établir une connexion vers une base existante. Quant à savoir comment créer le schéma de la base, c&#8217;est une [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.algorithmique.net/wp-content/uploads/2009/08/ruby.png" alt="ruby" title="ruby" width="72" height="72" class="alignleft size-full wp-image-566" />Si vous recherchez sur Google comment utiliser <a href="http://www.google.com/search?client=safari&#038;rls=en&#038;q=activerecord+without+rails&#038;ie=UTF-8&#038;oe=UTF-8">ActiveRecord sans Rails</a>, vous verrez qu&#8217;il existe pas mal de pages sur le sujet. Le problème est que l&#8217;on vous y raconte toujours la même histoire, à savoir comment établir une connexion vers une base existante. Quant à savoir comment créer le schéma de la base, c&#8217;est une autre histoire. Là encore, Google nous permet de trouver <a href="http://www.google.com/search?client=safari&#038;rls=en&#038;q=activerecord+migration+without+rails&#038;ie=UTF-8&#038;oe=UTF-8">quelques pistes</a>, mais rien de bien satisfaisant. A part peut-être le <a href="http://blog.aizatto.com/2007/05/27/activerecord-migrations-without-rails/">premier résultat</a> qui propose d&#8217;utiliser les migrations dans des fichiers séparés, un Rakefile, bref une artillerie un peu lourde<small><sup>1</sup></small>. Voyons comment faire <i>plus simple</i>.</p>
<h3>ActiveRecord</h3>
<p>Pour utiliser <tt>ActiveRecord</tt> nous avons besoin d&#8217;au moins<small><sup>2</sup></small> deux choses : un schéma et un modèle. En général les schémas sont mis en place via les <a href="http://v-dubois.developpez.com/ruby-on-rails/active-record-migrations/">migrations</a>. Pour cela, Rails créés dans le répertoire <tt>db/migrate</tt> des fichiers définissant des classes héritant de <tt>ActiveRecord::Migration</tt>. Les modèles sont, eux, placés dans le répertoire <tt>app/models</tt> de l&#8217;application Rails. Ils définissent des classes héritant d&#8217;<tt>ActiveRecord::Base</tt>. En général, modèles et migrations sont créés <i>en même temps</i>. Quand vous créez un modèle, Rails génère en même temps une migration :</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">$ ruby script/generate model user
      exists  app/models/
      exists  test/unit/
      exists  test/fixtures/
      create  app/models/user.rb
      create  test/unit/user_test.rb
      create  test/fixtures/users.yml
      create  db/migrate
      create  db/migrate/20091106191317_create_users.rb
$</pre></div></div>

<p>Le fichier de migration ainsi généré contiendra le code suivant :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> CreateUsers <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">up</span>
    create_table <span style="color:#ff3333; font-weight:bold;">:users</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span>
&nbsp;
      t.<span style="color:#9900CC;">timestamps</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">down</span>
    drop_table <span style="color:#ff3333; font-weight:bold;">:users</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Le fichier du modèle sera lui beaucoup plus court :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Si nous voulons utiliser notre modèle, il faut maintenant faire deux petites choses.</p>
<p><b>1. Compléter le schéma</b></p>
<p>En fait de schéma, c&#8217;est bien au fichier de migration que je pense. En effet, pour le moment notre table <tt>users</tt> ne contient que les champs de <tt>timestamps</tt>, et il faut donc y ajouter les champs permettant de définir un utilisateur.</p>
<p><b>2. Faire la migration</b></p>
<p>Pour cela il faut lancer un <tt>rake db:migrate</tt></p>
<p>Une fois cela fait, nous pouvons utiliser le modèle <tt>User</tt> dans nos contrôleurs.</p>
<p>Comme vous avez dû le comprendre au début de ce post, je trouve tout cela un peu lourd. Non seulement il faut, exploser les choses en une multitude de fichiers, mais il faut en plus un <tt>Rackfile</tt>. En ce qui me concerne j&#8217;aimerai pouvoir lancer une application Ruby utilisant <tt>ActiveRecord</tt>, que la base soit créée (ou mise à jour) s&#8217;il y a besoin, et tout cela, en ayant la possibilité de tout mettre dans un seul fichier&#8230; Bref, idéalement je voudrais pouvoir faire cela :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'active_record'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> DBSchema <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">up</span>
    create_table <span style="color:#ff3333; font-weight:bold;">:users</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span>
      t.<span style="color:#CC0066; font-weight:bold;">string</span> <span style="color:#ff3333; font-weight:bold;">:login</span>
      t.<span style="color:#CC0066; font-weight:bold;">string</span> <span style="color:#ff3333; font-weight:bold;">:password</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">down</span> 
    drop_table <span style="color:#ff3333; font-weight:bold;">:users</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">establish_connection</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;test.yml&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
User.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:login</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Muriel&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;leiruM&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">save</span>
User.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:login</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Greg&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;gerG&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">save</span>
&nbsp;
User.<span style="color:#9900CC;">all</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>u<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> u.<span style="color:#9900CC;">login</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#008000; font-style:italic;"># =&gt; Muriel</span>
<span style="color:#008000; font-style:italic;"># =&gt; Greg</span></pre></div></div>

<p>Malheureusement, ce n&#8217;est pas possible<small><sup>3</sup></small>. J&#8217;ai donc développé une petite surcouche permettant de faire ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'ar'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> DBSchema <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">AR::Schema</span> <span style="color:#006666;">1.0</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">up</span>
    create_table <span style="color:#ff3333; font-weight:bold;">:users</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span>
      t.<span style="color:#CC0066; font-weight:bold;">string</span> <span style="color:#ff3333; font-weight:bold;">:login</span>
      t.<span style="color:#CC0066; font-weight:bold;">string</span> <span style="color:#ff3333; font-weight:bold;">:password</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">down</span> 
    drop_table <span style="color:#ff3333; font-weight:bold;">:users</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">AR::Model</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
AR.<span style="color:#9900CC;">db_connect</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;test.yml&quot;</span>, <span style="color:#996600;">&quot;test.log&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
User.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:login</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Muriel&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;leiruM&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">save</span>
User.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:login</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Greg&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;gerG&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">save</span>
&nbsp;
User.<span style="color:#9900CC;">all</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>u<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> u.<span style="color:#9900CC;">login</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#008000; font-style:italic;"># =&gt; Muriel</span>
<span style="color:#008000; font-style:italic;"># =&gt; Greg</span></pre></div></div>

<h3>Création du schéma</h3>
<p>Comme vous pouvez le voir, je n&#8217;utilise pas <tt>ActiveRecord::Migration</tt> mais <tt>AR::Schema</tt>, ce qui semble plus logique puisqu&#8217;il s&#8217;agit bien de définir un schéma de base. Notez que ce schéma est défini avec un numéro de version<small><sup>4</sup></small>. Pour faire cela, nous allons faire un peu de <a href="http://fr.wikipedia.org/wiki/Métaprogrammation">métaprogrammation</a>. Dans les faits, <tt>AR::Schema</tt> n&#8217;est pas un classe, mais une méthode de classe qui renvoie une classe de type <tt>ActiveRecord::Migration</tt> :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> AR
  <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">Schema</span><span style="color:#006600; font-weight:bold;">&#40;</span> n <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@final</span> = <span style="color:#006600; font-weight:bold;">&#91;</span>n, <span style="color:#0066ff; font-weight:bold;">@final</span>.<span style="color:#9900CC;">to_f</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">max</span>
    m = <span style="color:#006600; font-weight:bold;">&#40;</span>@migrations <span style="color:#006600; font-weight:bold;">||</span>= <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">Class</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      meta_def<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> n <span style="color:#006600; font-weight:bold;">&#125;</span>
      meta_def<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:inherited</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>k<span style="color:#006600; font-weight:bold;">|</span> m <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> k <span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># ...</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Dans la classe de type <tt>ActiveRecord::Migration</tt> que nous renvoyons, nous définissons deux méthodes de classes : <tt>version</tt> et <tt>inherited</tt>. La première sert à stocker la version du schéma. La seconde est utilisée pour mettre à jour la liste des classes de migration définies. Ainsi si nous reprenons l&#8217;exemple ci-dessus :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> DBSchema <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">AR::Schema</span> <span style="color:#006666;">1.0</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">up</span>
    create_table <span style="color:#ff3333; font-weight:bold;">:users</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span>
      t.<span style="color:#CC0066; font-weight:bold;">string</span> <span style="color:#ff3333; font-weight:bold;">:login</span>
      t.<span style="color:#CC0066; font-weight:bold;">string</span> <span style="color:#ff3333; font-weight:bold;">:password</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">down</span> 
    drop_table <span style="color:#ff3333; font-weight:bold;">:users</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Dans <tt>AR</tt>, la variable <tt>@migrations</tt> sera égale à <tt>[DBSchema]</tt>, <tt>@final</tt> sera égale à <tt>1.0</tt> et <tt>DBSchema.version</tt> sera égal à <tt>1.0</tt>. Nous reviendrons plus tard sur l&#8217;intérêt de la variable <tt>@final</tt>.</p>
<h3>Création du modèle</h3>
<p>Là où nous avons l&#8217;habitude d&#8217;utiliser <tt>ActiveRecord::Base</tt>, je propose <tt>AR::Model</tt>. Là encore, ce n&#8217;est qu&#8217;une question de <i>logique</i> puisque nous définissons bien un modèle.</p>
<p>La mise en place d&#8217;<tt>AR::Model</tt> est on ne peut plus simple :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> AR
  Model = <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  <span style="color:#008000; font-style:italic;"># ...</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3>Connexion et Migration</h3>
<p>Il ne reste plus qu&#8217;à définir la méthode <tt>AR.db_connect</tt>. Dans cette méthode, nous devons faire deux choses : créer la connexion puis appliquer les migrations.</p>
<p>La première partie est relativement simple et passe par l&#8217;utilisation d&#8217;<tt>ActiveRecord::Base.establish_connection</tt>. </p>
<p>Pour la gestion des migrations, nous avons un peu plus de travail. En effet, pour savoir si une migration s&#8217;applique (et dans quel sens (<tt>up</tt> ou <tt>down</tt>), nous devons savoir quelle version du schéma existe (s&#8217;il existe). Si vous regardez comment Rails gère cela, vous verrez que dans la base de vos applications se trouve une table <tt>schema_migrations</tt> contenant le préfixe (format <tt>AAAAMMJJHHMMSS</tt>) du fichier de migration le plus proche dans le temps. Nous allons utiliser la même méthode, mais comme nous avons pris le parti de passer un numéro de version à nos schémas, ce sont ces derniers que nous allons utiliser. </p>
<p>Nous devons donc créer un modèle (<tt>SchemaInfo</tt>) qui nous servira à gérer cette version, avec la table correspondante dans la base. <tt>ActiveRecord</tt> ne supportant pas de devoir créer une table si elle existe déjà, nous commencerons par vérifier sa présence :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> AR
  <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> SchemaInfo <span style="color:#006600; font-weight:bold;">&lt;</span> Model
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#0000FF; font-weight:bold;">self</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> db_connect<span style="color:#006600; font-weight:bold;">&#40;</span> dbfile, logfile <span style="color:#006600; font-weight:bold;">&#41;</span>
      dbconfig = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>dbfile<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">keys_to_sym</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
      <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">establish_connection</span><span style="color:#006600; font-weight:bold;">&#40;</span>dbconfig<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">logger</span> = <span style="color:#CC00FF; font-weight:bold;">Logger</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>logfile<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@migrations</span>
        <span style="color:#9966CC; font-weight:bold;">unless</span> SchemaInfo.<span style="color:#9900CC;">table_exists</span>?
          <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Schema</span>.<span style="color:#9900CC;">define</span> <span style="color:#9966CC; font-weight:bold;">do</span>
            create_table SchemaInfo.<span style="color:#9900CC;">table_name</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span>
              t.<span style="color:#9900CC;">column</span> <span style="color:#ff3333; font-weight:bold;">:version</span>, <span style="color:#ff3333; font-weight:bold;">:float</span>
            <span style="color:#9966CC; font-weight:bold;">end</span>
          <span style="color:#9966CC; font-weight:bold;">end</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
        <span style="color:#008000; font-style:italic;"># ...</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Ceci étant, nous pouvons maintenant jouer avec les numéros de version. Cependant, pour pouvoir gérer pleinement<br />
 les migrations il peut être utile de préciser quelle version de schéma nous voulons utiliser. Par défaut, nous partirons du principe que c&#8217;est le schéma de plus haute version qui sera pris en compte, mais nous devons permettre de préciser la version du schéma à utiliser. Pour cela je vous propose de rajouter cette information dans le fichier de configuration de la base en y ajoutant l&#8217;item <tt>schema_version</tt> :</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">adapter: sqlite3
database: test.db
schema_version: 1.0</pre></div></div>

<p>Nous pouvons maintenant récupérer ce numéro de version dans <tt>AR.db_connect</tt> :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> AR
&nbsp;
  <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#0000FF; font-weight:bold;">self</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> db_connect<span style="color:#006600; font-weight:bold;">&#40;</span> dbfile, logfile <span style="color:#006600; font-weight:bold;">&#41;</span>
      dbconfig = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>dbfile<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">keys_to_sym</span>
      version = dbconfig.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:schema_version</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>_<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#0066ff; font-weight:bold;">@final</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Il ne reste plus qu&#8217;à lancer les migrations en fonction de la version. Ainsi, pour chaque schéma, si la version du schéma existant est inférieure à la version du schéma courant et que la version du schéma courant et inférieure ou égale à la version souhaitée, alors nous migrons vers le haut (<tt>up</tt>). Si la version du schéma existant est supérieure ou égale à la version du schéma courant et que la version du schéma courant est supérieure à la version du schéma souhaité, alors nous migrons vers le bas (<tt>down</tt>). Sinon, on ne fait rien.</p>
<p>Bien entendu, il ne faudra pas oublier de modifier la version du schéma dans la table d&#8217;information sur le schéma.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> AR
&nbsp;
  <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#0000FF; font-weight:bold;">self</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> db_connect<span style="color:#006600; font-weight:bold;">&#40;</span> dbfile, logfile <span style="color:#006600; font-weight:bold;">&#41;</span>
      dbconfig = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>dbfile<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">keys_to_sym</span>
      version = dbconfig.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:schema_version</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>_<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#0066ff; font-weight:bold;">@final</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
      <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">establish_connection</span><span style="color:#006600; font-weight:bold;">&#40;</span>dbconfig<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">logger</span> = <span style="color:#CC00FF; font-weight:bold;">Logger</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>logfile<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@migrations</span>
        <span style="color:#9966CC; font-weight:bold;">unless</span> SchemaInfo.<span style="color:#9900CC;">table_exists</span>?
          <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Schema</span>.<span style="color:#9900CC;">define</span> <span style="color:#9966CC; font-weight:bold;">do</span>
            create_table SchemaInfo.<span style="color:#9900CC;">table_name</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span>
              t.<span style="color:#9900CC;">column</span> <span style="color:#ff3333; font-weight:bold;">:version</span>, <span style="color:#ff3333; font-weight:bold;">:float</span>
            <span style="color:#9966CC; font-weight:bold;">end</span>
          <span style="color:#9966CC; font-weight:bold;">end</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
        si = SchemaInfo.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:first</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">||</span> SchemaInfo.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#0066ff; font-weight:bold;">@migrations</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>k<span style="color:#006600; font-weight:bold;">|</span>
          k.<span style="color:#9900CC;">migrate</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:up</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> si.<span style="color:#9900CC;">version</span> <span style="color:#006600; font-weight:bold;">&lt;</span> k.<span style="color:#9900CC;">version</span> <span style="color:#9966CC; font-weight:bold;">and</span> k.<span style="color:#9900CC;">version</span> <span style="color:#006600; font-weight:bold;">&lt;</span>= version
          k.<span style="color:#9900CC;">migrate</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:down</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> si.<span style="color:#9900CC;">version</span> <span style="color:#006600; font-weight:bold;">&gt;</span>= k.<span style="color:#9900CC;">version</span> <span style="color:#9966CC; font-weight:bold;">and</span> k.<span style="color:#9900CC;">version</span> <span style="color:#006600; font-weight:bold;">&gt;</span> version
        <span style="color:#9966CC; font-weight:bold;">end</span>
        si.<span style="color:#9900CC;">update_attributes</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> version<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3>Pour terminer</h3>
<p>Nous avons utilisé les méthodes <tt>meta_def</tt> et <tt>keys_to_sym</tt> lors de la création du module <tt>AR</tt>. Voici comment elles sont définies :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC00FF; font-weight:bold;">Object</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> meta_def<span style="color:#006600; font-weight:bold;">&#40;</span>m,<span style="color:#006600; font-weight:bold;">&amp;</span>b<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#006600; font-weight:bold;">&#40;</span>class<span style="color:#006600; font-weight:bold;">&lt;&lt;</span>self;self <span style="color:#9966CC; font-weight:bold;">end</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:define_method</span>,m,<span style="color:#006600; font-weight:bold;">&amp;</span>b<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC00FF; font-weight:bold;">Hash</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> keys_to_sym
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>k, v<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span>k<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">self</span><span style="color:#006600; font-weight:bold;">&#91;</span>k.<span style="color:#9900CC;">to_s</span>.<span style="color:#9900CC;">to_sym</span><span style="color:#006600; font-weight:bold;">&#93;</span> = v
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Voici donc le code complet de <tt>ar.rb</tt> :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">begin</span>
  <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'active_record'</span>
<span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">LoadError</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e
  <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">LoadError</span>, <span style="color:#996600;">&quot;ActiveRecord ne doit pas être installé : #{e.message}&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC00FF; font-weight:bold;">Object</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> meta_def<span style="color:#006600; font-weight:bold;">&#40;</span>m,<span style="color:#006600; font-weight:bold;">&amp;</span>b<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#006600; font-weight:bold;">&#40;</span>class<span style="color:#006600; font-weight:bold;">&lt;&lt;</span>self;self <span style="color:#9966CC; font-weight:bold;">end</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:define_method</span>,m,<span style="color:#006600; font-weight:bold;">&amp;</span>b<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC00FF; font-weight:bold;">Hash</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> keys_to_sym
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>k, v<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span>k<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">self</span><span style="color:#006600; font-weight:bold;">&#91;</span>k.<span style="color:#9900CC;">to_s</span>.<span style="color:#9900CC;">to_sym</span><span style="color:#006600; font-weight:bold;">&#93;</span> = v
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> AR
  Model = <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> SchemaInfo <span style="color:#006600; font-weight:bold;">&lt;</span> Model
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">Schema</span><span style="color:#006600; font-weight:bold;">&#40;</span> n <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@final</span> = <span style="color:#006600; font-weight:bold;">&#91;</span>n, <span style="color:#0066ff; font-weight:bold;">@final</span>.<span style="color:#9900CC;">to_f</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">max</span>
    m = <span style="color:#006600; font-weight:bold;">&#40;</span>@migrations <span style="color:#006600; font-weight:bold;">||</span>= <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">Class</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      meta_def<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> n <span style="color:#006600; font-weight:bold;">&#125;</span>
      meta_def<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:inherited</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>k<span style="color:#006600; font-weight:bold;">|</span> m <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> k <span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#0000FF; font-weight:bold;">self</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> db_connect<span style="color:#006600; font-weight:bold;">&#40;</span> dbfile, logfile <span style="color:#006600; font-weight:bold;">&#41;</span>
      dbconfig = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>dbfile<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">keys_to_sym</span>
      version = dbconfig.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:schema_version</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>_<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#0066ff; font-weight:bold;">@final</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
      <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">establish_connection</span><span style="color:#006600; font-weight:bold;">&#40;</span>dbconfig<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">logger</span> = <span style="color:#CC00FF; font-weight:bold;">Logger</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>logfile<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@migrations</span>
        <span style="color:#9966CC; font-weight:bold;">unless</span> SchemaInfo.<span style="color:#9900CC;">table_exists</span>?
          <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Schema</span>.<span style="color:#9900CC;">define</span> <span style="color:#9966CC; font-weight:bold;">do</span>
            create_table SchemaInfo.<span style="color:#9900CC;">table_name</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span>
              t.<span style="color:#9900CC;">column</span> <span style="color:#ff3333; font-weight:bold;">:version</span>, <span style="color:#ff3333; font-weight:bold;">:float</span>
            <span style="color:#9966CC; font-weight:bold;">end</span>
          <span style="color:#9966CC; font-weight:bold;">end</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
        si = SchemaInfo.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:first</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">||</span> SchemaInfo.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#0066ff; font-weight:bold;">@migrations</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>k<span style="color:#006600; font-weight:bold;">|</span>
          k.<span style="color:#9900CC;">migrate</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:up</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> si.<span style="color:#9900CC;">version</span> <span style="color:#006600; font-weight:bold;">&lt;</span> k.<span style="color:#9900CC;">version</span> <span style="color:#9966CC; font-weight:bold;">and</span> k.<span style="color:#9900CC;">version</span> <span style="color:#006600; font-weight:bold;">&lt;</span>= version
          k.<span style="color:#9900CC;">migrate</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:down</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> si.<span style="color:#9900CC;">version</span> <span style="color:#006600; font-weight:bold;">&gt;</span>= k.<span style="color:#9900CC;">version</span> <span style="color:#9966CC; font-weight:bold;">and</span> k.<span style="color:#9900CC;">version</span> <span style="color:#006600; font-weight:bold;">&gt;</span> version
        <span style="color:#9966CC; font-weight:bold;">end</span>
        si.<span style="color:#9900CC;">update_attributes</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> version<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Pourquoi vous avoir parlé de tout cela. Et bien simplement parce que c&#8217;est ce que j&#8217;ai mis en place dans <a href="http://github.com/glejeune/Capcode">Capcode</a> pour pouvoir utiliser <tt>ActiveRecord</tt><small><sup>5</sup></small>.</p>
<blockquote style="background-color:#969696; font-size:12px; padding: 5px; border-left:1px solid white;"><p>
Ce code s&#8217;inspire librement de ce qui est mis en place dans <a href="http://github.com/judofyr/camping">Camping</a>.
</p></blockquote>
<p><small><sup>1</sup> Ok, par forcement pour un gros projet&#8230;</small><br />
<small><sup>2</sup> Je dis <i>au moins</i>, car nous pouvons avoir plusieurs modèles</small><br />
<small><sup>3</sup> Notez que je conserve l&#8217;utilisation d&#8217;un fichier Yaml pour la configuration de la base.</small><br />
<small><sup>4</sup> J&#8217;avais déjà <a href="http://www.algorithmique.net/2009/03/04/creer-son-microframework-avec-rack/">expliqué comment créer ce type de classe</a>. </small><br />
<small><sup>5</sup> Et pourtant je déteste <tt>ActiveRecord</tt> et son principe de migration&#8230;</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.algorithmique.net/2009/11/07/activerecord-sans-rails/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tests unitaires avec Capcode</title>
		<link>http://www.algorithmique.net/2009/10/13/tests-unitaires-avec-capcode/</link>
		<comments>http://www.algorithmique.net/2009/10/13/tests-unitaires-avec-capcode/#comments</comments>
		<pubDate>Mon, 12 Oct 2009 23:52:00 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Projets]]></category>
		<category><![CDATA[Capcode]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Tests]]></category>

		<guid isPermaLink="false">http://www.algorithmique.net/?p=655</guid>
		<description><![CDATA[S&#8217;il y a bien un aspect, lors de la mise en place d&#8217;une application, qui obsède les développeurs, ce sont bien les tests. Et à juste titre. Au point que nous trouvons aujourd&#8217;hui de plus en plus d&#8217;équipes qui travaillent en TDD, contre toutes les lois qui nous ont été enseignées lors de nos études. [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.algorithmique.net/wp-content/uploads/2009/09/dev.png" alt="dev" title="dev" width="72" height="72" class="alignleft size-full wp-image-562" />S&#8217;il y a bien un aspect, lors de la mise en place d&#8217;une application, qui obsède les développeurs, ce sont bien les tests. Et à juste titre. Au point que nous trouvons aujourd&#8217;hui de plus en plus d&#8217;équipes qui travaillent en TDD, contre toutes les lois qui nous ont été enseignées lors de nos études. L&#8217;écriture de tests unitaires peut paraitre rébarbative, cela n&#8217;est reste pas moins une très bonne habitude à prendre pour éviter par la suite de longues heures à rechercher les bugs les plus vicieux que nous avons cachés dans notre code. Je vous propose donc de voir comment faire des tests unitaires avec <a href="http://github.com/glejeune/Capcode">Capcode</a>.</p>
<p>Comme vous le savez, Capcode est basé sur <a href="">Rack</a> et il existe pour ce dernier le projet <a href="http://github.com/brynary/rack-test">Rack::Test</a>, idéal pour ce que nous aider dans ce travail. </p>
<p>partons d&#8217;un exemple minimaliste :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># sample.rb</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> Capcode
  <span style="color:#9966CC; font-weight:bold;">class</span> Index <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      render <span style="color:#996600;">&quot;Hello World&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> Redir <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/r'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      redirect<span style="color:#006600; font-weight:bold;">&#40;</span> Index <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Vous remarquerez que je n&#8217;ai volontairement pas mis l&#8217;appel à <tt>Capcode.run</tt> dans ce code. Ceci pour deux raisons. J&#8217;ai pris l&#8217;habitude de déporter cet appel dans un fichier à part ce qui me permet de créer en parallèle un fichier de configuration rackup pour le <a href="http://www.algorithmique.net/2009/10/01/deployer-une-application-capcode-avec-phusion-passenger/">déploiement avec Passenger</a>. De plus, <tt>Rack::Test</tt> sert à tester des applications basées sur <tt>Rack</tt> et implique d&#8217;avoir accès directement à l&#8217;application, celle-là même que vous passez à votre handler.</p>
<p><tt>Rack::Test</tt> fonctionne avec <tt>Test::Unit</tt>, nous allons dons créer, pour chaque ensemble de tests, une classe héritant de <tt>Test::Unit::TestCase</tt> et nous inclurons dans cette classe le module <tt>Rack::Test::Methods</tt> :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># test_sample.rb</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'test/unit'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rack/test'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> HomepageTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span>
  <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Rack::<span style="color:#CC00FF; font-weight:bold;">Test</span>::Methods</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Comme je l&#8217;ai signalé, l&#8217;utilisation de <tt>Rack::Test</tt> implique que nous ayons accès à l&#8217;application. Nous allons donc la charger et faire en sorte qu&#8217;elle soit accessible dans la classe via la méthode <tt>app</tt> :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># test_sample.rb</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'test/unit'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rack/test'</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'sample.rb'</span>
@@app = Capcode.<span style="color:#9900CC;">application</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> HomepageTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span>
  <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Rack::<span style="color:#CC00FF; font-weight:bold;">Test</span>::Methods</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> app
    @@app
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># ...</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Nous pouvons ensuite ajouter nos tests. Chaque test est décrit dans une méthode de la classe, ces méthodes pouvant contenir autant d&#8217;assertions que nécessaire :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># test_sample.rb</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'test/unit'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rack/test'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'sample.rb'</span>
&nbsp;
@@app = Capcode.<span style="color:#9900CC;">application</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> HomepageTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span>
  <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Rack::<span style="color:#CC00FF; font-weight:bold;">Test</span>::Methods</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> app
    @@app
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> test_home
    get <span style="color:#996600;">'/'</span>
    assert_equal <span style="color:#996600;">&quot;http://example.org/&quot;</span>, last_request.<span style="color:#9900CC;">url</span>
    assert last_response.<span style="color:#9900CC;">ok</span>?
    assert_equal <span style="color:#996600;">&quot;Hello World&quot;</span>, last_response.<span style="color:#9900CC;">body</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> test_redirect
    get <span style="color:#996600;">'/r'</span>
    assert_equal <span style="color:#996600;">&quot;http://example.org/r&quot;</span>, last_request.<span style="color:#9900CC;">url</span>
    follow_redirect!
    assert_equal <span style="color:#996600;">&quot;http://example.org/&quot;</span>, last_request.<span style="color:#9900CC;">url</span>
    assert_equal <span style="color:#996600;">&quot;Hello World&quot;</span>, last_response.<span style="color:#9900CC;">body</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Si vous exécutez <tt>test_sample.rb</tt> vous devriez obtenir la sortie suivante :</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">Loaded suite /Users/greg/dev/Capcode/tests/test_sample
Started
.. 
Finished in 0.005839 seconds.
&nbsp;
2 tests, 6 assertions, 0 failures, 0 errors</pre></div></div>

<p>Pour les assertions, vous pouvez utiliser tout ce que propose <a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit/Assertions.html">Test::Unit</a>. Pour la partie &laquo;&nbsp;navigation&nbsp;&raquo;, <tt>Rack::Test</tt> vous offre les méthodes suivantes : </p>
<ul>
<li><tt>get</tt>, <tt>post</tt>, <tt>put</tt>, <tt>delete</tt> et <tt>head</tt> permettent respectivement de faire des requêtes de type <tt>GET</tt>, <tt>POST</tt>, <tt>PUT</tt>, <tt>DELETE</tt> et <tt>HEAD</tt>. Chacune de ces méthodes prend en paramètre l&#8217;URI à tester, mais également les paramètres, sous forme de hachage et éventuellement des données d&#8217;environnement (également sous forme de hachage).

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">post <span style="color:#996600;">'/login'</span>, <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">&quot;user&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;greg&quot;</span>, <span style="color:#996600;">&quot;password&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;s3cr3t&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

</li>
<li><tt>header</tt> permet de positionner la valeur d&#8217;une entête

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">header <span style="color:#996600;">&quot;User-Agent&quot;</span>, <span style="color:#996600;">&quot;Firefox&quot;</span></pre></div></div>

</li>
<li><tt>basic_authorize</tt> et <tt>digest_authorize</tt> permettent de donner le login et le mot de passe pour, respectivement, une <a href="http://www.algorithmique.net/2009/10/09/authentification-http-avec-capcode/">authentification basic ou digest</a>.

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">digest_authorize<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;greg&quot;</span>, <span style="color:#996600;">&quot;p4ssw0rd&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

</li>
<li><tt>follow_redirect!</tt> permet de suivre la dernière redirection renvoyée.<br />&nbsp;</li>
<li><tt>set_cookie</tt> et <tt>clear_cookie</tt> permettent de gérer les cookies.<br />&nbsp;</li>
<li><tt>last_request</tt> correspond à la dernière requête. C&#8217;est une instance de <a href="http://rack.rubyforge.org/doc/Rack/Request.html">Rack::Request</a>.<br />&nbsp;</li>
<li><tt>last_response</tt> correspond à la dernière réponse, c&#8217;est une instance de <a href="http://rack.rubyforge.org/doc/Rack/MockResponse.html">Rack::MockResponse</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.algorithmique.net/2009/10/13/tests-unitaires-avec-capcode/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Authentification HTTP avec Capcode</title>
		<link>http://www.algorithmique.net/2009/10/09/authentification-http-avec-capcode/</link>
		<comments>http://www.algorithmique.net/2009/10/09/authentification-http-avec-capcode/#comments</comments>
		<pubDate>Fri, 09 Oct 2009 16:46:08 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Projets]]></category>
		<category><![CDATA[Capcode]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.algorithmique.net/?p=635</guid>
		<description><![CDATA[Quand j&#8217;ai mis en place le moteur de rendu WebDAV dans Capcode, la première remarque qui m&#8217;est revenue fut &#171;&#160;Oui, mais comment faire pour sécuriser un peu tout ça ?&#171;&#160;. Bonne question dont malheureusement la réponse fut beaucoup plus facile à mettre en place que ce que j&#8217;avais imaginé1.
La sécurisation d&#8217;un serveur WebDAV passe par [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.algorithmique.net/wp-content/uploads/2009/10/projets.png" alt="projets" title="projets" width="67" height="72" class="alignleft size-full wp-image-556" />Quand j&#8217;ai mis en place <a href="http://www.algorithmique.net/2009/10/07/creer-un-serveur-webdav-en-4-puis-11-lignes-de-code-avec-ruby/">le moteur de rendu WebDAV dans Capcode</a>, la première remarque qui m&#8217;est revenue fut &laquo;&nbsp;<i>Oui, mais comment faire pour sécuriser un peu tout ça ?</i>&laquo;&nbsp;. Bonne question dont malheureusement la réponse fut beaucoup plus facile à mettre en place que ce que j&#8217;avais imaginé<small><sup>1</sup></small>.</p>
<p>La sécurisation d&#8217;un serveur WebDAV passe par de l&#8217;authentification HTTP. Il existe une solution dans rack, via <a href="http://rack.rubyforge.org/doc/Rack/Auth.html">Rack::Auth</a>. Malheureusement, non seulement la documentation est un élément qui fait cruellement défaut dans rack, mais en plus s&#8217;il est facile de mettre en place une authentification globale pour toute une application, c&#8217;est une autre paire de manches quand on souhaite faire cela pour une route précise. En effet, il n&#8217;est pas rare d&#8217;avoir, dans un site, une partie <i>publique</i> et une autre <i>privée</i>. Et c&#8217;est bien ce que je souhaitais permettre. </p>
<p>En cherchant sur <a href="http://www.google.com/search?client=safari&#038;rls=en&#038;q=Rack::Auth::Basic::Request&#038;ie=UTF-8&#038;oe=UTF-8">Google</a>, je suis tombé sur <a href="http://www.gittr.com/index.php/archive/sinatra-basic-authentication-selectively-applied/">cet excellent post</a> expliquant comment mettre en place une authentification <i>Basic</i> dans <a href="http://www.sinatrarb.com/">Sinatra</a>. J&#8217;ai donc adapté la solution pour <a href="http://github.com/glejeune/Capcode">Capcode</a>. Le problème de l&#8217;authentification <i>Basic</i> c&#8217;est qu&#8217;elle est plutôt réservée aux sites accessibles en HTTPS puisque les mots de passent sont en clair dans l&#8217;entête. J&#8217;ai donc fait un petit passage par la <a href="http://www.ietf.org/rfc/rfc2617.txt">RFC2617</a><small><sup>2</sup></small> et en lisant attentivement le code de <a href="http://rack.rubyforge.org/doc/Rack/Auth/Digest/Request.html">Rack::Auth::Digest::Request</a> et <a href="http://rack.rubyforge.org/doc/Rack/Auth/Digest/MD5.html">Rack::Auth::Digest::MD5</a>, j&#8217;ai rapidement ajouté l&#8217;authentification <i>Digest</i>. Ceci a donné naissance à un <i>helper</i> pour les controôleurs : <tt>http_authentication</tt>.</p>
<p>La mise en place est donc très simple. Voici un petit exemple :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rack'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> Capcode
  <span style="color:#9966CC; font-weight:bold;">class</span> Private <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/private'</span>    
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      <span style="color:#008000; font-style:italic;"># Basic HTTP Authentication</span>
      http_authentication<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:basic</span>, <span style="color:#ff3333; font-weight:bold;">:realm</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;My Capcode test!!!&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> 
        <span style="color:#006600; font-weight:bold;">&#123;</span>
          <span style="color:#996600;">&quot;greg&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;toto&quot;</span>,
          <span style="color:#996600;">&quot;mu&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;maia&quot;</span>
        <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>
      render <span style="color:#996600;">&quot;Success !&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span> 
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> Public <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/public'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      render <span style="color:#996600;">&quot;You don't need any special authorization here !&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
Capcode.<span style="color:#9900CC;">run</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006600; font-weight:bold;">&#41;</span></pre></td></tr></table></div>

<p>La partie importante se trouve de la ligne 8 à la ligne 13. </p>
<p><tt>http_authentication</tt> permet de spécifier que vous voulez mettre en place une authentification HTTP pour le contrôleur <tt>Private</tt>. Ce helper supporte les options suivantes :</p>
<ul>
<li><tt>:type</tt> qui permet de préciser le type d&#8217;authentification. Les valeurs possibles sont <tt>:basic</tt> (valeur par défaut) et <tt>:digest</tt>.</li>
<li><tt>:realm</tt> qui donne l&#8217;information sur le nom et mot de passe que peut utiliser l&#8217;utilisateur. C&#8217;est une chaine de caractère pouvant prendre n&#8217;importe quelle valeur (&laquo;&nbsp;Capcode.app&nbsp;&raquo; par défaut).</li>
<li><tt>:opaque</tt> qui est une chaîne générée par le serveur devant être retournée telle quelle par le client (defaut : &laquo;&nbsp;opaque&nbsp;&raquo;). Cette option n&#8217;est utile que dans le cas d&#8217;une authentification <i>Digest</i>.</li>
</ul>
<p>Enfin, <tt>http_authentication</tt> prend en paramètre un bloc qui doit lui retourner un hachage contenant les couples login/mot de passe pouvant s&#8217;authentifier, sous la forme :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&#123;</span>
  <span style="color:#996600;">&quot;user1&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;pass1&quot;</span>,
  <span style="color:#996600;">&quot;user2&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;pass2&quot;</span>,
  <span style="color:#008000; font-style:italic;"># ...</span>
<span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>Dans l&#8217;exemple ci-dessus, nous avons mis en place une authentification <i>Basic</i>. Aux vues de ce qui vient d&#8217;être dit, vous voyez aisément comment passer à une authentification de type <i>Digest</i> :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Digest HTTP Authentication</span>
http_authentication<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:digest</span>, <span style="color:#ff3333; font-weight:bold;">:opaque</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Ma phrase secrète&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:realm</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;My Capcode test!!!&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> 
  <span style="color:#006600; font-weight:bold;">&#123;</span>
    <span style="color:#996600;">&quot;greg&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;toto&quot;</span>,
    <span style="color:#996600;">&quot;mu&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;maia&quot;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span></pre></td></tr></table></div>

<p>Tout cela c&#8217;est très bien me direz vous, mais comment je fais si je veux protéger plusieurs routes avec une même authentification. Prenons l&#8217;exemple suivant :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> Capcode
  <span style="color:#9966CC; font-weight:bold;">class</span> Public <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/public'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      render <span style="color:#996600;">&quot;You don't need any special authorization here !&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> Private <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/private'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      render <span style="color:#996600;">&quot;Welcome to the private part of this site !&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> PrivateAgain <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/private/again'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      render <span style="color:#996600;">&quot;Welcome to the private/again part of this site !&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
Capcode.<span style="color:#9900CC;">run</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006600; font-weight:bold;">&#41;</span></pre></td></tr></table></div>

<p>Avec ce qui a été dit ci-dessus, si nous voulons protéger les parties <tt>Private</tt> et <tt>PrivateAgain</tt>, nous devons utiliser deux fois <tt>http_authentication</tt>. Essayez de le mettre seulement dans <tt>Private</tt> et vous verrez que vous pouvez accéder à <tt>PrivateAgain</tt> sans aucun problème. Ce qui est un problème !!!</p>
<p>Heureusement, il y a une solution. En effet, vous pouvez faire une déclaration de demande d&#8217;authentification de manière globale. Pour cela j&#8217;ai mis en place une méthode <tt>Capcode::http_authentication</tt> qui ressemble en tout point au helper utilisable dans les contrôleurs, mais prenant un paramètre de plus : <tt>:routes</tt>. Ainsi, vous pouvez mettre en place la protection souhaitée de la façon suivante :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'digest/md5'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> Capcode
&nbsp;
  OPAQUE = <span style="color:#6666ff; font-weight:bold;">Digest::MD5</span>.<span style="color:#9900CC;">hexdigest</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>.<span style="color:#9900CC;">to_s</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
  http_authentication<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:digest</span>, <span style="color:#ff3333; font-weight:bold;">:opaque</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> OPAQUE, <span style="color:#ff3333; font-weight:bold;">:realm</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Private parts&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:routes</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;/private&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> 
    <span style="color:#006600; font-weight:bold;">&#123;</span>
      <span style="color:#996600;">&quot;greg&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;toto&quot;</span>,
      <span style="color:#996600;">&quot;mu&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;maia&quot;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> Public <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/public'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      render <span style="color:#996600;">&quot;You don't need any special authorization here !&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> Private <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/private'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      render <span style="color:#996600;">&quot;Welcome to the private part of this site !&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> PrivateAgain <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/private/again'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      render <span style="color:#996600;">&quot;Welcome to the private/again part of this site !&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
Capcode.<span style="color:#9900CC;">run</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006600; font-weight:bold;">&#41;</span></pre></td></tr></table></div>

<p>A la ligne 7, nous utilisons la méthode <tt>http_authentication</tt> pour dire que nous voulons une protection pour toutes les routes ayant pour racine <tt>/private</tt>. En terme d&#8217;expression régulière cela veut dire que si la route match avec <tt>/^\/private([\/]{1}.*)?$</tt> alors il faudra s&#8217;authentifier pour y accéder. </p>
<p>Notez également que le paramètre <tt>:routes</tt> peut prendre comme valeur un tableau, ce qui peut grandement nous faciliter la vie si nous voulons utiliser une protection commune pour des routes n&#8217;ayant pas la même racine.</p>
<p>Et notre serveur WebDAV alors ? Et bien voici sa nouvelle version :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># file: sample.rb</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode/render/webdav'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> Capcode
  <span style="color:#008000; font-style:italic;"># !!! Render file from /Users/greg/Documents/etudes !!!</span>
  <span style="color:#9966CC; font-weight:bold;">class</span> WebDav <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/etudes'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      http_authentication<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:digest</span>, <span style="color:#ff3333; font-weight:bold;">:realm</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Greg' WebDAV Server&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> 
        <span style="color:#006600; font-weight:bold;">&#123;</span>
          <span style="color:#996600;">&quot;greg&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;my super secret password&quot;</span>,
          <span style="color:#996600;">&quot;commercial&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;semaine 23&quot;</span>
        <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>
      render <span style="color:#ff3333; font-weight:bold;">:webdav</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;/Users/greg/Documents&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> method_missing<span style="color:#006600; font-weight:bold;">&#40;</span>id, <span style="color:#006600; font-weight:bold;">*</span>a, <span style="color:#006600; font-weight:bold;">&amp;</span>b<span style="color:#006600; font-weight:bold;">&#41;</span>; get; <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>  
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Dernière petite chose avant de terminer, sachez que vous pouvez récupérer le login utilisé via <tt>request.env['REMOTE_USER']</tt>.</p>
<p><small><sup>1</sup> bon, j&#8217;ai <a href="https://twitter.com/glejeune/status/4711368628">un jour de retard</a>, mais quand même !!!</small><br />
<small><sup>2</sup> Lire également l&#8217;article <a href="http://fr.wikipedia.org/wiki/HTTP_Authentification">HTTP Authentification</a> de Wikipedia.</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.algorithmique.net/2009/10/09/authentification-http-avec-capcode/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creer un serveur WebDAV en 4 puis 11 lignes de code avec Ruby</title>
		<link>http://www.algorithmique.net/2009/10/07/creer-un-serveur-webdav-en-4-puis-11-lignes-de-code-avec-ruby/</link>
		<comments>http://www.algorithmique.net/2009/10/07/creer-un-serveur-webdav-en-4-puis-11-lignes-de-code-avec-ruby/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 17:15:43 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Projets]]></category>
		<category><![CDATA[Capcode]]></category>
		<category><![CDATA[Rack]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.algorithmique.net/?p=619</guid>
		<description><![CDATA[Le problème, quand on travaille sur Mac, c&#8217;est que les autres pensent qu&#8217;on n&#8217;est pas compatible. En fait, ce n&#8217;est pas vrai. Mon Pages est tout à fait capable d&#8217;ouvrir les saloperies de documents .docx que m&#8217;envoient mes collègues, et je lis sans problèmes les immondes documents PowerPoint avec Keynote. Je suis même capable de [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.algorithmique.net/wp-content/uploads/2009/10/projets.png" alt="projets" title="projets" width="67" height="72" class="alignleft size-full wp-image-556" />Le problème, quand on travaille sur Mac, c&#8217;est que les <i>autres</i> pensent qu&#8217;on n&#8217;est <i>pas compatible</i>. En fait, ce n&#8217;est pas vrai. Mon <a href="http://www.apple.com/fr/iwork/pages/">Pages</a> est tout à fait capable d&#8217;ouvrir les <span style="background-color: black">saloperies de</span> documents <tt>.docx</tt> que m&#8217;envoient mes collègues, et je lis sans problèmes les <span style="background-color: black">immondes</span> documents PowerPoint avec <a href="http://www.apple.com/fr/iwork/keynote/">Keynote</a>. Je suis même capable de générer des documents dans ces formats depuis les mêmes logiciels&#8230; Bref, je suis compatible ! C&#8217;est Microsoft, avec ses logiciels, qui n&#8217;est pas compatible, croyant encore et toujours que sa suprématie ne lui impose pas de permettre d&#8217;ouvrir des documents <i>étrangers</i><small><sup>1</sup></small>. Mais allez faire comprendre cela à quelqu&#8217;un qui vous parle en <a href="http://www.algorithmique.net/2009/10/06/semaine-23/">numéro de semaine</a> ;) Ces mêmes personnes qui ont l&#8217;habitude de s&#8217;échanger des fichiers via des <i>répertoires partagés</i>&#8230; Là encore, je suis capable d&#8217;aller piocher dans un de leurs répertoires (merci <a href="http://www.samba.org/">samba</a>) mais je peux toujours rêver pour que leur Windows puisse accéder à un de mes répertoires !</p>
<p>Pour régler ce dernier problème, je me suis penché sur <a href="http://fr.wikipedia.org/wiki/WebDAV">WebDAV</a>. Bien entendu, il y a <a href="http://httpd.apache.org/docs/2.0/mod/mod_dav.html">mod_dav</a> sur mon serveur <a href="http://httpd.apache.org/">apache</a>. Mais ce n&#8217;est pas très souple. Je me suis donc demandé si je ne pouvais pas trouver un serveur WebDAV simple et facile à mettre en place. Et bien c&#8217;était sans compter sur <a href="http://www.ruby-lang.org/">Ruby</a>, <a href="http://rack.rubyforge.org/">Rack</a> et surtout <a href="http://github.com/georgi/rack_dav">rack_dav</a>.</p>
<p>rack_dav permet de monter très facilement un serveur WebDAV. Ce sont les fameuses 4 lignes de code. Par exemple pour partager le contenu de mon répertoire <tt>Documents/etudes</tt> il suffit de créer le fichier de configuration rackup suivant :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># config.ru</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>; 
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rack_dav'</span>; 
use <span style="color:#6666ff; font-weight:bold;">Rack::CommonLogger</span>; 
&nbsp;
run <span style="color:#6666ff; font-weight:bold;">RackDAV::Handler</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:root</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'/Users/greg/Documents/etudes'</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Après avoir lancé <tt>rackup</tt>, mon dossier est accessible via l&#8217;URL <tt>http://mon.server.net:9292/</tt>.</p>
<p>Le problème vient quand on veut pouvoir partager plusieurs répertoires. Et c&#8217;est à ce moment-là que j&#8217;ai eu l&#8217;idée d&#8217;ajouter un moteur de rendu WebDAV dans <a href="http://github.com/glejeune/Capcode">Capcode</a>. La mise en place est aussi simple que pour les autres moteurs de rendu, et utilise donc la syntaxe <tt>render :webdav => "/path/to/root"</tt>. Ainsi, si je veux mettre en place la même chose que ce que j&#8217;ai fait ci-dessus avec rack, je code ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># file: sample.rb</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'capcode/render/webdav'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> Capcode
  <span style="color:#008000; font-style:italic;"># !!! Render file from /Users/greg/Documents/etudes !!!</span>
  <span style="color:#9966CC; font-weight:bold;">class</span> WebDav <span style="color:#006600; font-weight:bold;">&lt;</span> Route <span style="color:#996600;">'/etudes'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get
      render <span style="color:#ff3333; font-weight:bold;">:webdav</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;/Users/greg/Documents&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> method_missing<span style="color:#006600; font-weight:bold;">&#40;</span>id, <span style="color:#006600; font-weight:bold;">*</span>a, <span style="color:#006600; font-weight:bold;">&amp;</span>b<span style="color:#006600; font-weight:bold;">&#41;</span>; get; <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>  
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Il y a deux choses remarquables ici :</p>
<ol>
<li>Tout d&#8217;abord, pour permettre un accès au répertoire <tt>/Users/greg/Documents/etudes</tt>, j&#8217;utilise la route <tt>/etudes</tt> et le positionne le répertoire racine avec la valeur <tt>/Users/greg/Documents</tt>. Bien entendu, toutes les combinaisons sont possibles&#8230;</li>
<li>En plus de la méthode <tt>get</tt> je définis une méthode <tt>method_missing</tt> qui appelle la méthode <tt>get</tt>. Ceci est dû au fait que le protocole WebDAV définit <a href="http://tools.ietf.org/html/rfc2518">tout un tas de méthodes HTTP</a>, mais qui, dans le cas présent, peuvent toutes être traité comme le <tt>GET</tt>.</li>
</ol>
<p>Voilà&#8230; Tout cela se trouvera dans la prochaine version de Capcode ou sur <a href="http://github.com/glejeune/Capcode">github</a> pour les plus pressés.</p>
<p><small><sup>1</sup> Il fallait rétablir cette vérité.</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.algorithmique.net/2009/10/07/creer-un-serveur-webdav-en-4-puis-11-lignes-de-code-avec-ruby/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Semaine 23 ?!?</title>
		<link>http://www.algorithmique.net/2009/10/06/semaine-23/</link>
		<comments>http://www.algorithmique.net/2009/10/06/semaine-23/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 19:50:28 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.algorithmique.net/?p=613</guid>
		<description><![CDATA[Si comme moi, vous travaillez avec des commerciaux, vous aurez certainement constaté l&#8217;erreur de compilation qui affecte cette étrange population. En effet, à chaque fois que vous leur demandez une date ils vous répondent en numéro de semaine !?! Donc si vous voulez savoir quand commence la campagne truc, vous aurez comme toute réponse semaine [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.algorithmique.net/wp-content/uploads/2009/09/dev.png" alt="dev" title="dev" width="72" height="72" class="alignleft size-full wp-image-562" />Si comme moi, vous travaillez avec des <i>commerciaux</i>, vous aurez certainement constaté l&#8217;erreur de compilation qui affecte cette étrange population. En effet, à chaque fois que vous leur demandez une date ils vous répondent en <i>numéro de semaine</i> !?! Donc si vous voulez savoir quand commence la campagne truc, vous aurez comme toute réponse <i>semaine 23</i>&#8230; Merci ! Ils n&#8217;ont donc pas encore compris qu&#8217;ils sont les seuls à pouvoir décoder de tête cette information. </p>
<p>Bon, j&#8217;ai trouvé la solution, mais elle impose d&#8217;avoir toujours son ordinateur portable avec soi. Je me suis créé l&#8217;alias suivant :</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">alias week='ruby -e &quot;require \&quot;date\&quot;; puts Date.commercial( Time.now.year, ARGV[0].to_i|1, 1 ).strftime( \&quot;%d-%m-%Y\&quot;)&quot;'</pre></div></div>

<p>Moi : &laquo;&nbsp;Donc, <i>semaine 23</i> ?&nbsp;&raquo;</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">$ week 23
01-06-2009
$</pre></div></div>

<p>Lui : &laquo;&nbsp;Oui&#8230;&nbsp;&raquo;<br />
Moi : &laquo;&nbsp;Donc à partir du 1er juin&#8230;&nbsp;&raquo;<br />
Lui : &laquo;&nbsp;A ben je sais pas&#8230; Semaine 23 quoi !&nbsp;&raquo; </p>
]]></content:encoded>
			<wfw:commentRss>http://www.algorithmique.net/2009/10/06/semaine-23/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
