<?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"
	>

<channel>
	<title>Le Vosgien du Net</title>
	<atom:link href="http://levosgien.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://levosgien.net</link>
	<description>Parce que la vérité n'est pas toujours bonne à dire</description>
	<pubDate>Thu, 13 Nov 2008 23:17:16 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.5</generator>
	<language>en</language>
			<item>
		<title>Gentoo : How to unmerge all packages of a category</title>
		<link>http://levosgien.net/2008/11/14/gentoo-how-to-unmerge-all-packages-of-a-category/</link>
		<comments>http://levosgien.net/2008/11/14/gentoo-how-to-unmerge-all-packages-of-a-category/#comments</comments>
		<pubDate>Thu, 13 Nov 2008 23:17:16 +0000</pubDate>
		<dc:creator>Pierre</dc:creator>
		
		<category><![CDATA[Geekitude]]></category>

		<category><![CDATA[eix]]></category>

		<category><![CDATA[gentoo]]></category>

		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://levosgien.net/?p=138</guid>
		<description><![CDATA[	Thanks to eix !
Note : You must be root to unmerge packages
Start by installing emerge if you don&#8217;t have it : emerge eix
Run update-eix to create or update the eix database.
Now, this&#8230; trick should work for you too  
eix --nocolor -c -I -C dev-ruby &#124; cut -d " " -f 2 &#124; grep --color=never [...]]]></description>
			<content:encoded><![CDATA[	<p>Thanks to eix !<br/><br />
Note : <em>You must be root to unmerge packages</em><br/><br />
Start by installing emerge if you don&#8217;t have it : <code>emerge eix</code><br/><br />
Run <code>update-eix</code> to create or update the eix database.<br/><br />
Now, this&#8230; trick should work for you too <img src='http://levosgien.net/wp/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> <br/><br />
<code>eix --nocolor -c -I -C dev-ruby | cut -d " " -f 2 | grep --color=never dev-ruby | xargs emerge --unmerge</code><br/><br />
Need some explanations ?<br/><br />
<code>eix -c -I -C dev-ruby</code> extracts all installed packages from dev-ruby<br/><br />
<code>cut -d " " -f 2</code> extracts the full package name<br/><br />
<code>grep --color=never dev-ruby</code> filters the list ignoring eix overlays info and packages count (you could also use <code>eix -c -*...</code> to avoid that)<br/><br />
<code>xargs</code> takes the whole packages list and send it as a list of arguments to <code>emerge --unmerge</code> that will unmerge all listed packages in one shot !</p>

 ]]></content:encoded>
			<wfw:commentRss>http://levosgien.net/2008/11/14/gentoo-how-to-unmerge-all-packages-of-a-category/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Firebird backup script</title>
		<link>http://levosgien.net/2008/09/25/firebird-backup-script/</link>
		<comments>http://levosgien.net/2008/09/25/firebird-backup-script/#comments</comments>
		<pubDate>Thu, 25 Sep 2008 09:29:59 +0000</pubDate>
		<dc:creator>Pierre</dc:creator>
		
		<category><![CDATA[Geekitude]]></category>

		<category><![CDATA[bash]]></category>

		<category><![CDATA[firebird]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://levosgien.net/?p=123</guid>
		<description><![CDATA[	This is my first released backup script for Firebird RDBMS. It automagically search for all Firebird databases from a central directory, uses gfix to validate them, then backup + gzip them to a central backup directory keeping only 5 last successful backups.
	It may be used as a cron script to automate Firebird databases backup.


#!/usr/bin/env bash
#
# [...]]]></description>
			<content:encoded><![CDATA[	<p>This is my first released backup script for Firebird RDBMS. It automagically search for all Firebird databases from a central directory, uses gfix to validate them, then backup + gzip them to a central backup directory keeping only 5 last successful backups.</p>
	<p>It may be used as a cron script to automate Firebird databases backup.<br />
<span id="more-123"></span></p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/env bash</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;">#   Validate and Backup Firebird databases using Firebird</span>
<span style="color: #666666; font-style: italic;"># standard tools</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;">#   You can adjust FB_ROOT, FB_BIN, FB_DATA, Fb_BACKUP and </span>
<span style="color: #666666; font-style: italic;"># BACKUP_COUNT variables to fit your own requirements. </span>
<span style="color: #666666; font-style: italic;"># For instance, if you use an official package of Firebird for your</span>
<span style="color: #666666; font-style: italic;"># ditribution, you may have to change FB_ROOT to /usr/bin.</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># The contents of this file are subject to the Initial </span>
<span style="color: #666666; font-style: italic;"># Developer's Public License Version 1.0 (the &quot;License&quot;); </span>
<span style="color: #666666; font-style: italic;"># you may not use this file except in compliance with the </span>
<span style="color: #666666; font-style: italic;"># License. You may obtain a copy of the License from</span>
<span style="color: #666666; font-style: italic;"># the Firebird Project website, at </span>
<span style="color: #666666; font-style: italic;"># http://www.firebirdsql.org/index.php?op=doc&amp;id=idpl.</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Software distributed under the License is distributed </span>
<span style="color: #666666; font-style: italic;"># on an &quot;AS IS&quot; basis, WITHOUT WARRANTY OF ANY KIND, </span>
<span style="color: #666666; font-style: italic;"># either express or implied. See the License for the </span>
<span style="color: #666666; font-style: italic;"># specific language governing rights and limitations under </span>
<span style="color: #666666; font-style: italic;"># the License.</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># The Original Code is licenced under IDPL</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># The Initial Developer of the Original Code is </span>
<span style="color: #666666; font-style: italic;">#   Pierre Yager (pierre@levosgien.net).</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Portions created by ______________________</span>
<span style="color: #666666; font-style: italic;"># are Copyright (C) ______ _________________.</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># All Rights Reserved.</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Contributor(s): _________________________.</span>
<span style="color: #666666; font-style: italic;">#</span>
&nbsp;
<span style="color: #007800;">FB_ROOT</span>=<span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>firebird
<span style="color: #007800;">FB_BIN</span>=<span style="color: #800000;">${FB_ROOT}</span><span style="color: #000000; font-weight: bold;">/</span>bin
<span style="color: #007800;">FB_DATA</span>=<span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>firebird
<span style="color: #007800;">FB_BACKUP</span>=backup
<span style="color: #007800;">BACKUP_COUNT</span>=<span style="color: #000000;">5</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># You shouldn't have to make any changes below</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">id</span> -u<span style="color: #000000; font-weight: bold;">`</span> = 0 <span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">then</span>
  <span style="color: #7a0874; font-weight: bold;">echo</span> You are not root...
  <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">67</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Loads the ISC_USER and ISC_PASSWORD environment variables</span>
<span style="color: #7a0874; font-weight: bold;">source</span> <span style="color: #800000;">${FB_ROOT}</span><span style="color: #000000; font-weight: bold;">/</span>SYSDBA.password
&nbsp;
<span style="color: #7a0874; font-weight: bold;">export</span> ISC_USER
<span style="color: #7a0874; font-weight: bold;">export</span> ISC_PASSWORD
&nbsp;
<span style="color: #666666; font-style: italic;">#  Returns the filename without extension, whatever the </span>
<span style="color: #666666; font-style: italic;">#+ extension is...</span>
<span style="color: #000000; font-weight: bold;">function</span> namename<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #7a0874; font-weight: bold;">&#123;</span>
  <span style="color: #7a0874; font-weight: bold;">local</span> <span style="color: #007800;">name</span>=<span style="color: #800000;">${1##*/}</span>
  <span style="color: #7a0874; font-weight: bold;">local</span> <span style="color: #007800;">name0</span>=<span style="color: #ff0000;">&quot;${name%.*}&quot;</span>
  <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;${name0:-$name}&quot;</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Cleanup old backup files</span>
<span style="color: #000000; font-weight: bold;">function</span> cleanup<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #7a0874; font-weight: bold;">&#123;</span>
  <span style="color: #7a0874; font-weight: bold;">local</span> <span style="color: #007800;">PREFIX</span>=$<span style="color: #000000;">1</span>
&nbsp;
  <span style="color: #666666; font-style: italic;"># list files by time in reverse order </span>
  <span style="color: #7a0874; font-weight: bold;">local</span> <span style="color: #007800;">FILES</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-rt</span> <span style="color: #800000;">${FB_BACKUP}</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #800000;">${PREFIX}</span><span style="color: #000000; font-weight: bold;">*</span>.fbk.gz<span style="color: #000000; font-weight: bold;">`</span>
&nbsp;
  <span style="color: #666666; font-style: italic;"># count the previous files list</span>
  <span style="color: #7a0874; font-weight: bold;">local</span> <span style="color: #007800;">FILES_COUNT</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-lrt</span> <span style="color: #800000;">${FB_BACKUP}</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #800000;">${PREFIX}</span><span style="color: #000000; font-weight: bold;">*</span>.fbk.gz | <span style="color: #c20cb9; font-weight: bold;">wc</span> -l<span style="color: #000000; font-weight: bold;">`</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$FILES_COUNT</span> <span style="color: #660033;">-gt</span> <span style="color: #007800;">$BACKUP_COUNT</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
  <span style="color: #000000; font-weight: bold;">then</span>
    <span style="color: #666666; font-style: italic;"># Iterate the files list</span>
    <span style="color: #000000; font-weight: bold;">for</span> F <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #007800;">$FILES</span>
    <span style="color: #000000; font-weight: bold;">do</span>
      <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$FILES_COUNT</span> <span style="color: #660033;">-gt</span> <span style="color: #007800;">$BACKUP_COUNT</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
      <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #666666; font-style: italic;">#  And remove first files as soon as we have only </span>
        <span style="color: #666666; font-style: italic;">#+ BACKUP_COUNT files remaining</span>
        <span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #007800;">$F</span>
        <span style="color: #007800;">FILES_COUNT</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span>FILES_COUNT - <span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
      <span style="color: #000000; font-weight: bold;">else</span>
        <span style="color: #7a0874; font-weight: bold;">break</span>
      <span style="color: #000000; font-weight: bold;">fi</span>
    <span style="color: #000000; font-weight: bold;">done</span>
  <span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Uses gfix to validates the database</span>
<span style="color: #000000; font-weight: bold;">function</span> validate<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #7a0874; font-weight: bold;">&#123;</span>
  <span style="color: #800000;">${FB_BIN}</span><span style="color: #000000; font-weight: bold;">/</span>gfix <span style="color: #660033;">-validate</span> <span style="color: #660033;">-full</span> $<span style="color: #000000;">1</span>
  <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$?</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Uses gbak to backup the database then compress it...</span>
<span style="color: #000000; font-weight: bold;">function</span> backup<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #7a0874; font-weight: bold;">&#123;</span>
  <span style="color: #7a0874; font-weight: bold;">local</span> <span style="color: #007800;">DIR</span>=<span style="color: #800000;">${1%/*}</span>
  <span style="color: #7a0874; font-weight: bold;">local</span> <span style="color: #007800;">DB</span>=<span style="color: #000000; font-weight: bold;">`</span>namename <span style="color: #007800;">$F</span><span style="color: #000000; font-weight: bold;">`</span>
  <span style="color: #7a0874; font-weight: bold;">local</span> <span style="color: #007800;">TS</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">date</span> +<span style="color: #ff0000;">&quot;%Y%m%d_%H%M%S&quot;</span><span style="color: #000000; font-weight: bold;">`</span>
  <span style="color: #7a0874; font-weight: bold;">local</span> <span style="color: #007800;">BACKUP</span>=<span style="color: #800000;">${FB_BACKUP}</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #800000;">${DIR}</span>_<span style="color: #800000;">${DB}</span>_<span style="color: #800000;">${TS}</span>.fbk
  <span style="color: #800000;">${FB_BIN}</span><span style="color: #000000; font-weight: bold;">/</span>gbak <span style="color: #660033;">-b</span> $<span style="color: #000000;">1</span> <span style="color: #007800;">$BACKUP</span>
  <span style="color: #c20cb9; font-weight: bold;">gzip</span> <span style="color: #007800;">$BACKUP</span>
  cleanup <span style="color: #800000;">${DIR}</span>_<span style="color: #800000;">${DB}</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">pushd</span> <span style="color: #800000;">${FB_DATA}</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-d</span> <span style="color: #800000;">${FB_BACKUP}</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">then</span>
  <span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #800000;">${FB_BACKUP}</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#  Avoid */*.fdb to be expanded if there are no files in the </span>
<span style="color: #666666; font-style: italic;">#+ databases repository</span>
<span style="color: #7a0874; font-weight: bold;">shopt</span> <span style="color: #660033;">-s</span> nullglob
&nbsp;
<span style="color: #000000; font-weight: bold;">for</span> F <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">*/*</span>.fdb
<span style="color: #000000; font-weight: bold;">do</span>
  <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">`</span>validate <span style="color: #007800;">$F</span><span style="color: #000000; font-weight: bold;">`</span> = 0 <span style="color: #7a0874; font-weight: bold;">&#93;</span>
  <span style="color: #000000; font-weight: bold;">then</span>
    <span style="color: #666666; font-style: italic;"># Only backup valid databases</span>
    backup <span style="color: #007800;">$F</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">#  Future enhancements : write a message to stderr so that</span>
    <span style="color: #666666; font-style: italic;">#+ cron can send a mail to the DBA when databases are not </span>
    <span style="color: #666666; font-style: italic;">#+ valid...</span>
  <span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">popd</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null</pre></div></div>

	<p>Hope this will be useful. You can also <a href="http://levosgien.net/files/fb-backup.sh">download the script</a></p>

 ]]></content:encoded>
			<wfw:commentRss>http://levosgien.net/2008/09/25/firebird-backup-script/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Ruby Installer 3.0 &#8220;MinGW&#8221; et SQLite 3</title>
		<link>http://levosgien.net/2008/08/13/ruby-installer-30-mingw-et-sqlite-3/</link>
		<comments>http://levosgien.net/2008/08/13/ruby-installer-30-mingw-et-sqlite-3/#comments</comments>
		<pubDate>Wed, 13 Aug 2008 15:56:34 +0000</pubDate>
		<dc:creator>Pierre</dc:creator>
		
		<category><![CDATA[Geekitude]]></category>

		<category><![CDATA[mingw]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[sqlite]]></category>

		<guid isPermaLink="false">http://levosgien.net/?p=105</guid>
		<description><![CDATA[	Il n&#8217;est pas possible d&#8217;installer le gem sqlite3-ruby requis par Rails 2.x pour faire fonctionner une application &#8220;par défaut&#8221; si on utilise la version MinGW32 de Ruby packagée dans le projet Ruby Installer 3.0 pour Windows.
	Alors il faut bidouiller un peu&#8230; en fait la modif est tellement simple qu&#8217;elle devrait pouvoir être intégrée directement à [...]]]></description>
			<content:encoded><![CDATA[	<p>Il n&#8217;est pas possible d&#8217;installer le gem sqlite3-ruby requis par Rails 2.x pour faire fonctionner une application &#8220;par défaut&#8221; si on utilise la version MinGW32 de Ruby packagée dans le projet <a href="http://rubyinstaller.rubyforge.org/wiki/wiki.pl?Mingw">Ruby Installer 3.0 pour Windows</a>.</p>
	<p>Alors il faut bidouiller un peu&#8230; en fait la modif est tellement simple qu&#8217;elle devrait pouvoir être intégrée directement à sqlite3-ruby ou à Ruby Installer puisqu&#8217;il sait d&#8217;ores et déjà récupérer des sources, les décompresser et les compiler lui-même&#8230;</p>
	<p>Moi, compiler, ça m&#8217;amuse, alors on y va, même pas peur !</p>
	<p><span id="more-105"></span></p>
	<ul>
		<li>Installez Ruby 1.8 avec le <a href="http://rubyforge.org/projects/rubyinstaller">Ruby One Click Installer</a></li>
		<li>Mettez Rake à jour</li>
	</ul>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;">gem update rake</pre></div></div>

	<ul>
		<li>Installez <a href="http://code.google.com/p/msysgit">MSysGit</a></li>
		<li>Ouvrez la console Bash GIT (clic droit sur un dossier quelconque depuis l&#8217;explorateur Windows : <em>Git Bash Here</em>)</li>
		<li>Clonez le dépôt de <a href="http://github.com/luislavena/rubyinstaller">RubyInstaller</a></li>
	</ul>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #7a0874; font-weight: bold;">source</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #7a0874; font-weight: bold;">source</span>
git clone git:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>luislavena<span style="color: #000000; font-weight: bold;">/</span>rubyinstaller</pre></div></div>

	<ul>
		<li>Construisez Ruby Installer 3.0</li>
	</ul>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> rubyinstaller
rake <span style="color: #007800;">CHEKCOUT</span>=<span style="color: #000000;">1</span>
rake package</pre></div></div>

	<ul>
		<li>Installez le package &#8216;devkit&#8217; qui est dans sous répertoire &#8220;pkg&#8221;</li>
	</ul>
	<ul>
		<li>Enlevez la variable d&#8217;environnement RUBYOPT (qui normalement vaut &#8217;&#8212;rubygems&#8217;)</li>
		<li>Modifiez la variable d&#8217;environnement PATH et changez &#8216;C:\Ruby&#8230;&#8217; en &#8216;C:\Ruby18&#8230;&#8217;</li>
		<li>Vérifiez en lancant Ruby depuis une console DOS</li>
	</ul>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;">C:\<span style="color: #000000; font-weight: bold;">&gt;</span>ruby <span style="color: #660033;">--version</span>
ruby 1.8.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">2008</span>-08-08 patchlevel <span style="color: #000000;">286</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>i386-mingw32<span style="color: #7a0874; font-weight: bold;">&#93;</span></pre></div></div>

	<ul>
		<li>Tentez d&#8217;installer quelques gems</li>
	</ul>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;">gem <span style="color: #c20cb9; font-weight: bold;">install</span> rails 
gem <span style="color: #c20cb9; font-weight: bold;">install</span> capistrano
gem <span style="color: #c20cb9; font-weight: bold;">install</span> merb datamapper sequel 
gem <span style="color: #c20cb9; font-weight: bold;">install</span> fastercvs 
gem <span style="color: #c20cb9; font-weight: bold;">install</span> haml 
gem <span style="color: #c20cb9; font-weight: bold;">install</span> hpricot 
gem <span style="color: #c20cb9; font-weight: bold;">install</span> oniguruma 
gem <span style="color: #c20cb9; font-weight: bold;">install</span> ruport prawn 
gem <span style="color: #c20cb9; font-weight: bold;">install</span> ultraviolet 
gem <span style="color: #c20cb9; font-weight: bold;">install</span> thin</pre></div></div>

	<p>Mais le gem sqlite3-ruby, requis pour faire fonctionner une application Rails &#8220;par défaut&#8221; ne s&#8217;installera pas en version &#8220;native&#8221;, le gem étant préconfiguré pour les plateformes POSIX et même si l&#8217;installation de la version mswin32 est possible (avec l&#8217;option&#8212;platform mswin32), l&#8217;utiliser vous vaudra un message d&#8217;erreur disant que la version pour la plateforme &#8216;mswin32&#8217; n&#8217;est pas compatible avec la version &#8216;mingw32&#8217; qui est installée, d&#8217;autres gems comme mongrel, mongrel_cluster et d&#8217;autres dont la version native n&#8217;est pas installable mais qui sont livrés avec une version mswin32 précompilée fonctionnent.</p>
	<p>Donc il faut installer la version native. Mais elle ne compile pas. Alors il faut qu&#8217;elle compile&#8230; fastoche.</p>
	<ul>
		<li>Récupérez le code de sqlite3-ruby depuis GitHub</li>
	</ul>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #7a0874; font-weight: bold;">source</span>
git clone git:<span style="color: #000000; font-weight: bold;">//</span>github<span style="color: #000000; font-weight: bold;">/</span>jamis<span style="color: #000000; font-weight: bold;">/</span>sqlite3-ruby</pre></div></div>

	<ul>
		<li>Récupérez aussi les <a href="http://www.sqlite.org/sqlite-amalgamation-3_6_1.zip">Sources de SQLite3</a></li>
		<li>Décompressez les fichiers dans sqlite3-ruby\ext\sqlite3-api</li>
		<li>Récupérez la <a href="http://www.sqlite.org/sqlite-3_6_1.zip">DLL de SQLite3</a> précompilée pour Windows</li>
		<li>Décompressez les fichiers dans sqlite3-ruby\ext\sqlite3-api</li>
		<li>Compilez l&#8217;extension</li>
	</ul>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> sqlite3-ruby\ext\sqlite3-api
ruby extconf.rb
<span style="color: #c20cb9; font-weight: bold;">make</span></pre></div></div>

	<p>Là vous devriez voir apparaître un fichier (LE fichier !) sqlite3_api.so</p>
	<p>Ensuite, l&#8217;alternative : gem ou pas gem ?</p>
	<ul>
		<li><em>Gem</em> : commencez par changer Gem::Platform::WIN32 en Gem::Platform::CURRENT dans le fichier sqlite3-ruby-win32.gemspec (RubyGems a changé...)</li>
	</ul>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> ..\..
<span style="color: #666666; font-style: italic;"># Vous devriez être dans 'source/sqlite3-ruby'</span>
gem build sqlite3-ruby-win32.gemspec
gem <span style="color: #c20cb9; font-weight: bold;">install</span> sqlite3-ruby-1.2.2-x86-mingw32.gem</pre></div></div>

	<p><strong>Attention !</strong> Le Gem généré est énorme (plus de 2Mo !), c&#8217;est parce qu&#8217;il embarque tous les fichiers qui sont dans le sous-répertoire ext. Pour bien faire il faudrait encore modifier le gemspec pour qu&#8217;il ne prenne que les fichiers utile (les sources sqlite3-api-wrap.c et sqlite3-api.so, peut-être sqlite3.dll mais certainement pas les .o ni les sources de sqlite, sqlite3.c, sqlite3.h et sqlite3ext.h)</p>
	<ul>
		<li><em>Pas Gem</em> : les fichiers seront installés directement dans l&#8217;arborescence des extensions natives de Ruby (C:\Ruby18\lib\site_ruby)</li>
	</ul>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Vous devriez être dans 'source/sqlite3-ruby'</span>
ruby setup.rb config
ruby setup.rb setup
ruby setup.rb <span style="color: #c20cb9; font-weight: bold;">install</span></pre></div></div>

	<p>Voilà. Normalement vous avez de quoi utiliser SQLite3 !</p>

 ]]></content:encoded>
			<wfw:commentRss>http://levosgien.net/2008/08/13/ruby-installer-30-mingw-et-sqlite-3/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Rails 2.1, ça roule maintenant ! - Le tutoriel complet - 2ème partie</title>
		<link>http://levosgien.net/2008/08/04/rails-21-ca-roule-maintenant-le-tutoriel-complet-2eme-partie/</link>
		<comments>http://levosgien.net/2008/08/04/rails-21-ca-roule-maintenant-le-tutoriel-complet-2eme-partie/#comments</comments>
		<pubDate>Mon, 04 Aug 2008 07:58:35 +0000</pubDate>
		<dc:creator>Pierre</dc:creator>
		
		<category><![CDATA[Geekitude]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[traduction]]></category>

		<category><![CDATA[tutoriel]]></category>

		<guid isPermaLink="false">http://levosgien.net/?p=82</guid>
		<description><![CDATA[	On y est, voici la seconde partie de mon tutoriel sur Rails 2.1. Commencez par la première partie si vous ne l&#8217;avez pas déjà lue.
	
	NdT : Il est très difficile, et à mon avis inutile &#8211; mais comme je suis notoirement fainéant, vous pouvez penser que je ne suis pas le plus objectif pour dire [...]]]></description>
			<content:encoded><![CDATA[	<p>On y est, voici la <strong>seconde partie</strong> de mon tutoriel sur Rails 2.1. Commencez par la <a href="/2008/07/30/rails-21-ca-roule-maintenant-le-tutoriel-complet-1ere-partie/">première partie</a> si vous ne l&#8217;avez pas déjà lue.</p>
	<p><span id="more-82"></span></p>
	<p><strong>NdT</strong> : <em>Il est très difficile, et à mon avis inutile &#8211; mais comme je suis notoirement fainéant, vous pouvez penser que je ne suis pas le plus objectif pour dire ça &#8211; de traduire les noms des concepts techniques de Rails (et de l&#8217;informatique en général) parce que leur traduction littérale en français n&#8217;a aucun sens et ne renseigne pas plus le débutant sur la fonction que l&#8217;expression anglaise qui est constamment utilisée et qu&#8217;elle laisse le geek perplexe, se demandant si c&#8217;est nouveau ou si c&#8217;est seulement mal traduit&#8230; Donc je m&#8217;en tiendrai aux expressions anglaises puisque ce sont elles que vous trouverez dans les docs, les autres tutoriels, les webcasts et les autres ressources sur Rails qui fourmillent sur le net.</em></p>
	<h2>Les Finders et les Named Scopes</h2>
	<p>Voici une autre idée qui a été réalisée, ce sont les <a href="http://pivots.pivotallabs.com/users/nick/blog/articles/284-hasfinder-it-s-now-easier-than-ever-to-create-complex-re-usable-sql-queries">has_finder</a>.</p>
	<p>Pour comprendre ce que sont les named_scopes, nous devons comprendre, avant tout, comment la méthode #find d&#8217;ActiveRecord::Base fonctionne. L&#8217;idée de base est qu&#8217;elle reçoit un tableau associatif d&#8217;options. On les connait déjà, :conditions, :order, :limit, etc.</p>
	<p>Les gems comme has_finder ont ammené l&#8217;idée de fusionner tous ces tableaux associatifs en un seul. Donc si l&#8217;on a 2 tableaux associatifs de finders, chacun avec sa propre option :conditions, il pourrait sembler naturel de pouvoir les combiner en une seule requête cohérente. C&#8217;est le but de la nouvelle fonctionnalité named_scope de Rails 2.1.</p>
	<p>Pour la présenter, commençons par ajouter quelques données bidon dans nos fichiers de fixtures (les jeux de données.) Premièrement dans test/fixtures/posts.yml :</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">post_one:
  title: Hello World
  body: MyText
  created_at: &lt;%= (Time.now - 1.week).to_s(:db) %&gt;
  updated_at: &lt;%= (Time.now - 1.week).to_s(:db) %&gt;
&nbsp;
post_two:
  title: Hello Brazil
  body: MyText
  created_at: &lt;%= (Time.now - 2.weeks).to_s(:db) %&gt;
  updated_at: &lt;%= (Time.now - 2.weeks).to_s(:db) %&gt;
&nbsp;
post_three:
 title: Hello RailsConf
 body: MyText
 created_at: &lt;%= (Time.now).to_s(:db) %&gt;
 updated_at: &lt;%= (Time.now).to_s(:db) %&gt;
&nbsp;
post_four:
 title: Rails 2.1
 body:
 created_at: &lt;%= (Time.now).to_s(:db) %&gt;
 updated_at: &lt;%= (Time.now).to_s(:db) %&gt;
&nbsp;
post_five:
 title: RailsCasts
 body:
 created_at: &lt;%= (Time.now - 1.week).to_s(:db) %&gt;
 updated_at: &lt;%= (Time.now - 1.week).to_s(:db) %&gt;
&nbsp;
post_five:
 title: AkitaOnRails
 body:
 created_at: &lt;%= (Time.now).to_s(:db) %&gt;
 updated_at: &lt;%= (Time.now).to_s(:db) %&gt;</pre></div></div>

	<p>Et ensuite dans test/fixtures/comments.yml :</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">DEFAULTS: &amp;DEFAULTS
  created_at: &lt;%= Time.now.to_s(:db) %&gt;
  updated_at: &lt;%= Time.now.to_s(:db) %&gt;
&nbsp;
comment_one:
  post: post_one
  body: MyText1
  &lt;&lt;: *DEFAULTS
&nbsp;
comment_two:
  post: post_one
  body: MyText2
  &lt;&lt;: *DEFAULTS
&nbsp;
comment_three:
  post: post_one
  body: MyText3
  &lt;&lt;: *DEFAULTS
&nbsp;
comment_four:
  post: post_one
  body: MyText4
  &lt;&lt;: *DEFAULTS
&nbsp;
comment_five:
  post: post_two
  body: MyText5
  &lt;&lt;: *DEFAULTS</pre></div></div>

	<p>Enfin, dans le fichier test/fixtures/users.yml où le plugin restful_authentication a déjà créé quelques données de test qui servent à peupler le modèle User, nous devons seulement corriger un petit bug, une option de formattage oubliée, autour de la ligne 9 (il manque le paramètre :db à la méthode #to_s)</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">remember_token_expires_at: &lt;%= 1.days.from_now.to_s :db %&gt;</pre></div></div>

	<p>Si vous avez fait tout ça correctement, depuis la ligne de commande vous devriez pouvoir lancer :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">rake db:fixtures:load</pre></div></div>

	<p>Maintenant, améliorons notre modèle Post en éditant le fichier app/models/post.rb :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Post <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  has_many <span style="color:#ff3333; font-weight:bold;">:comments</span>
  named_scope <span style="color:#ff3333; font-weight:bold;">:empty_body</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;(body = '' or body is null)&quot;</span>
  named_scope <span style="color:#ff3333; font-weight:bold;">:this_week</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;created_at &gt; ?&quot;</span>, 1.<span style="color:#9900CC;">week</span>.<span style="color:#9900CC;">ago</span>.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:db</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  named_scope <span style="color:#ff3333; font-weight:bold;">:recent</span>, <span style="color:#CC0066; font-weight:bold;">lambda</span> <span style="color:#006600; font-weight:bold;">&#123;</span> |*args| <span style="color:#006600; font-weight:bold;">&#123;</span>:conditions <span style="color:#006600; font-weight:bold;">=&gt;</span>
    <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;created_at &gt; ?&quot;</span>, <span style="color:#006600; font-weight:bold;">&#40;</span>args.<span style="color:#9900CC;">first</span> || 2.<span style="color:#9900CC;">weeks</span>.<span style="color:#9900CC;">ago</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:db</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

	<p>La première modification est assez directe. Pour comprendre ce qu&#8217;elle fait, ouvrons un &#8216;script/console&#8217; (Et pendant qu&#8217;on y est, ouvrons aussi un autre terminal et suivons le fichier log/development.log avec la commande tail -f log/development.log)</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; Post.empty_body
=&gt; ...
&gt;&gt; Post.empty_body.count
=&gt; 2</pre></div></div>

	<p>Voici ce qu&#8217;il devrait se passer dans log/development.log :</p>

<div class="wp_syntax"><div class="code"><pre class="sql sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>body <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">''</span> <span style="color: #993333; font-weight: bold;">OR</span> body <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> 
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> count<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> count_all <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>body <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">''</span> <span style="color: #993333; font-weight: bold;">OR</span> body <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

	<p>C&#8217;est la même chose que si nous avions appelé ces méthodes dans une vieille version de Rails :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; Post.find(:all, :conditions =&gt; &quot;(body = '' or body is null)&quot;)
=&gt; ...
&gt;&gt; Post.count(:conditions =&gt; &quot;(body = '' or body is null)&quot;)
=&gt; 2</pre></div></div>

	<p>Ce n&#8217;est pas tout. Essayons un autre exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; Post.empty_body.this_week
=&gt; ...
&gt;&gt; Post.empty_body.this_week.count
=&gt; 2</pre></div></div>

	<p>Ces méthodes génèrent les requêtes suivantes :</p>

<div class="wp_syntax"><div class="code"><pre class="sql sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>created_at <span style="color: #66cc66;">&gt;</span> <span style="color: #ff0000;">'2008-05-18 09:03:19'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>body <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">''</span> <span style="color: #993333; font-weight: bold;">OR</span> body <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> 
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> count<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> count_all <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>created_at <span style="color: #66cc66;">&gt;</span> <span style="color: #ff0000;">'2008-05-18 09:03:19'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>body <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">''</span> <span style="color: #993333; font-weight: bold;">OR</span> body <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

	<p>Voilà l&#8217;objectif des &#8216;named scopes&#8217; : nommer explicitement des &#8216;sous-ensembles&#8217; significatifs et permettre de les chaîner simplement pour leur donner des significations plus complexes.</p>
	<p>Même lorsque l&#8217;on appelle &#8216;count&#8217;, Rails ne fait pas n&#8217;importe quoi, comme par exemple lire tous les objets concernés, les stocker dans une liste et renvoyer la taille de la liste.</p>
	<p>Vous pouvez voir qu&#8217;il est plutôt subtil dans la manière de fusionner les conditions. Vous pourrez aussi en chaîner autant que vous le voulez &#8211; bien entendu, vous devrez faire quelques essais, mais vous devrez aussi faire attention à ne pas sur-utiliser cette fonctionnalité.</p>
	<p>Il y a quelques pièges à éviter qui ont déjà été expliqués par <a href="http://railscasts.com/episodes/108">Ryan Bates</a>, je vais quand même vous en faire part :</p>
	<ul>
		<li>Le named_scope &#8216;this_week&#8217; est problématique. Regardez la commande &#8216;1.week.ago&#8217;. Comprenez qu&#8217;elle ne sera évaluée qu&#8217;une seule fois pendant toute la durée de vie de cette classe. Ce qui signifie que jusqu&#8217;à ce que vous redémarriez la machine virtuelle Ruby, cette commande ne sera exécutée qu&#8217;une et une seule fois. Alors, si aujourd&#8217;hui nous sommes le &#8220;18 mai 2008&#8221;, cette valeur sera stockée dans la définition de la classe et disons que vous avez été capable de maintenir votre application Rails en ligne pendant des mois. Après cette période, la valeur stockée sera toujours le &#8220;18 mai 2008&#8221;.</li>
	</ul>
	<ul>
		<li>Le named_scope &#8216;recent&#8217; montre comment faire ça correctement. Si vous avez besoin de paramètres dynamiques pour exécuter la requête, vous devez les mettre dans un bloc. Attention, il ne peut y avoir qu&#8217;une seule clé :conditions dans le tableau associatif des options. Nous devons placer la paire :conditions entre les accolades de l&#8217;expression lambda, mais entre ses propres accolades pour pouvoir être différenciée du tableau associatif lui-même (les accolades sont optionnelles si elles ne provoquent pas d&#8217;ambiguité.)</li>
	</ul>
	<p>Il y a une astuce avec l&#8217;étoile (*args) pour permettre d&#8217;avoir une valeur par &#8216;défaut&#8217; dans le cas où le développeur ne fourni pas de date. De cette façon nous pouvons l&#8217;utiliser aussi comme ça :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; Post.recent.count
=&gt; 4
&gt;&gt; Post.recent(2.days.ago).count
=&gt; 3</pre></div></div>

	<p>Qui génère alors ce SQL :</p>

<div class="wp_syntax"><div class="code"><pre class="sql sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> count<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> count_all <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span>created_at <span style="color: #66cc66;">&gt;</span> <span style="color: #ff0000;">'2008-05-11 09:17:49'</span><span style="color: #66cc66;">&#41;</span> 
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> count<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> count_all <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span>created_at <span style="color: #66cc66;">&gt;</span> <span style="color: #ff0000;">'2008-05-23 09:17:51'</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

	<p>Les named_scopes ouvrent pas mal de nouvelles manières créatives et sensées d&#8217;organiser des requêtes complexes en parties plus petites et plus cohésives. Il y a probablement d&#8217;autres pièges à leur utilisation mais nous les trouverons bien assez vite. Essayez-les autant que vous le pouvez parce qu&#8217;ils sont vraiment très utiles.</p>
	<h2>Optimisation du chargement zélé (eager loading)</h2>
	<p>Pendant qu&#8217;on parle des finders, il y a eu un autre changement assez peu médiatisé. Regardez-ça :</p>

<div class="wp_syntax"><div class="code"><pre class="rails rails" style="font-family:monospace;">Post.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:include</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:comments</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

	<p>Jusqu&#8217;à Rails 2.0 nous aurions vu ce genre de chose dans le journal des requêtes SQL :</p>

<div class="wp_syntax"><div class="code"><pre class="sql sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">`posts`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`id`</span> <span style="color: #993333; font-weight: bold;">AS</span> t0_r0<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`posts`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`title`</span> <span style="color: #993333; font-weight: bold;">AS</span> t0_r1<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`posts`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`body`</span> <span style="color: #993333; font-weight: bold;">AS</span> t0_r2<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`comments`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`id`</span> <span style="color: #993333; font-weight: bold;">AS</span> t1_r0<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`comments`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`body`</span> <span style="color: #993333; font-weight: bold;">AS</span> t1_r1 <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">OUTER</span> <span style="color: #993333; font-weight: bold;">JOIN</span> <span style="color: #ff0000;">`comments`</span> <span style="color: #993333; font-weight: bold;">ON</span> comments<span style="color: #66cc66;">.</span>post_id <span style="color: #66cc66;">=</span> posts<span style="color: #66cc66;">.</span>id</pre></div></div>

	<p>Mais maintenant, dans Rails 2.1, la même commande produira des requêtes SQL différentes. En fait, 2 au lieu d&#8217;une seule. <em>&#8220;Et en quoi serait-ce une amélioration ?&#8221;</em> Regardons les requêtes SQL en question :</p>

<div class="wp_syntax"><div class="code"><pre class="sql sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">`posts`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`posts`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`title`</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`posts`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`body`</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> 
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">`comments`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`comments`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`body`</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`comments`</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`comments`</span><span style="color: #66cc66;">.</span>post_id <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">130049073</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">226779025</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">269986261</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">921194568</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">972244995</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

	<p>Le mot clé :include pour le <strong>chargement zélé</strong> (eager loading) a été implémenté pour s&#8217;attaquer au redoutable problème des <a href="http://railscasts.com/episodes/22"><strong>1+N</strong></a>. Avec les associations, lorsque vous chargez l&#8217;objet parent et que vous commencez à lire chaque objet de l&#8217;association un par un, va se poser le problème du <strong>1+N</strong>. Si votre objet parent a 100 enfants, vous allez exécuter 101 requêtes ce qui n&#8217;est pas bon. Une manière d&#8217;optimiser celà est de joindre le tout en utilisant une clause OUTER JOIN dans le SQL, comme ça, les parents et les enfants sont chargés en une seule fois par une seule requête.</p>
	<p>Ca semblait être une bonne idée et en fait, c&#8217;en est une. Mais dans certaines situations, le monstrueux OUTER JOIN peut devenir plus lent que plusieurs requêtes plus petites. Beaucoup de discussions ont eu lieu sur le sujet et vous pouvez obtenir plus de détails en lisant les tickets <a href="http://dev.rubyonrails.org/ticket/9640">9640</a>, <a href="http://dev.rubyonrails.org/ticket/9497">9497</a>, <a href="http://dev.rubyonrails.org/ticket/9560">9560</a>, <a href="http://rails.lighthouseapp.com/projects/8994/tickets/109-patch-ensure-necessary-included-tables-are-joined-in-construct_finder_sql_for_association_limiting">L109</a>.</p>
	<p>Voilà l&#8217;idée : il est généralement plus efficace de découper la monstrueuse jointure en petites requêtes, comme dans l&#8217;exemple précédent. Ca peut permettre d&#8217;éviter la surcharge liée au problème du produit cartésien. Pour les non initiés, regardons l&#8217;exécution de la version OUTER JOIN de la requête :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">mysql&gt; SELECT `posts`.`id` AS t0_r0, `posts`.`title` AS t0_r1, `posts`.`body` AS t0_r2, `comments`.`id` AS t1_r0, `comments`.`body` AS t1_r1 FROM `posts` LEFT OUTER JOIN `comments` ON comments.post_id = posts.id ;
+-----------+-----------------+--------+-----------+---------+
| t0_r0     | t0_r1           | t0_r2  | t1_r0     | t1_r1   |
+-----------+-----------------+--------+-----------+---------+
| 130049073 | Hello RailsConf | MyText |      NULL | NULL    |
| 226779025 | Hello Brazil    | MyText | 816076421 | MyText5 |
| 269986261 | Hello World     | MyText |  61594165 | MyText3 |
| 269986261 | Hello World     | MyText | 734198955 | MyText1 |
| 269986261 | Hello World     | MyText | 765025994 | MyText4 |
| 269986261 | Hello World     | MyText | 777406191 | MyText2 |
| 921194568 | Rails 2.1       | NULL   |      NULL | NULL    |
| 972244995 | AkitaOnRails    | NULL   |      NULL | NULL    |
+-----------+-----------------+--------+-----------+---------+
8 rows in set (0.00 sec)</pre></div></div>

	<p>Faites attention à ceci : est-ce que vous avez vu les doublons des trois premières colonnes (de t0_r0 à t0_r2) ? Elles viennent des colonnes du modèle Post, les autres étant les colonnes correspondant aux commentaires de chacun des post. Notez que le post &#8220;Hello World&#8221; a été lu 4 fois. C&#8217;est comme ça que fonctionne cette jointure : les lignes parentes sont répétées pour chacun de leurs enfants. Ce post en particulier à 4 commentaires, alors il est répété 4 fois.</p>
	<p>Le problème est que ceci va impacter Rails assez fortement parce qu&#8217;il va devoir faire avec pas mal de petits objets à courte durée de vie. La douleur est surtout ressentie du côté de Rails, pas vraiment du côté de MySQL. Maintenant, comparons avec les petites requêtes :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">mysql&gt; SELECT `posts`.`id`, `posts`.`title`, `posts`.`body` FROM `posts`;
+-----------+-----------------+--------+
| id        | title           | body   |
+-----------+-----------------+--------+
| 130049073 | Hello RailsConf | MyText |
| 226779025 | Hello Brazil    | MyText |
| 269986261 | Hello World     | MyText |
| 921194568 | Rails 2.1       | NULL   |
| 972244995 | AkitaOnRails    | NULL   |
+-----------+-----------------+--------+
5 rows in set (0.00 sec)
&nbsp;
mysql&gt; SELECT `comments`.`id`, `comments`.`body` FROM `comments` WHERE (`comments`.post_id IN (130049073,226779025,269986261,921194568,972244995));
+-----------+---------+
| id        | body    |
+-----------+---------+
|  61594165 | MyText3 |
| 734198955 | MyText1 |
| 765025994 | MyText4 |
| 777406191 | MyText2 |
| 816076421 | MyText5 |
+-----------+---------+
5 rows in set (0.00 sec)</pre></div></div>

	<p>En fait, j&#8217;ai triché un peu, j&#8217;ai enlevé les champs created_at et updated_at manuellement des requêtes ci-dessus pour que vous comprenniez mieux ce qui se passe. Voilà ce que nous avons : l&#8217;ensemble de données des posts, séparé et <strong>non doublonné</strong> et celui des commentaires dont le nombre est identique à celui de la requête précédente. Plus l&#8217;ensemble de données est long et complexe, plus c&#8217;est important parce que Rails doit gérer plus d&#8217;objets. Allouer et libérer plusieurs centaines ou milliers de petits objets dupliqués n&#8217;est jamais une bonne chose.</p>
	<p>Mais cette nouvelle fonctionnalité est élégante. Disons que vous vouliez quelque chose comme ça :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; Post.find(:all, :include =&gt; [:comments], :conditions =&gt; [&quot;comments.created_at &gt; ?&quot;, 1.week.ago.to_s(:db)])</pre></div></div>

	<p>Dans Rails 2.1, il comprendra qu&#8217;il y a une condition de filtrage sur la table &#8220;comments&#8221; alors il ne coupera pas la requête, à la place, il préférera générer l&#8217;ancienne version avec la jointure externe :</p>

<div class="wp_syntax"><div class="code"><pre class="sql sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">`posts`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`id`</span> <span style="color: #993333; font-weight: bold;">AS</span> t0_r0<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`posts`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`title`</span> <span style="color: #993333; font-weight: bold;">AS</span> t0_r1<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`posts`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`body`</span> <span style="color: #993333; font-weight: bold;">AS</span> t0_r2<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`posts`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`created_at`</span> <span style="color: #993333; font-weight: bold;">AS</span> t0_r3<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`posts`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`updated_at`</span> <span style="color: #993333; font-weight: bold;">AS</span> t0_r4<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`comments`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`id`</span> <span style="color: #993333; font-weight: bold;">AS</span> t1_r0<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`comments`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`post_id`</span> <span style="color: #993333; font-weight: bold;">AS</span> t1_r1<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`comments`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`body`</span> <span style="color: #993333; font-weight: bold;">AS</span> t1_r2<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`comments`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`created_at`</span> <span style="color: #993333; font-weight: bold;">AS</span> t1_r3<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`comments`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`updated_at`</span> <span style="color: #993333; font-weight: bold;">AS</span> t1_r4 <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">OUTER</span> <span style="color: #993333; font-weight: bold;">JOIN</span> <span style="color: #ff0000;">`comments`</span> <span style="color: #993333; font-weight: bold;">ON</span> comments<span style="color: #66cc66;">.</span>post_id <span style="color: #66cc66;">=</span> posts<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span>comments<span style="color: #66cc66;">.</span>created_at <span style="color: #66cc66;">&gt;</span> <span style="color: #ff0000;">'2008-05-18 18:06:34'</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

	<p>De cette manière les jointures embarquées, les conditions et toutes les autres opérations sur les jointures de tables devraient continuer à marcher correctement. Dans l&#8217;ensemble ça devrait même accélérer vos requêtes. Plusieurs personnes ont déjà rapporté qu&#8217;en recevant plus de  requêtes individuelles, MySQL semblait recevoir plus de CPU d&#8217;un coup. Faites vos exercies et vos tests de stress, analysez et voyez ce qu&#8217;il se passe.</p>
	<h2>Mises à jour partielles et objets altérés (Dirty Objects)</h2>
	<p>Dans les anciens temps, si vous aviez voulu mettre à jour seulement un attribut, vous auriez fait ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">p</span> = Post.<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:#CC0066; font-weight:bold;">p</span>.<span style="color:#9900CC;">title</span> = <span style="color:#996600;">&quot;New Title&quot;</span>
<span style="color:#CC0066; font-weight:bold;">p</span>.<span style="color:#9900CC;">save</span></pre></div></div>

	<p>Voyons quelle tête a le vieux SQL qui été généré :</p>

<div class="wp_syntax"><div class="code"><pre class="sql sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">UPDATE</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #ff0000;">`title`</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'New Title'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`body`</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;MyText&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`created_at`</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;2008-05-25 14:59:21&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`updated_at`</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'2008-05-25 18:14:55'</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #ff0000;">`id`</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">130049073</span></pre></div></div>

	<p>Vous voyez le &#8216;problème&#8217; ? Il réécrit chacun de tous les attributs du modèle, même s&#8217;il n&#8217;ont pas changé d&#8217;un poil. Ca a deux effets pratiques :</p>
	<ul>
		<li>Augmenter la charge de la base de données en cas de mises à jour massives</li>
		<li>Garantir que le modèle reste cohérent (souvenez-vous de ça, nous y reviendrons !)</li>
	</ul>
	<p>Pour résoudre le premier problème une nouvelle fonctionnalité a été ajoutée. Regardons à quoi ressemble le SQL généré par Rails 2.1 :</p>

<div class="wp_syntax"><div class="code"><pre class="sql sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">UPDATE</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #ff0000;">`title`</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'New Title'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`updated_at`</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'2008-05-25 18:14:55'</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #ff0000;">`id`</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">130049073</span></pre></div></div>

	<p>Vous voyez la différence ? Il ne met à jour que les attributs qui ont réellement changé ainsi que la colonne d&#8217;horodatage updated_at, et laisse les autres tranquilles. Sans rien toucher, c&#8217;est comme ça que se comporteront vos mises à jour. Nous avons même quelques nouvelles méthodes pour &#8216;demander&#8217; au modèle ce qu&#8217;il se passe avant d&#8217;envoyer réellement les données dans la base de données :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; p = Post.find(:first)
=&gt; ...
&gt;&gt; p.title = &quot;Another Title&quot;
=&gt; &quot;Another Title&quot;
&gt;&gt; p.changed?
=&gt; true
&gt;&gt; p.changed
=&gt; [&quot;title&quot;]
&gt;&gt; p.changes
=&gt; {&quot;title&quot;=&gt;[&quot;New Title&quot;, &quot;Another Title&quot;]}
&gt;&gt; p.title_changed?
=&gt; true
&gt;&gt; p.title_was
=&gt; &quot;New Title&quot;
&gt;&gt; p.title_change
=&gt; [&quot;New Title&quot;, &quot;Another Title&quot;]
&gt;&gt; p.title_will_change!
=&gt; &quot;Another Title&quot;</pre></div></div>

	<p>Je pense que ce que fait chaque méthode doit vous paraître évident. Il y a maintenant un module <a href="http://caboo.se/doc/classes/ActiveRecord/Dirty.html">ActiveRecord::Dirty</a> qui a été ajouté à la classe ActiveRecord::Base qui offre des possibilités d&#8217;interroger le modèle lui même (#changed?, #changes) ou d&#8217;interroger chaque attribut individuellement simplement en ajoutant les suffixes _changed?, _was et ainsi de suite.</p>
	<p>Tout ceci semble bien sympa, mais souvenez vous : nous n&#8217;avons traité que la première puce de ma liste. Il reste un deuxième problème : la <strong>cohérence des données</strong>.</p>
	<p>Le problème advient lorsqu&#8217;on considère que deux utilisateurs peuvent être en train de mettre à jour le même modèle au même moment. Dans l&#8217;ancienne version ça pouvait aussi se produire et la stratégie était : <em>&#8220;le dernier qui met à jour gagne.&#8221;</em> Ce n&#8217;est peut-être pas la meilleure solution mais au moins on est assurés que tout ce qui est attribué dans le modèle est correct du point de vue d&#8217;au moins un des utilisateurs.</p>
	<p>Avec cette nouvelle fonctionnalité, l&#8217;utilisateur A change un attribut, l&#8217;utilisateur B en change deux autres du même enregistrement et là nous avons potentiellement 3 colonnes incohérentes fusionnées dans la même ligne. Ca peut vite devenir incontrôlable.</p>
	<p>Le problème de la concurrence dans les bases de données n&#8217;est pas nouveau. On connait au moins deux trucs pour le règler, le premier est <a href="http://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html"><strong>Le Verrouillage Pessimiste</strong></a>, où le premier utilisateur pose un verrou qui interdit aux autres utilisateurs de l&#8217;éditer en même temps. Mais dans une application Web, ce n&#8217;est évidemment pas recommandé. La deuxième option c&#8217;est <a href="http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html"><strong>Le Verrouillage Optimiste</strong></a>.</p>
	<p>Pour l&#8217;activer il faut ajouter une colonne nommée &#8216;lock_version&#8217; de type entier dont la valeur initiale par défaut est &#8216;0&#8217; puis :</p>
	<ul>
		<li>Les utilisateurs A et B chargent le même enregistrement.</li>
		<li>A termine son travail et met à jour l&#8217;enregistrement.</li>
		<li>La colonne &#8216;lock_version&#8217; est incrémentée.</li>
		<li>B termine lui aussi et tente de mettre à jour l&#8217;enregistrement. L&#8217;opération va échouer parce que la commande SQL générée va chercher à mettre à jour l&#8217;enregistrement dont le champ &#8216;lock_version&#8217; vaut &#8216;0&#8217; mais il a déjà été incrémenté et il vaut &#8216;1&#8217;.</li>
	</ul>
	<p>De cette manière nous avons réellement bloqué les mises à jour indésirables tout en donnant à l&#8217;utilisateur B une chance de relire l&#8217;enregistrement contenant les modifications de A et de réévaluer ses propres modifications.</p>
	<p>C&#8217;est une technique à utiliser avec discernement, uniquement lorsqu&#8217;elle est nécessaire. Ne commencez pas à ajouter des colonnes &#8216;lock_version&#8217; dans toutes les tables comme des dingues. Autre chose, si pour de bonnes raisons personnelles vous n&#8217;aimiez pas ces Mises à Jour Partielles, vous pourriez les désactiver dans le fichier environment.rb comme ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">partial_updates</span> = <span style="color:#0000FF; font-weight:bold;">false</span> <span style="color:#008000; font-style:italic;"># the default is true</span></pre></div></div>

	<p>Il y a eu d&#8217;autres améliorations de performances, lisez <a href="http://blog.pluron.com/2008/01/ruby-on-rails-i.html">Nimble</a>. Mais aussi <a href="http://railscasts.com/episodes/109">Ryan Bates</a> et <a href="http://ryandaigle.com/articles/2008/4/1/what-s-new-in-edge-rails-partial-updates">Ryan Daigle</a> à ce sujet.</p>
	<h2>D&#8217;autres gadgets pour ActiveRecord</h2>
	<p>Pour les exemples suivants, lançons script/console pour une autre nouvelle fonctionnalité bien pratique :</p>

<div class="wp_syntax"><div class="code"><pre class="rails rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&gt;&gt;</span> Post.<span style="color:#5A0A0A; font-weight:bold;">first</span> <span style="color:#008000; font-style:italic;"># 1</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> ...
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> Post.<span style="color:#5A0A0A; font-weight:bold;">last</span>  <span style="color:#008000; font-style:italic;"># 2</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> ...
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> Post.<span style="color:#9900CC;">empty_body</span>.<span style="color:#5A0A0A; font-weight:bold;">first</span>       <span style="color:#008000; font-style:italic;"># 3</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> ...
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> Post.<span style="color:#9900CC;">empty_body</span>.<span style="color:#9900CC;">recent</span>.<span style="color:#5A0A0A; font-weight:bold;">last</span> <span style="color:#008000; font-style:italic;"># 4</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> ...
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> Post.<span style="color:#9900CC;">all</span>            <span style="color:#008000; font-style:italic;"># 5</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> ...
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> Post.<span style="color:#9900CC;">empty_body</span>     <span style="color:#008000; font-style:italic;"># 6</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> ...
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> Post.<span style="color:#9900CC;">empty_body</span>.<span style="color:#9900CC;">all</span> <span style="color:#008000; font-style:italic;"># 7</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> ...</pre></div></div>

	<p>ActiveRecord a 3 nouveaux raccourcis, #first, #last et #all, qui évitent de taper find(:first), find(:last) ou find(:all). La bonne nouvelle : ils marchent aussi avec les <strong>named_scopes</strong> ! Regardons le SQL généré pour comprendre ce qu&#8217;ils font :</p>

<div class="wp_syntax"><div class="code"><pre class="sql sql" style="font-family:monospace;"><span style="color: #66cc66;">//</span> <span style="color: #cc66cc;">1</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">1</span>
<span style="color: #66cc66;">//</span> <span style="color: #cc66cc;">2</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> posts<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">DESC</span> <span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">1</span>
<span style="color: #66cc66;">//</span> <span style="color: #cc66cc;">3</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>body <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">''</span> <span style="color: #993333; font-weight: bold;">OR</span> body <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">1</span>
<span style="color: #66cc66;">//</span> <span style="color: #cc66cc;">4</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>created_at <span style="color: #66cc66;">&gt;</span> <span style="color: #ff0000;">'2008-05-11 19:55:33'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>body <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">''</span> <span style="color: #993333; font-weight: bold;">OR</span> body <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> posts<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">DESC</span> <span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">1</span>
<span style="color: #66cc66;">//</span> <span style="color: #cc66cc;">5</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span>
<span style="color: #66cc66;">//</span> <span style="color: #cc66cc;">6</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>body <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">''</span> <span style="color: #993333; font-weight: bold;">OR</span> body <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">//</span> <span style="color: #cc66cc;">7</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #ff0000;">`posts`</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>body <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">''</span> <span style="color: #993333; font-weight: bold;">OR</span> body <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

	<p>J&#8217;ai numéroté pour vous, à la fois les appels de méthodes Rails et les requêtes SQL générées ci-dessus pour vous permettre de suivre. C&#8217;est assez clair. La nouveauté ici c&#8217;est l&#8217;option :last. En fait elle trie les résultats en utilisant la clé primaire et ne récupère que le dernier. Faites bien attention à la signification de &#8220;dernier&#8221;, dans ce cas, il signifie <em>&#8220;la plus grande clé primaire&#8221;</em> et pas quelque chose comme <em>&#8220;le dernier enregistrement mis à jour&#8221;</em>. Pour ça, il vaut mieux créer un named_scope &#8216;last_updated&#8217;, par example.</p>
	<p>Autre nouvelle fonctionnalité dans Rails 2.1, le support des associations <strong>has_one :through</strong>. Je suis désolé de ne pas avoir de bon cas d&#8217;utilisation de cette fonctionnalité dans cette démo, mais je vais essayer quelque chose à titre d&#8217;exemple pour la tester.</p>
	<p>Commençons par créer deux nouveaux échaffaudages :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">./script/generate scaffold Company name:string
./script/generate scaffold Role</pre></div></div>

	<p>Puis éditions le fichier db/migrate/20080526004326_create_roles.rb (encore une fois, vos horodatages seront différents) comme ça :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> CreateRoles <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>
    change_table <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#9966CC; font-weight:bold;">do</span> |t|
      t.<span style="color:#9900CC;">belongs_to</span> <span style="color:#ff3333; font-weight:bold;">:company</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>
    change_table <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#9966CC; font-weight:bold;">do</span> |t|
      t.<span style="color:#9900CC;">remove_belongs_to</span> <span style="color:#ff3333; font-weight:bold;">:company</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 nom de la migration est un peu trompeur parce qu&#8217;on a déjà une autre migration pour créer la table &#8216;roles&#8217;. Cette fois nous nous contentons d&#8217;ajouter une nouvelle colonne. Créons maintenant les associations :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># app/models/company.rb</span>
<span style="color:#9966CC; font-weight:bold;">class</span> Company
  has_many <span style="color:#ff3333; font-weight:bold;">:roles</span>
  has_many <span style="color:#ff3333; font-weight:bold;">:users</span>, <span style="color:#ff3333; font-weight:bold;">:through</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:roles</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># app/models/role.rb</span>
<span style="color:#9966CC; font-weight:bold;">class</span> Role
  belongs_to <span style="color:#ff3333; font-weight:bold;">:user</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:company</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># app/models/user.rb</span>
<span style="color:#9966CC; font-weight:bold;">class</span> User
  has_many <span style="color:#ff3333; font-weight:bold;">:roles</span>
  has_one <span style="color:#ff3333; font-weight:bold;">:company</span>, <span style="color:#ff3333; font-weight:bold;">:through</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:roles</span>, <span style="color:#ff3333; font-weight:bold;">:order</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'created_at DESC'</span>
  ...
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

	<p>Ouvrons maintenant un autre script/console pour tester ces nouvelles associations :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; admin = Role.create(:name =&gt; &quot;Administrator&quot;)
=&gt; ...
&gt;&gt; acme = Company.create(:name =&gt; &quot;Acme LLC&quot;)
=&gt; #
&gt;&gt; admin.company = acme
&gt; ...</pre></div></div>

	<p>Nous avons commencé par créer un nouveau Role et une nouvelle Company puis nous les avons associés.</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; user = User.find(:first)
=&gt; ...
&gt;&gt; user.roles &lt;&lt; admin
=&gt; ...
&gt;&gt; user.save
=&gt; true</pre></div></div>

	<p>Puis nous avons cherché un utilisateur dans notre base de données et nous lui avons associé le nouveau rôle.</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; admin.reload
=&gt; ...
&gt;&gt; admin.user
=&gt; ...
&gt;&gt; admin.company
=&gt; #
&gt;&gt; user.company
=&gt; #</pre></div></div>

	<p>Et voilà les choses intéressantes. Premièrement nous avons rechargé le rôle, pour être sûrs. Nous nous assurons qu&#8217;il est correctement associé à l&#8217;utilisateur et à la nouvelle entreprise.</p>
	<p>Ce qui est intéressant c&#8217;est que l&#8217;utilisateur est associé directement à une et une seule entreprise par l&#8217;intermédiaire de son rôle. Ce à quoi il faut faire attention c&#8217;est que l&#8217;utilisateur peut avoir plusieurs autres (has_many) rôles. C&#8217;est pourquoi la méthode de classe has_one supporte la plupart des options des finders comme :conditions et, comme dans l&#8217;exemple précédent, :order. Elle limitera toujours l&#8217;ensemble de résulats à 1 en ne récupérant que la première ligne même s&#8217;il y en a plusieurs, alors faites attentions aux incohérences de votre modèle métier si vous ne faites pas assez de tests.</p>
	<h2>Améliorations d&#8217;ActiveResource</h2>
	<p>Nous nous amusons avec le projet &#8216;blog&#8217; que nous avons commencé dans <a href="/2007/12/12/rolling-with-rails-2-0-the-first-full-tutorial">Rolling with Rails 2</a>. Mais il y en avait un autre très petit que nous avions créé dans <a href="/2007/12/12/rolling-with-rails-2-0-the-first-full-tutorial-part-2">la partie 2</a> qui s&#8217;appelle &#8216;blog_remote&#8217;. On va maintenant le réutiliser pour découvrir les nouvelles fonctionnalités d&#8217;ActiveResource.</p>
	<p>Avant tout, si vous êtes arrivés jusqu&#8217;ici, vous devriez vous trouver dans le répertoire du projet &#8216;blog&#8217;. Démarrez le serveur, comme d&#8217;habitude avec &#8217;./script/server&#8217;. Il devrait se charger et écouter le port 3000 par défaut (si vous n&#8217;avez pas changé vos options d&#8217;environement.)</p>
	<p>Depuis un autre termina, ouvrez le projet &#8216;blog_remote&#8217; depuis lequel nous allons tester de nouvelles fonctionnalités de Rails 2.1 :</p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;">$ <span style="color: #7a0874; font-weight: bold;">cd</span> ..<span style="color: #000000; font-weight: bold;">/</span>blog_remote</pre></div></div>

	<p>Vous devez suivre les étapes décrites dans la première partie de ce tutoriel pour autoriser ce projet à utiliser la dernière version de Rails installée au niveau système. Sinon, gelez simplement la dernière version du dépôt de Rails ou, éventuellement copiez la version de Rails utilisée par le projet &#8216;blog&#8217;.</p>
	<p>Souvenez-vous que nous avons un app/models/post.rb comme celui-là :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Post <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveResource::Base</span>
  <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">site</span> = <span style="color:#996600;">'http://akita:akita@localhost:3000/admin'</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

	<p>Ca servait à mettre en avant le fait que l&#8217;authentification HTTP était inclue dans Rails 2.0. Mais, si vous êtes comme moi, vous n&#8217;aimez peut-être pas plus que ça le fait de devoir concaténer le nom d&#8217;utilisateur et le mot de passe dans l&#8217;URL. Il y a eu quelques solutions pour régler ça, mais dans Rails 2.1, on peut finalement faire comme ça :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Post <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveResource::Base</span>
  <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">site</span> = <span style="color:#996600;">'http://localhost:3000/admin'</span>
  <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">user</span> = <span style="color:#996600;">'akita'</span>
  <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">password</span> = <span style="color:#996600;">'akita'</span>
  <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">timeout</span> = <span style="color:#006666;">5</span> <span style="color:#008000; font-style:italic;"># c'est IMPORTANT!</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

	<p>Ca devrait rendre les choses un peu plus simple à maintenir. Mais la plus intéressante est l&#8217;option de configuration #timeout. C&#8217;est même très important parce que le timeout (délai de garde) HTTP par défaut est de <strong>60 secondes</strong>. Alors, si pour une raison ou une autre, l&#8217;application distante est indisponible, votre application devra attendre jusqu&#8217;à une minute avant de lever une exception.</p>
	<p>Vous pouvez imaginer que ce n&#8217;est pas très efficace, parce que ca peut potentiellement bloquer toutes vos instances de Rails pour au moins une minute. Testez et analysez vos requêtes distantes, faites en sorte qu&#8217;elles soient petites et essayez de trouver le plus petit timeout possible pour votre application. Plus d&#8217;informations <a href="http://blog.codefront.net/2008/04/22/new-in-rails-activeresource-timeouts-and-why-it-matters/">ici</a> et, bien sûr, nous vous recommandons de faire le moins d&#8217;appels distants possible dans un site web public. Mettez en cache ce que vous pouvez au lieu de devoir sortir tout le temps pour la moindre requête.</p>
	<p>Pour vérifier que tout est en ordre et fonctionne (le serveur du projet &#8216;blog&#8217; doit fonctionner,) depuis &#8216;blog_remote&#8217;, ouvrez &#8216;script/console&#8217; :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; Post.find(:all)
=&gt; [...]</pre></div></div>

	<p>Vous devriez voir les objets arriver dans le tuyau depuis le projet de blog &#8216;distant&#8217;. Référez-vous à mon tutoriel sur Rails 2.0 pour comprendre comment tout ça a été assemblé.</p>
	<h2>Et bien plus encore</h2>
	<p>Il y a eu des centaines de changements dans Rails 2.1, et pas mal d&#8217;améliorations. Une chose que j&#8217;aime en particulier c&#8217;est l&#8217;optimisation du routage. Oleg Andreev a le <a href="http://www.novemberain.com/2008/1/17/routes-recognition">scoop</a>. Ca doit être pratiquement transparent pour nous.<br />
Beaucoup de tests d&#8217;ActiveRecord ont été nettoyés par John Barnette, la documentation a été sérieusement revue grâce à Pratik Naik. Les attributs d&#8217;ActiveRecord sont maintenant moins coûteux&#8230;</p>
	<p><a href="http://blog.codefront.net/2008/02/06/living-on-the-edge-of-rails-6-better-performance-git-support-and-more/">Redemtion in a Blog</a> a aussi suivi le moindre petit changement dans Rails Edge et je vais lui emprunter les morceaux les plus intéressants.</p>
	<p>Un morceau intéressant est l&#8217;aliasage des ressources. Vous pouvez maintenant faire ceci dans votre config/routes.rb :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">map.<span style="color:#9900CC;">resources</span> <span style="color:#ff3333; font-weight:bold;">:comments</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'comentarios'</span></pre></div></div>

	<p>De cette manière http://your_site/comentarios doit se comporter exactement de la même manière que http://your_site/comments. C&#8217;est probablement une bonne chose pour les développeurs web qui aiment l&#8217;optimisation pour les moteurs de recherche (SEO). Vous trouverez encore plus de trucs sur l&#8217;alisage des ressources dans le plugin de Carlos Brando <a href="http://www.nomedojogo.com/custom-resource-name-plugin/">Custom Resource Name</a> qui devrait même fonctionner avec d&#8217;anciennes versions de Rails. Et puisqu&#8217;on parle de mapping, maintenant vous pouvez aussi faire ça :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">map.<span style="color:#9900CC;">new_session</span> <span style="color:#ff3333; font-weight:bold;">:controller</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'sessions'</span>, <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'new'</span>
map.<span style="color:#9900CC;">root</span> <span style="color:#ff3333; font-weight:bold;">:new_session</span></pre></div></div>

	<p>&#8216;map.root&#8217; accepte maintenant un symbole comme argument pour définir le chemin racine de l&#8217;application.</p>
	<p>Ryan Bates <a href="http://railscasts.com/episodes/75">s&#8217;est plaint</a> (et a écrit un correctif) pour cette utilisation particulière de fields_for :</p>

<div class="wp_syntax"><div class="code"><pre class="rails rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#5A0A0A; font-weight:bold;">fields_for</span> <span style="color:#996600;">&quot;project[task_attributes][]&quot;</span>, task <span style="color:#9966CC; font-weight:bold;">do</span> |f| <span style="color:#006600; font-weight:bold;">%&gt;</span>
  <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">text_field</span> <span style="color:#ff3333; font-weight:bold;">:name</span>, <span style="color:#ff3333; font-weight:bold;">:index</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">nil</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
  <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#5A0A0A; font-weight:bold;">hidden_field</span> <span style="color:#ff3333; font-weight:bold;">:id</span>, <span style="color:#ff3333; font-weight:bold;">:index</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">nil</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></pre></div></div>

	<p>Notez le :index => nil qui fait un peu &#8216;tache&#8217;. Maintenant vous pouvez écrire simplement :</p>

<div class="wp_syntax"><div class="code"><pre class="rails rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#5A0A0A; font-weight:bold;">fields_for</span> <span style="color:#996600;">&quot;project[task_attributes][]&quot;</span>, task, <span style="color:#ff3333; font-weight:bold;">:index</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">nil</span> <span style="color:#9966CC; font-weight:bold;">do</span> |f| <span style="color:#006600; font-weight:bold;">%&gt;</span>
  <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">text_field</span> <span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
  <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#5A0A0A; font-weight:bold;">hidden_field</span> <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></pre></div></div>

	<p>Et nous avons un autre raccourci bien pratique pour les vues. Au lieu de faire ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="rails rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#5A0A0A; font-weight:bold;">form_for</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:person</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> |f| <span style="color:#006600; font-weight:bold;">%&gt;</span>
  <span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">render</span> <span style="color:#ff3333; font-weight:bold;">:partial</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'form'</span>, <span style="color:#ff3333; font-weight:bold;">:locals</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:form</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> f <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></pre></div></div>

	<p>Vous pouvez utiliser cette version courte :</p>

<div class="wp_syntax"><div class="code"><pre class="rails rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#5A0A0A; font-weight:bold;">form_for</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:person</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> |f| <span style="color:#006600; font-weight:bold;">%&gt;</span>
  <span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">render</span> <span style="color:#ff3333; font-weight:bold;">:partial</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> f <span style="color:#006600; font-weight:bold;">%&gt;</span>
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></pre></div></div>

	<p>Ce qui est significativement plus lisible et maintenable que la version précédente. Néanmoins, les deux devraient continuer à fonctionner dans Rails 2.1.</p>
	<p>Et puis, pour les projets qui font un usage intensif des téléchargements de fichiers, nous avons maintenant un meilleur moyen de gérer le transfert des gros fichiers qui évite de bloquer complètement une instance de Mongrel :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">send_file <span style="color:#996600;">'/path/to.png'</span>, <span style="color:#ff3333; font-weight:bold;">:x_sendfile</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>, <span style="color:#ff3333; font-weight:bold;">:type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'image/png'</span></pre></div></div>

	<p>L&#8217;ancienne méthode &#8216;send_file&#8217; accepte maintenant la configuration :x_sendfile des entêtes. De ce que j&#8217;en ai compris, elle demande aux serveurs HTTP comme  Apache et LightTPD de gérer le transfert du fichier tout en laissant l&#8217;instance de Rails transquile pour gérer les autres requêtes. Cette technique a déjà été expliquée par <a href="http://john.guen.in/past/2007/4/17/send_files_faster_with_xsendfile/">John Guenin</a> et il était nécessaire d&#8217;installer un plugin. Mais dans Rails 2.1 c&#8217;est par défaut.</p>
	<h2>Conclusion</h2>
	<p>Rails 2.1 apporte son lot d&#8217;améliorations et d&#8217;optimisations et elles sont vraiment bienvenues. Si vous utilisez déjà Rails 2, cette mise à jour devrait fonctionner pratiquement sans rien faire. Encore une fois, si vous utilisez une version Rails 1.2 ou plus ancienne, vous n&#8217;avez pas de raison de ne pas tenter de faire la mise à jour.</p>
	<p>Au lieu de demander <em>&#8220;Puis-je/Dois-je mettre à jour mes projets vers Rails 2.1?&#8221;</em> vous devez plutôt vous demander <em>&#8220;Est-ce que j&#8217;ai un jeu de tests complet ?&#8221;</em> Si c&#8217;est le cas, tant mieux, vous devriez pouvoir faire la mise à jour sans problème et voir ce que vos tests vous racontent. S&#8217;il n&#8217;y a que quelques bugs, vous devriez pouvoir les corriger en moins d&#8217;une journée. Mais si vous n&#8217;avez pas une couverture complète de tests, alors vous devrez investir le temps nécessaire pour écrire les tests qui couvriront toute votre application, et seulement après, songer à faire la mise à jour.</p>
	<p>Les optimisations de performances à elles seules suffisent à justifier la mise à jour vers Rails 2.1.</p>

 ]]></content:encoded>
			<wfw:commentRss>http://levosgien.net/2008/08/04/rails-21-ca-roule-maintenant-le-tutoriel-complet-2eme-partie/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Rails 2.1, ça roule maintenant ! - Le tutoriel complet - 1ère partie</title>
		<link>http://levosgien.net/2008/07/30/rails-21-ca-roule-maintenant-le-tutoriel-complet-1ere-partie/</link>
		<comments>http://levosgien.net/2008/07/30/rails-21-ca-roule-maintenant-le-tutoriel-complet-1ere-partie/#comments</comments>
		<pubDate>Tue, 29 Jul 2008 22:02:10 +0000</pubDate>
		<dc:creator>Pierre</dc:creator>
		
		<category><![CDATA[Geekitude]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[traduction]]></category>

		<category><![CDATA[tutoriel]]></category>

		<guid isPermaLink="false">http://levosgien.net/?p=65</guid>
		<description><![CDATA[	Cet article est la traduction de la première partie de l&#8217;article Rolling With Rails 2.1 de Fabio Akita, j&#8217;ai conservé le style de Fabio à la première personne, c&#8217;est donc Fabio qui parle dans la suite de ce texte (là c&#8217;était moi, vous avez compris) et mis à jour les exemples avec ce qui est [...]]]></description>
			<content:encoded><![CDATA[	<p>Cet article est la traduction de la première partie de l&#8217;article <a href="http://www.akitaonrails.com/2008/5/25/rolling-with-rails-2-1-the-first-full-tutorial-part-1">Rolling With Rails 2.1</a> de <a href="http://www.akitaonrails.com">Fabio Akita</a>, j&#8217;ai conservé le style de Fabio à la première personne, c&#8217;est donc Fabio qui parle dans la suite de ce texte (là c&#8217;était moi, vous avez compris) et mis à jour les exemples avec ce qui est produit par la version finale de Rails 2.1.</p>
	<p>Je vais reprendre exactement là où nous nous étions arrêtés dans le précédent tutoriel, si vous ne l&#8217;avez pas lu, je vous suggère de le faire maintenant ou de télécharger le code qui est disponible sur <a href="http://github.com/akitaonrails/rolling_with_rails_tutorial/tree/master">GitHub</a>. J&#8217;ai ajouté un tag &#8216;for_2.0&#8217; pour ce qui concerne le précédent tuto et un nouveau tag &#8216;for_2.1&#8217; pour les mises à jour que je suis sur le point de vous montrer dans ce nouvel article. Vous pouvez soit suivre mon précédent tutoriel pour voir tout fonctionner ou le sauter et vous contenter de télécharger le code d&#8217;exemple depuis ma page GitHub.</p>
	<p>Pour la suite de cet article, je vais considérer que vous avez le projet &#8216;blog&#8217; dans un répertoire de votre machine. Peu importe que vous l&#8217;ayez décompressé depuis le tarball ou que vous ayez cloné l&#8217;arbre complet depuis mon dépôt GitHub.</p>
	<p>Ceci est la première partie et voici la <a href="/2008/08/04/rails-21-ca-roule-maintenant-le-tutoriel-complet-2eme-partie/">deuxième partie</a>.</p>
	<p><span id="more-65"></span></p>
	<h2>Installation</h2>
	<p>Avant de commencer, je vous recommande de faire ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">$ gem update --system</pre></div></div>

	<p>Ou, si vous avez RubyGems 0.8.4 ou une version plus ancienne, d&#8217;essayer ça :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">$ gem install rubygems-update
$ update_rubygems</pre></div></div>

	<p>Puis, pour installer Rails 2.1 de faire :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">$ gem install rails</pre></div></div>

	<p>A moins que vous ne vouliez geler les gems de rails dans votre projet, dans ce cas faites :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">$ rake rails:freeze:gems</pre></div></div>

	<p>Bien entendu, vous devez lancer cette tâche depuis la racine de votre projet. Pour ce tutoriel, j&#8217;ai utilisé la version 2.1 de Rails que j&#8217;ai cloné depuis GitHub, directement depuis le trunk de Rails Edge :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">$ cd blog
$ git clone git://github.com/rails/rails.git vendor/rails</pre></div></div>

	<p>La ligne ci-dessus suppose que vous connaissez git et que vous l&#8217;avez installé correctement. Si ce n&#8217;est pas le cas, récupérez simplement la &#8220;tarball&#8221; de Rails : http://github.com/rails/rails/tarball/master depuis le site GitHib et décompressez la dans le dossier vendor/rails de votre projet.</p>
	<p>EN gardant cela à l&#8217;esprit, si vous avez déjà un projet Rails en place &#8211; c&#8217;est le &#8220;blog&#8221; dans notre exemple &#8211; n&#8217;oubliez pas que vous devez mettre à jour quelques resssources de Rails comme ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">$ rake rails:update</pre></div></div>

	<p>A partir de Rails 2.1, la prochaine fois que vous devrez mettre à jour les gems de Rails (quand la version 2.2 ou une autre sera sortie,) cette étape ne sera plus nécessaire. Le gel des gems mettra à jour les ressources Rails de votre projet automatiquement pour vous.</p>
	<p>Après ça, la première chose que vous devrez faire dans le fichier <strong>config/environment.rb</strong> sera de mettre à jour le numéro de la version de Rails dont votre projet dépend :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">RAILS_GEM_VERSION = <span style="color:#996600;">'2.1.0'</span></pre></div></div>

	<p>En pratique, cette modification n&#8217;aura d&#8217;effet que si vous utilisez la version de Rails installée comme un gem au niveau du système, si vous avez gelé Rails dans votre projet, c&#8217;est la version dans vendor/rails qui aura la prévalence sur la version installée dans le système.</p>
	<p>Enfin, ajoutez un nouveau fichier appelé <strong>config/initializers/new_rails_defaults.rb</strong> contenant ce qui suit :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># These settins change the behavior of Rails 2 apps and will be defaults</span>
<span style="color:#008000; font-style:italic;"># for Rails 3. You can remove this initializer when Rails 3 is released.</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Only save the attributes that have changed since the record was loaded.</span>
<span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">partial_updates</span> = <span style="color:#0000FF; font-weight:bold;">true</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Include ActiveRecord class name as root for JSON serialized output.</span>
<span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">include_root_in_json</span> = <span style="color:#0000FF; font-weight:bold;">true</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Use ISO 8601 format for JSON serialized times and dates</span>
ActiveSupport.<span style="color:#9900CC;">use_standard_json_time_format</span> = <span style="color:#0000FF; font-weight:bold;">true</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Don't escape HTML entities in JSON, leave that for the #json_escape helper</span>
<span style="color:#008000; font-style:italic;"># if you're including raw json in an HTML page.</span>
ActiveSupport.<span style="color:#9900CC;">escape_html_entities_in_json</span> = <span style="color:#0000FF; font-weight:bold;">false</span></pre></div></div>

	<h2>Dépendances aux RubyGems</h2>
	<p>La première chose que vous allez trouver dans le nouveau fichier environment.rb est de quoi gérer les dépendances de votre projet avec les gems qu&#8217;il utilise. Par exemple, ajoutons le code suivant dans le bloc Initializer :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;haml&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;1.8&quot;</span>
config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;launchy&quot;</span>
config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;defunkt-github&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:lib</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'github'</span>, <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;http://gems.github.com&quot;</span></pre></div></div>

	<p>Pour l&#8217;instant, oubliez à quoi servent ces gems et regardons seulement ce que nous pouvons faire. Depuis la ligne de commande, nous pouvons utiliser :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">$ rake gems</pre></div></div>

	<p>Voici le résultat :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">[ ] haml = 1.8
[ ] launchy 
[ ] defunkt-github 
&nbsp;
I = Installed
F = Frozen</pre></div></div>

	<p>Un bon conseil : si votre projet dépend d&#8217;un quelconque gem, soyez sur de l&#8217;avoir ajouté à la liste qui est dans le fichier environment.rb. Je vous recommande même d&#8217;indiquer de quelle version du gem vous dépendez, de cette manière, vous serez sûr de ne pas être surpris par un nouveau bug étrange qui arrivera parce que vous aurez mis à jour vos gems système et qu&#8217;un de ceux qui aura été mis à jour et dont vous dépendez aura cassé votre projet. Ca m&#8217;est déjà arrivé et je pense qu&#8217;il vaut mieux être prudent.</p>
	<p>La méthode &#8216;config.gem&#8217; accepte en paramètres le nom du gem et un tableau associatif d&#8217;options. Utilisez :version pour ajouter une condition sur le numéro de version (vous pouvez préciser >, <, =, >=, <=,) :source pour spécifier une adresse d&#8217;un dépôt de gems non standard et utilisez :lib si le chemin d&#8217;installation ne peut pas être déduit du nom du gem.</p>
	<p>Revenons à ce que nous avons ajouté avant et disséquons chaque ligne :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;haml&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;1.8&quot;</span></pre></div></div>

	<p>Ca signifie que votre application nécessire la version 1.8 du gem de <a href="http://haml.hamptoncatlin.com/">HAML</a> (même si, l&#8217;excellent Hampton Caitlin vient juste de sortir HAML 2.0.2). C&#8217;est un exemple de cas où nous devons geler une version antérieure à la version courante.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;launchy&quot;</span>
config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;defunkt-github&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:lib</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'github'</span>, <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;http://gems.github.com&quot;</span></pre></div></div>

	<p>Habituellement, la commande &#8216;gem&#8217; cherchera les gems dans le dépôt &#8216;official&#8217; sur gems.rubyforge.org. Mais maintenant nous avons un autre endroit qui devient de plus en plus populaire et qui est <a href="http://gems.github.com/">Github</a>. Comme la commande gem standard ne sait rien de ce dépôt, nous devons la spécifier explicitement en utilisant l&#8217;option :source.</p>
	<p>Un autre détail : le nom du gem sur GitHub suit une convention différence de RubyForge : <em>&#8221;[nom de l&#8217;utilisateur]-[nom du gem]&#8221;</em>, bien que l&#8217;utilisateur <a href="http://github.com/defunkt">defunkt</a> (qui est le grand Chris Wanstrath lui-même) ait un gem nommé <a href="http://github.com/defunkt/github-gem/tree/master">github-gem</a> la commande &#8216;require&#8217; doit le charger depuis la lib nommée &#8216;github&#8217;, sans le préfixe &#8216;defunkt&#8217;, nous utilisons donc l&#8217;option :lib pour l&#8217;indiquer. Le gem &#8216;launchy&#8217; n&#8217;est là que parce que &#8216;github-gem&#8217; en dépend.</p>
	<p>Nous n&#8217;utiliserons aucun de ces gems dans notre projet de blog de démo, ils sont juste là pour illustrer la nouvelle fonctionnalité de Rails 2.1. Maintenant que nous avons indiqué de quels gems nous dépendons, et que le résultat de la commande nous a montré qu&#8217;ils n&#8217;étaient pas installés sur notre système, nous pouvons les installer de cette façon :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">$ sudo rake gems:install</pre></div></div>

	<p>Si vous êtes sous Windows, ignorez toujours que j&#8217;utilise la commande <strong>sudo</strong>, mais sur les systèmes Unix (comme Linux et OS X) nous ne pouvons probablement rien installer dans /usr/local ou /opt sans les autorisations adaptées, d&#8217;où le &#8216;sudo&#8217;. Cette commande doit revoyer quelque chose comme ça (tout dépend s&#8217;ils sont, ou pas, déjà installés) :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">gem install haml --version &quot;= 1.8&quot;
ERROR:  While generating documentation for haml-1.8.0
... MESSAGE:   Unhandled special: Special: type=17, text=&quot;&lt;!-- This is the peanutbutterjelly element --&gt;&quot;
... RDOC args: --ri --op /usr/lib64/ruby/gems/1.8/doc/haml-1.8.0/ri --title Haml --main README --exclude lib/haml/buffer.rb --line-numbers --inline-source --quiet lib VERSION MIT-LICENSE README
(continuing with the rest of the installation)
Successfully installed haml-1.8.0
1 gem installed
Installing ri documentation for haml-1.8.0...
Installing RDoc documentation for haml-1.8.0...
gem install launchy
Successfully installed launchy-0.3.2
1 gem installed
Installing ri documentation for launchy-0.3.2...
Installing RDoc documentation for launchy-0.3.2...
gem install defunkt-github --source http://gems.github.com
Successfully installed defunkt-github-0.1.3
1 gem installed
Installing ri documentation for defunkt-github-0.1.3...
Installing RDoc documentation for defunkt-github-0.1.3...</pre></div></div>

	<p>Après que tout les gems ont été correctement installés, la tâche &#8216;gems&#8217; de la commande &#8216;rake&#8217; doit nous renvoyer le résultat suivant :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">[I] haml = 1.8
[I] launchy 
[I] defunkt-github 
&nbsp;
I = Installed
F = Frozen</pre></div></div>

	<p>Une autre fonctionnalité sympa vous permettra de vous en sortir quand vous serez coincé dans une situation où vous ne pourrez pas installer des gems au niveau système. Par exemple, si vous devez déployer votre application dans un compte limité d&#8217;un hébergement mutualisé, ou si votre client vous interdit d&#8217;installer de nouveaux logiciels.</p>
	<p>Vous avez alors l&#8217;alternative de &#8216;vendoriser&#8217; vos gems, c&#8217;est à dire, de faire en sorte que les gems dont vous avez besoin soient embarqués dans la structure de votre projet, comme ça :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">$ rake gems:unpack:dependencies</pre></div></div>

	<p>Ca va &#8216;dépaqueter&#8217; tous les gems dont vous avez besoin dans la structure de votre projet sous vendor/gems :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">Unpacked gem: '~/rails/tuto/vendor/gems/haml-1.8.0'
Unpacked gem: '~/rails/tuto/vendor/gems/launchy-0.3.2'
Unpacked gem: '~/rails/tuto/vendor/gems/defunkt-github-0.1.3'</pre></div></div>

	<p>Si on lance de nouveau la tâche &#8216;gems&#8217; maintenant, on voit ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">[I] haml = 1.8
[F] launchy 
[F] defunkt-github 
&nbsp;
I = Installed
F = Frozen</pre></div></div>

	<p>Notez que la plupart des gems ont changé de statut en passant de [I]nstallé à [F]rozen (gelé). Mais, même si le gem HAML a été copié, pour une étrange raison, il continue d&#8217;être affiché comme [I] au lieu de [F], probablement à cause d&#8217;un bug dans Rails. Je pense qu&#8217;ils devraient tous être affichés [F] à moins qu&#8217;il n&#8217;y ait une bonne raison pour que la version installée de HAML sur le système prévale sur celle qui est dans vendor/gems.</p>
	<p>De toutes manières, nous n&#8217;y pouvons rien, disons que nous avons besoin d&#8217;un autre gem qui a besoin d&#8217;une compilation native comme RMagick, alors ajoutons une nouvelle ligne à notre fichier environment.rb :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">...
<span style="color:#9900CC;">config</span>.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;rmagick&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:lib</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;RMagick2&quot;</span>
...</pre></div></div>

	<p>En particulier, nous devons &#8216;savoir&#8217; que ce gem est appelé &#8216;rmagick&#8217; mais qu&#8217;il doit être requis comme &#8216;RMagick2&#8217;. Référez vous à la documentation du gem pour savoir quoi faire. Sans la bonne option :lib ici nous aurions une exception disant qu&#8217;il ne peut pas trouver la librairie &#8216;Rmagick2.so&#8217;.</p>
	<p>Maintenant nous pouvons l&#8217;installer et le dépaqueter dans notre dossier vendor/gems en utilisant la même commande &#8216;gems:unpack:dependencies&#8217;. Après quoi nous devrons utiliser la tâche &#8216;build&#8217;, comme ça :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">$ sudo rake gems:install
$ rake gems:unpack:dependencies
$ rake gems:build</pre></div></div>

	<p>Nous l&#8217;installons et nous le dépaquetons (dans le cas où vous n&#8217;avez pas déjà RMagick), puis nous lancons la tâche &#8216;build&#8217;. C&#8217;est nécessaire pour réaliser toutes les compilations natives (si vous êtes sous OS X, vous devez avoir installé XCode pour avoir des compilateurs à disposition. Sous Linux, regardez si votre distribution n&#8217;aurait pas un paquet comme build-essential) :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">Built gem: '~/rails/tuto/vendor/gems/haml-1.8.0'
Built gem: '~/rails/tuto/vendor/gems/launchy-0.3.2'
Built gem: '~/rails/tuto/vendor/gems/defunkt-github-0.1.3'
Built gem: '~/rails/tuto/vendor/gems/rmagick-2.5.2'</pre></div></div>

	<p>Au moins ça, c&#8217;est la théorie. Il faut encore que j&#8217;explore ces fonctionnalités un peu plus parce que je n&#8217;ai aucune idée de la manière dont c&#8217;est censé fonctionner en production. Le concept en général semble fonctionner correctement. Il sera probablement utile dans la phase de &#8220;setup&#8221; des recettes Capistrano quand vous devrez configurer un nouveau déploiement. Puis vous pourrez utiliser la tâche &#8216;gems:install&#8217; pour installer une version système des gems requis. Ou vous pourriez préalablement les dépaqueter dans votre projet et utiliser la tâche &#8216;gems:install&#8217; séparément ensuite, mais la librairie devrait alors être compilée dans le répertoire home d&#8217;un utilisateur au lieu d&#8217;être dans le dossier des librairies du système.</p>
	<p>C&#8217;est la partie dont je ne sais encore si elle fonctionne ou pas. Est-ce que quelqu&#8217;un a déjà essayé ? Pour plus d&#8217;informations, référez vous à <a href="http://railscasts.com/episodes/110">RailsCasts</a> et à <a href="http://ryandaigle.com/articles/2008/4/1/what-s-new-in-edge-rails-gem-dependencies">Ryan Daigle</a></p>
	<h2>Nouveau support des heures, jusqu&#8217;à Rails 2.0 (partie 1)</h2>
	<p><strong>Avertissement :</strong> n&#8217;utilisez, ni n&#8217;exécutez rien de cette section. Je vais simplement vous montrer quelques trucs pour expliquer mon point de vue. Nous referons des exercices dans la section suivante. C&#8217;est une longue explication des détails du fonctionnement des opérations sur les heures jusqu&#8217;à Rails 2.0. J&#8217;ai déjà rencontré plusieurs débutants qui n&#8217;avaient pas compris ça. Si vous savez déjà tout, sautez à la <a href="#new_time_support2">section suivante</a>.</p>
	<p>Puisque tous les gems dont nous avons besoin sont installés, regardons plus en détail l&#8217;un des aspects qui m&#8217;intéresse le plus dans cette nouvelle version : <strong>Les Heures</strong>.</p>
	<p>Jusqu&#8217;à la version 2.0 nous devions passer beaucoup de temps pour traiter les problèmes d&#8217;heures. La version 2.1 ne résoud pas tous les problèmes, mais elle rend au moins les choses beaucoup plus cohérentes. Il reste encore plein de possibilités pour l&#8217;améliorer.</p>
	<p>En premier et avant toute chose, pour les non-initiés, il faut comprendre comment on faisait avant. Ruby a trois classes différentes pour jouer avec les Dates et les Heures : La classe <a href="http://www.ruby-doc.org/core/classes/Date.html">Date</a>, la classe <a href="http://www.ruby-doc.org/core/classes/Time.html">Time</a> et la classe <a href="http://www.ruby-doc.org/core/classes/DateTime.html">DateTime</a> (qui étend la classe Date.) La plus rapide étant la classe Time dont une partie est écrite en C et compilée. &#8220;Mais&#8221;, la classe Time ne peut gérer que des datetimes de l&#8217;époque Unix (1970) alors que Date/DateTime peut gérer des datetimes beaucoup plus complexes.</p>
	<p>Donc, vous devez commencer par choisir judicieusement. En général, la plupart des gens finissent par utiliser la classe Time pour les combinaisons de dates et d&#8217;heures et la classe Date pour les dates seules. &#8220;Mais&#8221; il y a un autre problème avec lequel quelques-uns d&#8217;entre nous devons composer : la <strong>Localisation</strong>.</p>
	<p>Le premier problème se pose quand votre application est destinée à des gens qui sont dans plusieurs fuseaux horaires. Vous n&#8217;avez pas besoin d&#8217;aller très loin : dans le même pays, deux états peuvent facilement se retrouver dans des fuseaux horaires différents. Rails a toujours fourni une classe <a href="http://api.rubyonrails.com/classes/TimeZone.html">TimeZone</a> utilisable telle quelle pour tenter de s&#8217;occuper de ce problème. Mais, de par sa conception, elle pose un autre problème sur lequel je reviendrai plus tard. Finalement on vous recommande en général de décommenter cette ligne dans le fichier config/environment.rb :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">config.<span style="color:#9900CC;">active_record</span>.<span style="color:#9900CC;">default_timezone</span> = <span style="color:#ff3333; font-weight:bold;">:utc</span></pre></div></div>

	<p>Après avoir fait ça, il y a un autre &#8220;design pattern&#8221; qu&#8217;il faut appliquer : coller un fuseau horaire à chaque utilisateur. Pour faire çà, on se contente généralement d&#8217;ajouter un champ chaîne &#8220;time_zone&#8221; dans le modèle User. Puis l&#8217;utilisateur doit se logger et choisir son fuseau horaire dans une sorte de liste déroulante ou mieux, si vous avez.</p>
	<p>Celà fait, il s&#8217;agit en fait d&#8217;ajouter un filtre &#8216;around_filter&#8217; au niveau de l&#8217;application pour adapter le fuseau horaire de l&#8217;utilisateur à chaque requête. Pour faire ça vous devez ajouter ça dans le fichier app/controllers/application.rb :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> ApplicationController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActionController::Base</span>
  around_filter <span style="color:#ff3333; font-weight:bold;">:set_timezone</span>
&nbsp;
  private
  <span style="color:#9966CC; font-weight:bold;">def</span> set_timezone
    <span style="color:#9966CC; font-weight:bold;">begin</span>
      TzTime.<span style="color:#9900CC;">zone</span> = <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">current_user</span>.<span style="color:#9900CC;">time_zone</span>
      <span style="color:#9966CC; font-weight:bold;">yield</span>
    <span style="color:#9966CC; font-weight:bold;">ensure</span>
      TzTime.<span style="color:#9900CC;">reset</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><em>&#8220;Aha!&#8221;</em> Je vous entend. Que fout ce &#8216;TzTime&#8217; ici ? Bien, comme je vous l&#8217;ai expliqué avant, Ruby est fourni avec 3 classes de gestion des Dates/Heures. Pour que Rails fonctionne correctement avec les fuseaux horaires des utilisateurs, vous devez ajouter une nouvelle classe de gestion des dates et des heures appellée &#8216;TzTime&#8217;. Cette classe est ajoutée par le plugin <a href="http://weblog.jamisbuck.org/2007/2/2/introducing-tztime">TzTime</a> de Jamis Buck&#8217;s. Vous l&#8217;obtiendrez en installant son plugin dans votre projet Rails, comme ça :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">$ ./script/plugin install tztime</pre></div></div>

	<p>Le problème est que la classe Time de Ruby utilise le fuseau horaire de la machine sur laquelle elle s&#8217;exécute. Alors quand vous voudrez utiliser &#8216;Time.now&#8217; pour créer une nouvelle instance de Time, elle sera relative au fuseau horaire de la machine locale. Le filtre (le hack en fait) qu&#8217;on a ajouté surcharge ce comportement en utilisant la nouvelle classe singleton TzTime qui &#8216;se comporte&#8217; comme la classe Time mais qui dispose de son propre système de gestion des fuseaux horaires.</p>
	<p>Le filtre doit être de type &#8216;around_filter&#8217; parcequ&#8217;il faut que nous le réinitialisions après que la requête a été traitée pour éviter que des erreurs surviennent lorsqu&#8217;un autre utilisateur arrive, par exemple, sans que sa propriété time_zone ait été définie correctement. Comme nous changeons l&#8217;état d&#8217;un singleton, toutes les requêtes s&#8217;exécuterons dans ce contexte unique.</p>
	<p>Pour mieux comprendre, lançons &#8216;script/console&#8217; et exécutons quelques requêtes (avant ça, vous devez avoir installé le plugin TzTime dans votre projet) :</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; Time.now
=&gt; Sun May 25 02:59:17 -0300 2008</pre></div></div>

	<p>Notez que &#8216;Time.now&#8217; utilise le fuseau horaire de ma machine qui est GMT-3 (heure du Brésil.) Vous pouvez voir ça dans le &#8217;-0300&#8217; de la représentation de l&#8217;instance de l&#8217;heure.</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; Time.utc(2008,5,25,3)
=&gt; Sun May 25 03:00:00 UTC 2008</pre></div></div>

	<p>Le singleton Time dispose d&#8217;une méthode &#8216;utc&#8217; qui nous renvoie une instance à GMT-0 (heure de Greenwich.)</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt;&gt; Time.local(2008,5,25,3)
=&gt; Sun May 25 03:00:00 -0300 2008</pre></div></div>

	<p>Le singleton Time a aussi une méthode &#8216;local&#8217; qui nous renvoie une instance dans le fuseau horaire courant (-0300). Maintenant voyons la différence lorsqu&#8217;on utilise TzTime à la place.</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">&gt