<?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>Olivier El Mekki</title>
	<atom:link href="http://blog.olivier-elmekki.com/wp-rss2.php" rel="self" type="application/rss+xml" />
	<link>http://blog.olivier-elmekki.com</link>
	<description></description>
	<pubDate>Sun, 16 Nov 2008 09:43:47 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
	<language>en</language>
			<item>
		<title>Qu&#8217;est-ce qu&#8217;un serveur?</title>
		<link>http://blog.olivier-elmekki.com/2008/11/13/quest-ce-quun-serveur/</link>
		<comments>http://blog.olivier-elmekki.com/2008/11/13/quest-ce-quun-serveur/#comments</comments>
		<pubDate>Thu, 13 Nov 2008 13:12:43 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=262</guid>
		<description><![CDATA[Lors d&#8217;une discussion récente, un ami m&#8217;a suggéré qu&#8217;un de ses problèmes de fonctionnalités disparaissant d&#8217;une application web venait du fait qu&#8217;il testait cette application sur sa machine locale plutôt que sur son serveur, en pensant que cette application désactivait ces fonctionnalités si elle repérait être sur une machine locale.
Bien que toutes sortes idées viennent [...]]]></description>
			<content:encoded><![CDATA[<p>Lors d&#8217;une discussion récente, un ami m&#8217;a suggéré qu&#8217;un de ses problèmes de fonctionnalités disparaissant d&#8217;une application web venait du fait qu&#8217;il testait cette application sur sa machine locale plutôt que sur son serveur, en pensant que cette application désactivait ces fonctionnalités si elle repérait être sur une machine locale.</p>
<p>Bien que toutes sortes idées viennent immédiatement à un développeur pour réaliser cela lorsqu&#8217;on lui suggère, deux objections se présentent instantanément :</p>
<ol>
<li>Ça n&#8217;a aucun intérêt.</li>
<li>Rien ne différencie un serveur d&#8217;une machine locale.</li>
</ol>
<p>C&#8217;est ce second point que je voudrais clarifier aujourd&#8217;hui.</p>
<p><span id="more-262"></span></p>
<h2>Un serveur est une application</h2>
<p>La confusion courante est de croire que le serveur est une machine d&#8217;un genre spécial, qui ne fonctionne pas comme les autres. En un sens, c&#8217;est vrai, comme nous le verrons ensuite, mais pas d&#8217;un point de vue strict.</p>
<p>D&#8217;un point de vue strict, un serveur est une application : serveur web comme Apache, serveur ftp comme ProFTPd, serveur smtp/pop/imap (mail) comme Postfix, serveur svn comme Subversion, etc.</p>
<p>Installez l&#8217;une de ces applications sur votre machine locale, et vous avez un serveur.</p>
<h2>Qu&#8217;est-ce qui fait qu&#8217;une application est un serveur?</h2>
<p>La particularité d&#8217;une application de type serveur est de permettre à d&#8217;autres applications de se connecter à elle. D&#8217;un point de vue technique, cela passe par l&#8217;utilisation de<em> sockets</em>.</p>
<p>Un socket est une main tendue par votre application, une main qui attend d&#8217;être saisie pour pouvoir commencer une conversation. Le cas le plus courant est l&#8217;utilisation d&#8217;un socket utilisant le protocol TCP/IP. Cela signifie que la main sera tendue au travers d&#8217;une porte, les <em>ports</em>, que vous voyez partout lorsque vous configurez votre routeur ou votre pare-feu. Avec un tel type de socket, une application sur une machine distante pourra passer par internet pour serrer la main de votre application type serveur et commencer à dialoguer.</p>
<p>Néanmoins, un serveur ne passe pas nécessaire par un socket utilisant le protocol TCP/IP. Ainsi, il existe d&#8217;autres types de socket auquels on ne peut se connecter que depuis la machine qui execute le serveur, comme les socket de type UNIX.</p>
<p>Dans le monde des systèmes libres, nous possédons de nombreux exemples de ce type : le serveur graphique Xorg (qui permet de dessiner et manipuler les fenêtres), le serveur de son Jackd (qui permet d&#8217;accéder au système audio), le serveur DCOP pour KDE (qui permet aux applications KDE de discuter entre elles), etc.</p>
<p>Pour résumer, un serveur est simplement cela : une application qui permet à d&#8217;autres application de se connecter à elle.</p>
<h2>Et pourtant, je loue un serveur dédié!</h2>
<p>L&#8217;utilisation du terme <em>serveur</em> pour désigner la machine est donc un abus de langage. Sur une machine &#8220;serveur&#8221; tournent les même systèmes d&#8217;exploitation que sur une machine &#8220;locale&#8221;.</p>
<p>Cet abus de langage révèle pourtant une réalité concrète. Une machine &#8220;serveur&#8221; n&#8217;est pas une machine comme vous en avez chez vous. Ses composants ont été réduit au strict nécessaire, et les composants relatifs au réseau ont une qualité disproportionnée relativement à votre machine personnelle. Cette machine est sous tension en permanence et est en permanence connectée (si tout va bien) à un réseau permettant une bande passante en envoi sans comparaisons.</p>
<p>Pourtant, ce sont exactement les même composants : un processeur, un disque dur, de la ram, une carte réseau, etc. Ce qui fait la différence est que cette machine est <strong>optimisée pour un usage intensif de serveurs</strong> (au sens strict).</p>
<p>On retrouve la même chose au niveau du système d&#8217;exploitation. Ce qui fait la différence entre un Windows et un Windows Server, et entre une Ubuntu Desktop Edition et une Ubuntu Server Edition, c&#8217;est l&#8217;<em>optimisation</em>. Dans la version <em>server</em> de ces systèmes d&#8217;exploitation, tout a été pensé pour permettre un usage intensif de serveurs et un grand nombre de connexions.</p>
<p>Lorsqu&#8217;on compile un noyau Linux, on a ainsi le choix entre différentes politiques de planification de la priorité des processus, selon qu&#8217;on utilisera intensivement quelques processus qui devront avoir une grande priorité sur les autres (comme sur une machine optimisée <em>bureau</em>) ou qu&#8217;on aura un très grand nombre de processus qui devront être traités de manière égale (comme sur une machine optimisée <em>serveur</em>).</p>
<p>Rien ne vous empêche pourtant d&#8217;opter pour un tel type de configuration sur votre machine personnelle, et, d&#8217;un point de vue purement technique, <em>une application est parfaitement incapable de savoir si elle se trouve sur un système optimisé serveur ou un système optimisé bureau</em>.</p>
<p>Un petit bémol : bien entendu en informatique, rien n&#8217;est impossible. On pourra toujours trouver quelques bidouilles qui permettront de se faire une idée de quel type d&#8217;environnement nous utilisons. Cela n&#8217;a juste rien d&#8217;évident.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=262" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2008/11/13/quest-ce-quun-serveur/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Plugin &#8220;dans cette rubrique&#8221; pour typolight</title>
		<link>http://blog.olivier-elmekki.com/2008/11/06/plugin-dans-cette-rubrique-pour-typolight/</link>
		<comments>http://blog.olivier-elmekki.com/2008/11/06/plugin-dans-cette-rubrique-pour-typolight/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 14:09:47 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[typolight]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=250</guid>
		<description><![CDATA[Typolight est un CMS qui sort du lot. C&#8217;est même un CMF (content managing framework)  comme le souligne David Molliere : typolight réconcilie le développeur backend et le CMS, grâce à sa très permissive extensibilité et à son API claire. Je vous invite à voir le post de Bouctoubou sur le sujet, ainsi que [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.typolight.org/">Typolight</a> est un CMS qui sort du lot. C&#8217;est même un <a href="http://en.wikipedia.org/wiki/Content_Management_Framework">CMF</a> (content managing framework)  <a href="http://blog.bouctoubou.com/2008/04/11/typolight-le-meilleur-cms-au-monde/#comment-1031">comme le souligne</a> <a href="http://david-molliere.net/">David Molliere</a> : typolight réconcilie le développeur backend et le CMS, grâce à sa très permissive extensibilité et à son API claire. Je vous invite à voir <a href="http://blog.bouctoubou.com/2008/04/11/typolight-le-meilleur-cms-au-monde/">le post de Bouctoubou</a> sur le sujet, ainsi que les nombreux autres pour en savoir plus.</p>
<p>Je vous propose aujourd&#8217;hui un plugin de navigation locale pour typolight.</p>
<p><span id="more-250"></span></p>
<h2>Ce qu&#8217;il fait</h2>
<p>Le module de navigation de sous-menus de typolight m&#8217;a assez ennuyé parce qu&#8217;il nécessitait qu&#8217;on définisse le niveau de départ et de fin dans l&#8217;arborescence. Si vous voulez afficher un lien vers les sous-pages d&#8217;une page à, disons, deux niveaux de récursion, et d&#8217;une page à quatre niveau de récursion, vous devrez faire deux modules &#8220;navigation éléments de sous-menu&#8221; différents.</p>
<p>Le module que je vous propose à une fonctionnement de type &#8220;dans cette rubrique&#8221;. Il liste les enfants directs de la page dans laquelle vous vous trouvez.</p>
<h2>Installation</h2>
<p>Le module s&#8217;installe dans system/modules/ .</p>
<p>Vous pouvez l&#8217;installer par svn :</p>
<blockquote><pre style="padding-left: 30px;">svn checkout svn://olivier-elmekki.com/typolight-modules/local_nav</pre>
</blockquote>
<p>Ou en <a href="http://blog.olivier-elmekki.com/download/local_nav.tar.bz2">téléchargeant l&#8217;archive</a>.</p>
<p>Une fois le module en place, il sera accessible dans la liste des modules de frontend dans la rubrique <em>navigation</em> et sous le nom de &#8220;navigation locale&#8221;.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=250" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2008/11/06/plugin-dans-cette-rubrique-pour-typolight/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Vous suivez vos visites effectives. Suivez-vous vos visites ratées?</title>
		<link>http://blog.olivier-elmekki.com/2008/10/22/vous-suivez-vos-visites-effectives-suivez-vous-vos-visites-ratees/</link>
		<comments>http://blog.olivier-elmekki.com/2008/10/22/vous-suivez-vos-visites-effectives-suivez-vous-vos-visites-ratees/#comments</comments>
		<pubDate>Tue, 21 Oct 2008 23:51:56 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[entreprise]]></category>

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

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=246</guid>
		<description><![CDATA[Dans le domaine de l&#8217;analyse des visites, nous possédons de très bons outils. Beaucoup ne jurent que par google analytics, j&#8217;ai déjà présenté piwik, un autre outil de la même classe.
Mais si vous suivez à la trace vos visites réelles, qu&#8217;en est-il des visites qui ont été tentées alors que votre site était aux abonnés [...]]]></description>
			<content:encoded><![CDATA[<p>Dans le domaine de l&#8217;analyse des visites, nous possédons de très bons outils. Beaucoup ne jurent que par google analytics, <a href="http://blog.olivier-elmekki.com/2008/09/03/une-alternative-a-google-analytic-piwik/">j&#8217;ai déjà présenté piwik</a>, un autre outil de la même classe.</p>
<p>Mais si vous suivez à la trace vos visites réelles, qu&#8217;en est-il des visites qui ont été tentées alors que votre site était aux abonnés absents?</p>
<p><span id="more-246"></span></p>
<h3>L&#8217;angoisse du downtime</h3>
<p>Quand vous avez un site pro, vous êtes possédés par une angoisse : celle que votre site soit inaccessible. Vous êtes parti déjeuner, ou pire : vous surfez sur facebook. Une heure, deux heures (trois heures? ). Et soudain, vous réalisez que votre site n&#8217;est plus accessible. Combien de visiteurs et clients potentiels avez-vous perdus ainsi? Vous n&#8217;en savez rien.</p>
<h3>La solution Kolibria</h3>
<p><a href="http://www.kolibria.com/fr">Kolibria Webservice</a> vient de réaliser une application payante permettant de remédier à ce problème : <a href="http://blog.kolibria.com/articles/2008/10/21/monitoria-yet-another-website-monitoring-service">monitoria</a>. La cible est clairement les sites à revenus et offre un outil permettant d&#8217;envoyer des alertes par mail et par sms dès que le site est considéré come innaccessible ou franchement lent. De plus, des statistiques sont réalisées sur vos périodes de downtime. Je vous invite à voir <a href="http://blog.kolibria.com/files/press-release_21-10-08_monitoria.pdf">la press release</a> pour plus d&#8217;information.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=246" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2008/10/22/vous-suivez-vos-visites-effectives-suivez-vous-vos-visites-ratees/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Maîtriser les tests unitaires dans Ruby on Rails</title>
		<link>http://blog.olivier-elmekki.com/2008/10/17/maitriser-les-tests-unitaires-dans-ruby-on-rails/</link>
		<comments>http://blog.olivier-elmekki.com/2008/10/17/maitriser-les-tests-unitaires-dans-ruby-on-rails/#comments</comments>
		<pubDate>Thu, 16 Oct 2008 22:31:24 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=220</guid>
		<description><![CDATA[Maintenant que vous maîtrisez les fixtures (et que vous les avez écrit et testés), vous savez que votre réseau de relations entre les modèles ne posera pas de problèmes.
La tâche va consister dès lors à écrire plus précisément vos modèles, et en particulier vos validations. Bien entendu, nous allons commencer par écrire les tests :]


Maîtriser [...]]]></description>
			<content:encoded><![CDATA[<p>Maintenant que vous maîtrisez les fixtures (et que vous les avez écrit et testés), vous savez que votre réseau de relations entre les modèles ne posera pas de problèmes.</p>
<p>La tâche va consister dès lors à écrire plus précisément vos modèles, et en particulier vos validations. Bien entendu, nous allons commencer par écrire les tests :]</p>
<p><span id="more-220"></span></p>
<ul>
<li><a href="http://blog.olivier-elmekki.com/2008/10/14/maitriser-les-fixtures-dans-les-tests-de-ruby-on-rails/">Maîtriser les fixtures</a><strong> </strong></li>
<li><strong>Maîtriser les tests unitaires</strong></li>
<li>Maîtriser les tests fonctionnels</li>
<li>Maîtriser les tests d&#8217;intégration</li>
</ul>
<h3>Introduction à Test:Unit</h3>
<p>Test::Unit est en fait un framework de test <a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/">intégré à la library standard de ruby</a>. Pour mieux le comprendre, nous allons laisser Rails de côté quelques instants.</p>
<p>Test::Unit mêle quatre notions : <em></em>les <em>assertions</em>, les<em> testcases</em>, les <em>testsuites</em> et les <em>fixtures</em>.</p>
<p><strong>Une assertion</strong> est l&#8217;unité la plus élémentaire. Il s&#8217;agit d&#8217;une expression effectuant un test. Si le test est passé, rien de particulier ne se passe ; si le test échoue, une erreur sera affichée. La méthode de base est <em>assert</em>. Elle évalue si l&#8217;expression passée est vraie ou fausse. Vous pouvez spécifier un message personnalisé au cas ou le test échoue.</p>
<blockquote>
<pre>assert true
assert 1 &lt; 2
assert false, "évidemment que non"</pre>
</blockquote>
<p>Les deux premières assertions passeront, la dernière échouera. Il existe tout un jeu de méthodes d&#8217;assertions intéressantes, comme <em>assert_equal</em>, <em>assert_match</em>, <em>assert_not_same</em>, <em>assert_not_nil</em>, <em>assert_nothing_raised</em>, etc. Je vous laisse regarder la <a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit/Assertions.html">doc officielle</a> pour en faire le tour.</p>
<p><strong>Un testcase </strong>est une classe dérivée de Test::Unit::TestCase qui regroupera les tests propres à une classe (ou pas : vous êtes libre, dans Test::Unit, d&#8217;en faire ce que vous voulez, mais il est conseillé de faire ainsi, et Rails en fait un par modèle).</p>
<blockquote>
<pre>require 'test/unit'
require 'Dog'
require 'Cat'
require 'Person'

class DogTest &lt; Test::Unit::TestCase
  def test_should_create_tame_dog_and_feed_him
    doggy    = Dog.new
    grandma  = Person.new "rotten meat"
    assert grandma.dog = doggy, "grandma doesn't want a dog"
    assert_kind_of Animal, doggy, "that dog is weird"
    assert doggy.feed
  end

  def test_should_know_what_is_good_for_him
    doggy    = Dog.new
    kitty    = Cat.new
    grandma  = Person.new "rotten meat"
    assert doggy.feed( kitty )
    assert_raise { doggy.feed grandma }
  end
end</pre>
</blockquote>
<p>Il s&#8217;agit, concrètement, d&#8217;un ensemble de méthodes qu&#8217;on définira et qu&#8217;on nommera chacune test_<em>quelquechose</em>. Le préfixe <em>test_</em> est obligatoire. On donne généralement un nom représentatif à ce test, étant donné que ce nom apparaîtra si le test échoue. On peut écrire des méthodes sans le préfixe <em>test_</em> mais elles ne seront donc pas considéré comme des tests et ne seront pas exécutées automatiquement.</p>
<p>Car c&#8217;est l&#8217;intérêt de cette classe : lorsqu&#8217;on exécute un fichier qui <em>require &#8216;test/unit&#8217;</em>, il lance automatiquement les tests les uns après les autres et affiche un rapport à la fin.</p>
<p>Isoler ainsi les assertions dans des testcases a pour intérêt évident une plus grande sémantique et une meilleure organisation des tests, mais cela permet aussi de partager des <strong>fixtures</strong>. Contrairement à ce que nous avons vu dans l&#8217;article précédent, les fixtures de Test::Unit standard ne sont pas des fichiers YAML, c&#8217;est un ajout de Rails. Dans les tests standards, on gère les fixtures grâce à deux méthodes rajoutées dans le testcase : setup et teardown.</p>
<p><em>setup</em> sera appelé avant l&#8217;exécution de chaque méthode du testcase. Cela signifie que les fixtures qui sont placés dedans sont réinitialisés entre deux tests. Si vous utilisez des destructeurs, <em>teardown</em> sera exécuté <em>après</em> chaque test (cela peut être intéressant dans une perspective de <em>logging</em> aussi). L&#8217;exemple précédent peut donc être simplifié ainsi :</p>
<blockquote>
<pre>require 'test/unit'
require 'Dog'
require 'Cat'
require 'Person'

class DogTest &lt; Test::Unit::TestCase
  def setup
    @doggy    = Dog.new
    @kitty    = Cat.new
    @grandma  = Person.new "rotten meat"
  end

  def test_should_create_tame_dog_and_feed_him
    assert @grandma.dog = @doggy, "grandma doesn't want a dog"
    assert_kind_of Animal, @doggy, "that dog is weird"
    assert @doggy.feed
  end

  def test_should_know_what_is_good_for_him
    assert @doggy.feed( @kitty )
    assert_raise { @doggy.feed @grandma }
  end
end</pre>
</blockquote>
<p>Bien qu&#8217;utilisant son propre système de fixture, Rails sait aussi se servir de ce système-là, ce qui vous permet d&#8217;exécuter du code arbitraire avant et après chaque méthode de test.</p>
<p>Enfin, une <strong>testsuite</strong> regroupe plusieurs <em>testcases</em>. C&#8217;est principalement un outil de convenance pour vous empêcher de devoir exécuter tous vos tests manuellement les uns après les autres, ou de devoir les mettre dans le même fichier. Ainsi, il vous suffit de faire un fichier contenant :</p>
<blockquote>
<pre>require 'test/unit'
require 'my_tests/DogTest'
require 'my_tests/CatTest'
require 'my_tests/PersonTest'
# etc</pre>
</blockquote>
<p>Et tous les tests seront lancés à l&#8217;exécution de ce fichier.</p>
<p>Voilà, vous avez maintenant une connaissance solide des bases de Test::Unit, nous allons pouvoir revenir à Rails.</p>
<h3>Test::Unit dans Rails</h3>
<p>Peut-être faut-il lever tout de suite un quipropos. Dans le répertoire <em>test/</em> d&#8217;une application Rails, vous pourrez voir <em>unit/</em>, <em>functional/</em> et <em>integration/</em>. Le fait qu&#8217;un répertoire se nomme <em>unit</em> ne doit pas vous induire en erreur : tous trois utilisent Test::Unit (avec des ajouts propres à Rails), et plus particulièrement, Test::Unit::TestCase, ou dérivé.</p>
<p>On peut noter un changement de focalisation entre les trois, allant de <em>unit/</em>, très précis et particulier, à <em>integration</em>, très abstrait et dont les tests simulent des cas concrets de parcours dans l&#8217;application par un utilisateur.</p>
<ul>
<li><strong>unit/</strong> sert à tester les modèles</li>
<li><strong>functional/</strong> sert à tester les contrôleurs (ce qui implique donc également un travail sur les modèles)</li>
<li><strong>integration/</strong> sert à tester des scénarios, par exemple : un utilisateur se log, clique sur le lien &#8220;profil&#8221;, modifie ses pseudo de conversation, va sur une page de discussion et post un commentaire (ce qui implique un travail sur les vues, les contrôleurs et les modèles).</li>
</ul>
<p>Pour lancer les tests, on peut utiliser une de ces formes de commande :</p>
<pre>ruby test/unit/user_test.rb
rake test:units
rake test:functionals
rake test:integration
rake test</pre>
<p>La première lance un unique testcase, ici celui du modèle User. Les trois suivants lance l&#8217;ensemble des testcases d&#8217;une des trois famille de tests. Le dernier lance tous les tests.</p>
<p>Comme je l&#8217;ai dit plus haut, Rails permet un gestion des fixtures plus sophistiquée que Test::Unit. Vous avez déjà écrit vos fixtures. Pour les charger dans vos tests, il suffit d&#8217;indiquer le nom du fixture que vous voulez charger dans la classe de votre testcase, par exemple :</p>
<pre>class AccountTest &lt; ActiveSupport::TestCase
  fixtures :accounts, :users
  # ...
end</pre>
<p>Si vous désirez charger tous les fixtures, vous pouvez spécifier :</p>
<pre>fixtures :all</pre>
<p>Par Ailleurs, vous pouvez utiliser des <em>helpers</em> dans vos tests, que vous placerez dans <em>test/test_helper.rb</em>.</p>
<p>Enfin, Rails rajoute <a href="http://api.rubyonrails.com/classes/Test/Unit/Assertions.html">deux méthodes très utiles</a> à Test::Unit::Assertions : <em>assert_difference </em>et <em>assert_no_difference</em>.</p>
<p>Voilà, le plus lourd est passé. Vous avez les bases pour vous servir de l&#8217;<em>ensemble</em> des tests de rails. Oui, c&#8217;est la petite surprise de la notion de test unitaire dans Rails : elle crée la confusion avec Test::Unit qui est en fait la base de tout.</p>
<p>Étant donné que le terme Test::Unit est peu mentionné dans Rails (il y a même une classe ActiveSupport::Testcase qui ne fait qu&#8217;hériter de Test::Unit::TestCase), je parlerai des tests relatifs à <em>test/unit/</em> lorsque je parlerai de tests unitaires.</p>
<h3>Au volant!</h3>
<p>Voyons maintenant comment se servir des tests unitaires dans le contexte du test driven development.</p>
<p>L&#8217;implémentation MVC de Rails est fortement portée sur les modèles. Cela veut dire que vous devez avoir des modèles très chargés et des contrôleurs très maigres (je ne parviens pas à retrouver la citation exacte, désolé).</p>
<p>Pourtant l&#8217;écriture des tests des modèles, préalable à l&#8217;écriture des modèles même, n&#8217;est pas si conséquente que cela. La raison en est surtout que vous saurez de quoi à besoin votre modèle lorsque vous penserez vos contrôleurs.</p>
<p>Une première écriture de test de modèle se concentre donc généralement sur le test du <a href="http://fr.wikipedia.org/wiki/CRUD">CRUD</a> et des validations. Un exemple typique sera donc :</p>
<pre>require 'test_helper'

class AccountTest &lt; ActiveSupport::TestCase
  fixtures :accounts, :users
  # create
  def test_should_create
    assert_difference 'Account.count' do
      Account.create :user =&gt; users( :quentin), :name =&gt; 'test_should_create_account_name'
    end
  end

  def test_validations
    assert_no_difference 'Account.count' do
      account = Account.create
      assert_not_nil account.errors.on( :user_id ), "Un compte appartient à un user"
      assert_not_nil account.errors.on( :name ), "Les comptes sont distingués par leur nom par les visiteurs"
    end
  end

  def test_name_should_be_unique
    assert_no_difference 'Account.count', "Les comptes sont distingués par leur nom par les visiteurs" do
      account = Account.create :user =&gt; users( :quentin), :name =&gt; accounts( :account1 ).name
      assert_not_nil account.errors.on( :name )
    end
  end

  # read
  def test_should_read
    account = Account.create :user =&gt; users( :quentin ), :name =&gt; "test_read_account_name"
    assert_nothing_raised do
      second = Account.find_by_name 'test_read_account_name'
      assert_equal second.id, account.id
    end
  end

  # update
  def test_should_update
   assert (accounts( :account1 ).update_attributes :name =&gt; "test_update_account_name")
  end

  # delete
  def test_should_delete
    assert_difference 'Account.count', -1 do
      users( :quentin ).destroy
    end
  end

  def test_all_clear
    flunk
  end
end</pre>
<p>On test donc principalement ici les tâches classique du modèle et les validations. <em>Ce n&#8217;est pas insignifiant</em>. Lorsque vous vous enfoncerez dans le développement de votre application et que vous écrirez d&#8217;autres modèles, il y a de fortes chances pour que vous n&#8217;ayez plus bien en tête ce qui se passe dans ce modèle-ci. Lancer régulièrement les tests vous assurera de la solidité de votre modèle.</p>
<p>De plus, vous vous êtes sûrement déjà retrouvé dans le cas où des bugs sont apparus parce que vous avez modifié du code dont vous ne vous souveniez plus du sens. Pour éviter ça, je vous conseille d&#8217;abuser des messages personnalisés des assertions. Plutôt que de simplement répéter la raison pour laquelle le test échoue, et qui est déjà comprise dans le nom de la méthode de test, votre message personnalisé peut expliquer pour quelles raisons contextuelles le test doit passer. C&#8217;est le meilleur moyen pour vous rappeler ce que vous avez fait sur les fichiers précédents sans devoir aller les rouvrir, chercher d&#8217;où provient l&#8217;erreur et lire les éventuels commentaires que vous y avez laissé.</p>
<p>Revenons à la décortication de l&#8217;exemple.</p>
<p>Vous avez peut-être remarqué que l&#8217;expression passée à assert_difference ou assert_no_difference est un string. C&#8217;est indispensable. C&#8217;est fonction évalue bien une différence numérique, mais elle doivent avoir en paramètre un expression dans un string qui sera passé à eval. La raison de cela est que cette expression est évaluée deux fois : une fois au début, une fois à la fin. La soustraction est faite ensuite entre le résultat final et le résultat originel. <em>assert_difference</em> prend en second argument la valeur que doit avoir cette soustraction. Cela implique qu&#8217;on doit la spécifier si on veut ajouter un message personnel (troisième argument). La valeur par défaut est 1, ce qui veut dire que <em>assert_difference</em> test par défaut s&#8217;il y a eu un ajout sur l&#8217;expression, typiquement : le nouvel objet a-t&#8217;il été enregistré?</p>
<p><em>users( :quentin )</em> et <em>accounts( :account1 )</em> permettent de retrouver des fixtures selon leur nom.</p>
<p>Un dernier détail à propos de ce code, la dernière méthode. <em>flunk</em> est une fonction permettant de faire échouer systématiquement le test. C&#8217;est en fait un raccourci pour <em>assert false</em>. Lors de la première écriture d&#8217;un test et de son modèle (ou autre), une dernière méthode avec un <em>flunk</em> permet de signifier qu&#8217;il y a encore des choses à écrire. Votre fichier de test, outre le fait d&#8217;être un observer et un reminder, est aussi une todo list. Lorsque vous aurez fini la première écriture de votre modèle et que son test passera sans problème, vous pourrez supprimer la méthode de <em>flunk</em>.</p>
<h3>Conclusion</h3>
<p>Vous venez d&#8217;avaler la partie la plus complexe pour qui découvre les outils de tests de Rails. Les tests d&#8217;intégration et fonctionnels seront plus complexes, mais il réutiliseront les même outils et structures, avec quelques méthodes ajoutées par Rails pour vous simplifier la vie.</p>
<p>Dans le cadre du Test Driven Development, vous aviez d&#8217;abord écrit les relations de vos modèles et vos migrations grâce aux fixtures, vous écrivez maintenant les validations et peut-être quelques méthodes de vos modèles grâce aux tests unitaires.</p>
<p>Vous reviendrez sur ces tests, lorsque vous vous attaquerez à vos contrôleurs et que vous voudrez ajouter de nouvelles méthodes à vos modèles. Vous créerez probablement d&#8217;autres modèles, également, en fonction des précisions que votre client vous fournira, des nouvelles requêtes et de tous les imprévus qui pimentent la vie d&#8217;un développeur. Notez d&#8217;ailleurs que dans le cadre d&#8217;un développement agile et des fameux phantasmes de &#8220;je suis en face du client, il me demande une modif, je change deux lignes, je lui montre, il n&#8217;en revient pas&#8221;, les tests vous seront d&#8217;un grand secour, afin que ça ne devienne pas &#8220;je suis en face du client, il me demande une modif, je change deux lignes, ça casse tout, je cherche le bug, il s&#8217;impatiente, je lui dis que ça prendra deux minutes, je comble le vide en baratinant du discours technique, je trouve pas, ça m&#8217;enerve&#8221;.</p>
<p>Ce qui compte, c&#8217;est que lorsque vous en aurez fini avec l&#8217;écriture de ces tests et des modèles qu&#8217;ils couvrent, vos modèles seront pleinement opérationnels et solides. Il est alors temps de s&#8217;attaquer aux contrôleurs (oui, vous avez fait tout ça en une journée, hormis la map initiale).</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=220" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2008/10/17/maitriser-les-tests-unitaires-dans-ruby-on-rails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Maîtriser les fixtures dans les tests de Ruby on Rails</title>
		<link>http://blog.olivier-elmekki.com/2008/10/14/maitriser-les-fixtures-dans-les-tests-de-ruby-on-rails/</link>
		<comments>http://blog.olivier-elmekki.com/2008/10/14/maitriser-les-fixtures-dans-les-tests-de-ruby-on-rails/#comments</comments>
		<pubDate>Mon, 13 Oct 2008 23:24:12 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=193</guid>
		<description><![CDATA[Dans un article précédent, j&#8217;ai vanté les mérites du test driven development avec Ruby on Rails. Étant donné que très peu de gens utilisent les outils de test de Rails et que ces derniers reposent (comme tout dans ce framework) sur un ensemble de conventions à prendre en main, j&#8217;avais promis de revenir plus largement [...]]]></description>
			<content:encoded><![CDATA[<p>Dans un <a href="http://blog.olivier-elmekki.com/2008/09/27/test-driven-development-avec-ruby-on-rails/">article précédent</a>, j&#8217;ai vanté les mérites du test driven development avec Ruby on Rails. Étant donné que très peu de gens utilisent les outils de test de Rails et que ces derniers reposent (comme tout dans ce framework) sur un ensemble de conventions à prendre en main, j&#8217;avais promis de revenir plus largement sur ce point.</p>
<p>Il me semble qu&#8217;il est intéressant de commencer par les fixtures, car ce sont les données de bases des tests et surtout, parce que l&#8217;utilisation qui en est faite est souvent très basique, alors que les fixtures offrent des possibilités avancées qui facilitent grandement les tests.</p>
<p>Je vais d&#8217;abord revenir sur les bases des fixtures pour ceux qui découvrent les outils de test, et nous verrons ensuite ces sucreries.</p>
<p><span id="more-193"></span></p>
<ul>
<li><strong>Maîtriser les fixtures </strong></li>
<li>Maîtriser les tests unitaires</li>
<li>Maîtriser les tests fonctionnels</li>
<li>Maîtriser les tests d&#8217;intégration</li>
</ul>
<h3>Au commencement, il y avait data</h3>
<p>Eh oui l&#8217;informatique, c&#8217;est le traitement automatique de l&#8217;information. On pourrait décrire l&#8217;ensemble des entités informatiques sous l&#8217;expression : data + process. Les tests de Rails ne font pas défaut : il faut d&#8217;abord leur fournir des données à manipuler.</p>
<p>Si vous avez scrupuleusement suivi les tutoriels d&#8217;initiation à Rails, vous avez pris l&#8217;habitude de créer trois bases de données : <em>development</em>, <em>production</em> et <em>test</em>. Ce n&#8217;est pas anodin. Cela veut dire que chaque environnement possède son propre ensemble de données.</p>
<p>Vous l&#8217;aurez deviné, les outils de test utilisent la base de donnée <em>test</em>, qui ne recoupe pas les données des autres environnements (ce qui évite de laisser la base de donnée dans un état indéfini après avoir lancé les tests). Comment introduire des données dans cette base, alors? C&#8217;est le travail des fixtures.</p>
<h3>Et son nom était YML</h3>
<p>Il existe trois formats pour les fixtures, le plus courant étant YAML (ou YML). Son avantage est d&#8217;être supporté en builtin par Ruby. Si vous utilisez Ruby, vous l&#8217;avez sûrement déjà rencontré car il est abondamment utilisé pour serialiser des objets. C&#8217;est un peu l&#8217;équivalent de JSON pour le Javascript (bien que ce ne soit pas exclusif à js et que ce dernier pourrait utiliser d&#8217;autres formats). Et même sans être un rubyiste, vous vous en servez pour configurer la connexion à la base de donnée dans Rails, dans le fichier <em>config/database.yml</em>.</p>
<p>Son usage est relativement intuitif. On donne un nom à chaque fixture, et ses attributs sont placés en dessous, en étant indentés (attention : seulement des espaces, pas de tabulations!). Le nom est tout à fait arbitraire et pourra être utilisé dans les tests (et dans les fixtures eux-mêmes).</p>
<p>Chaque fichier de fixture correspond à un modèle. Ainsi, tous les éléments dans <em>test/fixtures/comments.yml</em> seront transformés en objets <em>Comment</em>, tels que définis dans <em>app/models/comment.rb</em>.</p>
<blockquote>
<pre>spam:
  id: 1
  user_id: 1
  created_at: "2008-10-12 18:50:10"
  content: "http://inpythonwetrust.com"
  status: 2</pre>
</blockquote>
<p>Cet exemple présuppose que vous avez par ailleurs un modèle <em>User</em> et un fixture dans <em>users.yml </em>avec un id = 1, par exemple :</p>
<blockquote>
<pre>troller:
  id: 1
  name: "persiffleur"
  mail: "nid2viper@gmail.com"
  created_at: "2008-10-12 18:50:10"</pre>
</blockquote>
<p>Les fixtures sont aussi simples à utiliser que ça : il suffit de donner un nom et de reprendre les champs SQL de la table à laquelle correspond le modèle. C&#8217;est sympa, mais on est en droit de s&#8217;attendre à un peu plus de magie de la part de Rails.</p>
<h3>Et il dit : Que la lumière soit!</h3>
<p>C&#8217;est bien-heureusement le cas. Pour commencer, il est inutile de préciser les champs <em>created_at</em> et <em>updated_at</em>. Rails leur donne automatiquement la valeur de <em>Time.now</em>.</p>
<p>Si vous désirez préciser une valeur autre que <em>Time.now</em>, Rails vous facilite la tâche en permettant d&#8217;utiliser <em>erb</em> dans les fixtures. Vous pouvez donc utiliser tous les helpers accessibles depuis vos vues, par exemple :</p>
<blockquote>
<pre>created_at: &lt;%= 2.days.ago.to_s :db %&gt;</pre>
</blockquote>
<p>Ensuite (et c&#8217;est mon feature préféré), vous pouvez également ne pas spécifier l&#8217;<em>id</em>. Un <em>id</em> est alors automatiquement généré par Rails à partir du nom du fixture. Ce qui permet d&#8217;écrire quelque chose comme ça:</p>
<blockquote>
<pre># users.yml
troller:
  name: "persiffleur"
  mail: "nid2viper@gmail.com"</pre>
</blockquote>
<p>et</p>
<blockquote>
<pre># comments.yml
spam:
  user: troller
  content: "http://inpythonwetrust.com"
  status: 2</pre>
</blockquote>
<p>Cette possibilité doit commencer à vous faire entrevoir l&#8217;intérêt en terme de <em>Test Driven Development</em>. À noter que les guillemets ne sont pas nécessaire pour marquer le début et la fin des strings, mais je préfère personnellement les utiliser quand même pour distinguer les strings des identifiers.</p>
<p>Enfin, le fait de pouvoir utiliser erb signifie également la possibilité d&#8217;introduire de la logique dans vos fixtures. Ne faites pas ces gros yeux, YAML ne définit pas de standard MVC :] . Cela a un intérêt majeur si vous voulez voir comment votre application tient le choc avec 5000 utilisateurs.</p>
<blockquote>
<pre>&lt;% 5000.times do |i| %&gt;
user_&lt;%= i -%&gt;:
  name: "user_&lt;%= i -%&gt;"
  mail: "user_&lt;%= i -%&gt;@gmail.com"
&lt;% end %&gt;</pre>
</blockquote>
<h3>Le premier jour, il écrivit les fixtures</h3>
<p>Personnellement, je commence toujours un projet par&#8230; inkscape. Je fais une map des différentes entités dont je pense avoir besoin dans l&#8217;immédiat, je dessine leur relation et je leur donne les quelques attributs qui me passent par la tête. Le dessin vectoriel est juste parfait pour ça.</p>
<p>L&#8217;étape suivante, pour tout développeur Rails, est de créer les modèles (juste la création même, par le biais des générateurs). Puis, ils écrivent généralement les migrations.</p>
<p>Du point de vue du test driven development, c&#8217;est une mauvaise idée. Les fixtures, dans leur usage avancé, permettent une écriture bien plus naturelle des schémas. Prenons l&#8217;exemple suivant de migration :</p>
<blockquote>
<pre>class CreateComments &lt; ActiveRecord::Migration
  def self.up
    create_table :comments do |t|
      t.column  'article_id',   :integer,   :null =&gt; false
      t.column  'user_id',      :integer,   :default =&gt; 0
      t.column  'content',      :text,      :null =&gt; false
      t.timestamps
    end
  end

  def self.down
    drop_table :comments
  end
end</pre>
</blockquote>
<p>Cela est déjà très concret et implique un blocage réflexif sur l&#8217;implémentation de la base de donnée. En écrivant d&#8217;abord les fixtures, on peut se permettre d&#8217;écrire simplement ce qu&#8217;on attends du modèle en terme de structure :</p>
<blockquote>
<pre>ruvanche_comment:
  article: ruby
  user: ruvanche
  content: "301"</pre>
</blockquote>
<p>Cela permet de se faire une idée rapidement des attributs dont on a  <em>réellement </em>besoin et de voir comment les données sont reliées entre elles, nous faisant vite remarquer si une relation de notre map est défaillante (par exemple, un <em>has_many</em> qui devrait plutôt devenir un <em>many_to_many</em>, ou un attribut qui devrait plutôt devenir un modèle). On regagne donc le temps perdu à modifier/reset les migrations et réintroduire des données (ou à écrire des migrations de fix).</p>
<p>Une fois que ces données <em>abstraites mais en action</em> ont été écrites, on peut penser à écrire les migrations, qui sont des informations <em>concrètes mais de réserve</em> (dans le sens où on ne les pensera en action que quand on écrira les modèles, si on omet les tests). Puis, quasiment simultanément, les relations dans les modèles, c&#8217;est-à-dire les <em>has_many</em>, <em>belongs_to</em> et autres.</p>
<p>Les fixtures qu&#8217;on aura écrit permettront de tester rapidement s&#8217;il y a des problèmes dans le schémas de la base de donnée ou dans le jeu des relations. Pas même besoin d&#8217;écrire des tests, le simple <em>test_truth</em> qui aura été généré automatiquement dans les tests de vos modèles vous suffiront à mettre ce réseau de relations à l&#8217;épreuve. Lancez simplement :</p>
<blockquote>
<pre>rake test</pre>
</blockquote>
<p>Et vous pourrez fixer les bases de vos modèles et vos migrations avant même d&#8217;avoir commencé à écrire du code effectif, et surtout avant d&#8217;avoir chargé des données.</p>
<p>Pas besoin d&#8217;imaginer non plus cinq fixtures différents en différents états lors de la première écriture des fixtures. Il s&#8217;agit juste de se représenter à quoi peut ressemble une instance d&#8217;un modèle. Les états particuliers viendront d&#8217;eux-même lorsqu&#8217;on écrira effectivement les tests.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=193" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2008/10/14/maitriser-les-fixtures-dans-les-tests-de-ruby-on-rails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Installation de ruby on rails pour designers</title>
		<link>http://blog.olivier-elmekki.com/2008/10/09/installation-de-ruby-on-rails-pour-designers/</link>
		<comments>http://blog.olivier-elmekki.com/2008/10/09/installation-de-ruby-on-rails-pour-designers/#comments</comments>
		<pubDate>Thu, 09 Oct 2008 08:50:41 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=161</guid>
		<description><![CDATA[Vous êtes designer, et on vous a demandé de travailler sur un projet Ruby On Rails. Vous télécharger le code de l&#8217;application et là, aïe aïe aïe, qu&#8217;est-ce que c&#8217;est que tout ça?
Ruby On Rails est un framework, ce qui implique une grosse infrastructure présente par défaut. De plus, le code est éclaté du fait [...]]]></description>
			<content:encoded><![CDATA[<p>Vous êtes designer, et on vous a demandé de travailler sur un projet Ruby On Rails. Vous télécharger le code de l&#8217;application et là, aïe aïe aïe, qu&#8217;est-ce que c&#8217;est que tout ça?</p>
<p>Ruby On Rails est un framework, ce qui implique une grosse infrastructure présente par défaut. De plus, le code est éclaté du fait de la séparation MVC. Cela, c&#8217;est la première bonne nouvelle pour vous, designers. Le seul endroit où vous devez agir est dans les vues, et dans le CSS. Mais revenons pas à pas sur le processus d&#8217;installation.</p>
<p><span id="more-161"></span></p>
<p>Cet article se concentre sur l&#8217;installation pour Windows, étant donné que c&#8217;est encore le système le plus courant. Si vous utilisez un système libre, il vous suffira de passer par votre gestionnaire de paquet. Si vous utilisez MacOSX, je ne peux vous dire où télécharger le nécessaire, mais il ne devrait pas y avoir de changements majeurs.</p>
<h3>Installation du nécessaire</h3>
<p>Ruby on Rails, comme son nom l&#8217;indique, est un framework utilisant le langage Ruby. Il vous faut donc, dans un premier temps, installer l&#8217;interpréteur de ce langage. Il existe un <a href="http://rubyforge.org/frs/?group_id=167">installeur</a> pour ça. Lorsque vous l&#8217;installez, prenez bien soin de laisser l&#8217;option cochée par défaut qui propose d&#8217;installer RubyGem.</p>
<p>Gem est un gestionnaire de paquet pour ruby. Cela signifie que par son intermédiaire, vous pouvez installer, supprimer et mettre à jour des libraries ruby (Gem ira les chercher de lui-même sur le net). Rails fait partie de ces libraries.</p>
<p>Pour installer rails, ouvrez une invite de commande MS-DOS. Il faut d&#8217;abord mettre à jour la liste des paquets de gem, puis installer rails lui même, en lançant ces deux commandes successives :</p>
<blockquote>
<pre><code>gem update --system
</code><code>gem install rails --include-dependencies</code></pre>
</blockquote>
<p>Ensuite, vous devez installer le moteur de base de donnée utilisé pour votre projet. Le plus courant est MySQL. Rails propose aujourd&#8217;hui par défaut l&#8217;utilisation de SQLite3, mais bien que ce soit une base de donnée que j&#8217;apprécie beaucoup, la library Rails qui en permet l&#8217;utilisation m&#8217;a causé de nombreux problèmes. Je vous conseille donc d&#8217;utiliser MySQL à la place (si néanmoins vos développeurs utilisent sqlite, son installation ne vous posera pas de problème, interrogez vos développeurs au cas où).</p>
<p>Téléchargez <a href="http://dev.mysql.com/downloads/mysql/5.0.html#win32">l&#8217;installeur de MySQL</a> et suivez ses instructions. Vous pouvez accepter la plupart des choix par défaut, si ce n&#8217;est le charset par défaut. Demandez à vos développeurs quel charset ils utilisent, il y a de grandes chances pour qu&#8217;ils vous répondent : UTF-8. Dans ce cas, au moment du choix du charset, choisissez : <em>Best Support For Multilinguism</em>. Assurez-vous également, dans la fenêtre suivante, de cocher : <em>Include BIN directory in Windows PATH</em>.</p>
<p>Il ne reste plus qu&#8217;à installer l&#8217;application rails en elle-même. Les développeurs avec lesquels vous travaillerez utiliseront probablement SVN pour synchroniser votre travail commun. <a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a> vous permettra de facilement utiliser ce protocole. Un peu de vocabulaire pour vous aider à vous y retrouver:</p>
<ul>
<li><em>checkout</em> : sert à télécharger l&#8217;ensemble de l&#8217;application pour la première fois.</li>
<li><em>commit</em> : sert à envoyer vos modifications.</li>
<li><em>update </em>: sert à mettre à jour votre copie de travail en téléchargeant les modifications qui ont été faites depuis la dernière fois (assurez vous de le faire régulièrement si vous ne voulez pas avoir des conflits de version).</li>
<li><em>add to ignore list</em> : permet de faire ignorer un fichier ou un dossier et donc de ne pas l&#8217;envoyer dans les mises à jour. Vous voudrez probablement utiliser cela pour ne pas envoyer vos fichiers de logs et celui de la configuration de votre base de donnée.</li>
</ul>
<h3>Configuration</h3>
<p>Lors de cette étape, il s&#8217;agit surtout de configurer la base de donnée. Si vos développeurs sont gentils, il vous auront fourni un fichier de configuration standard que vous pourrez adapter. Si ce n&#8217;est pas le cas, je vais vous en donner un.</p>
<p>Mais d&#8217;abord, il faut bien saisir qu&#8217;il existe, dans Rails, trois environnements : l&#8217;environnement de <em>développement</em>, l&#8217;environnement de <em>production</em> et l&#8217;environnement de <em>test</em>. Du point de vue du designer, vous ne vous servirez que du premier. C&#8217;est l&#8217;environnement classiquement utilisé pendant la conception d&#8217;une application. Lorsque l&#8217;application est publiée, on la place en environnement de <em>production</em>, ce qui joue principalement sur le fait que beaucoup plus d&#8217;éléments sont mis en cache. Cela permet d&#8217;aller plus vite, mais le caching, de par sa nature, pose des problèmes ennuyeux lorsqu&#8217;on fait de nombreuses et régulières modifications. L&#8217;environnement de <em>test</em>, quant à lui, ne sert qu&#8217;aux tests automatisés et n&#8217;ai pas utilisé manuellement.</p>
<p>Si j&#8217;insiste sur la distinction entre ces trois environnements, c&#8217;est que chacun possède sa propre base de donnée. Ainsi, un fichier de configuration standard pour MySQL sur Windows ressemble à ceci (notez que sur un système à base Unix, vous pouvez, pour augmenter la vitesse, utiliser le fichier de socket de mysql plutôt que de vous connecter à localhost) :</p>
<blockquote>
<pre>development:
  adapter: mysql
  encoding: utf8
  host: localhost
  database: <strong>projet_dev</strong>
  username: <strong>nom</strong>
  password: <strong>password</strong>

test:
  adapter: mysql
  encoding: utf8
  host: localhost
  database: <strong>projet_test</strong>
  username: <strong>nom</strong>
  password: <strong>password</strong>

production:
  adapter: mysql
  encoding: utf8
  host: localhost
  database: <strong>projet_prod</strong>
  username: <strong>nom</strong>
  password: <strong>password</strong></pre>
</blockquote>
<p>N&#8217;ayant pas besoin du second et du troisième environnement, vous pouvez très bien omettre leur description. Placez ces informations dans un fichier nommé <em>database.yml</em> et rangez ce fichier dans <em>config/ </em>dans le répertoire de votre application rails.</p>
<p>Il faut ensuite créer les bases de données. Ouvrez une invite de commande MS-DOS et tapez dedans (en remplaçant le nom de votre projet, le nom de votre utilisateur et le mot de passe) :</p>
<blockquote>
<pre>mysql</pre>
</blockquote>
<p>Renseignez votre mot de passe, puis :</p>
<blockquote>
<pre>create database <strong>projet_dev</strong> ;
grant all on <strong>projet_dev</strong>.* to '<strong>nom</strong>'@'localhost' identified by '<strong>password</strong>' ;</pre>
</blockquote>
<p>Répétez cela avec <strong>projet_test </strong>et <strong>projet_prod</strong> si vraiment vous en avez besoin.</p>
<p>La base de donnée est maintenant créée, il reste une dernière fois à mettre les mains dans le cambouis pour créer sa structure (promis après, c&#8217;est fini). Avec votre invite de commande, rendez-vous dans le répertoire de l&#8217;application et tapez :</p>
<blockquote>
<pre>rake db:migrate</pre>
</blockquote>
<p>Cela créera automatiquement cette structure. Si vos développeurs ont vraiment été très gentils (mais ne rêvons pas, ce sont des développeurs), cette commande peuple même la db avec des données utilisables (en créant des utilisateurs, des produits, etc).</p>
<p>La configuration est maintenant terminée. Vous pouvez démarrer l&#8217;application en utilisant le serveur intégré de rails (où peut-être voulez-vous que nous voyions rapidement la configuration d&#8217;apache? <img src='http://blog.olivier-elmekki.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ). Toujours dans le répertoire principal de l&#8217;application, dans l&#8217;invite de commande, tapez :</p>
<blockquote>
<pre>ruby script/server</pre>
</blockquote>
<p>Il ne vous reste plus maintenant qu&#8217;à vous rendre à l&#8217;adresse <a href="http://127.0.0.1:3000">http://127.0.0.1:3000</a> . Tapez <em>control-c</em> dans l&#8217;invite de commande pour arrêter le serveur. Ce serveur est particulièrement lent et ne peut donc être utilisé en production, mais il a le mérite de permettre de tester rapidement une application.</p>
<h3>Explication de l&#8217;architecture</h3>
<p>Ruby on Rails est un framework reposant sur le MVC : <em>Models</em>, <em>Views</em>, <em>Controllers</em>. Cela signifie qu&#8217;il y a une distinction fondamentale entre ce qui relève de la gestion des entités (les modèles, la plupart du temps mappés sur des tables de la base de donnée), des actions exécutables par l&#8217;utilisateur (les contrôleurs) et du contenu renvoyé en échange (les vues).</p>
<p>Ce qui vous intéresse, en tant que designer ou frontend developer, ce sont ces vues. C&#8217;est là que résident les fichiers .html (ou plutôt, les fichiers html.erb, je vais revenir là dessus). Les <em>models</em>, <em>views</em> et <em>controllers</em> se trouvent dans le répertoire <em>app/</em> .</p>
<p>Probablement encore plus important pour vous est le répertoire <em>public/</em> . C&#8217;est en fait le seul répertoire visible de l&#8217;extérieur. Vous pourrez y placer vos fichiers CSS, javascript, audio, images et autres.</p>
<p>Et c&#8217;est à peu prêt tout ce que vous avez besoin de savoir sur l&#8217;architecture d&#8217;une application rails pour pouvoir travailler avec.</p>
<p>Je n&#8217;ai encore jamais rien vu dans le dossier <em>doc/</em>, mais si vos développeurs sont les nouveaux messies sur Terre, ils y auront placé toute sorte d&#8217;informations intéressantes. Les noms des dossiers <em>config/</em> et <em>log/</em> parlent d&#8217;eux-même. <em>lib/</em> et <em>vendor/</em> servent à placer des bouts de codes des plus utiles, <em>db/</em> est le répertoire où l&#8217;on place les <em>migrations</em>, qui ont permis la création quasi-magique de la base de donnée tout à l&#8217;heure. <em>script/</em> contient quelques utilités comme le serveur, et beaucoup de petits scripts facilitant la vie des développeurs. <em>test/</em> est le répertoire où se trouvent les tests automatisés (et si vous voulez embêter vos développeurs, demandez leur pourquoi les fichiers dans <em>test/functionals</em> et <em>test/units</em> ont si peu de lignes). Enfin, Rakefile est un fichier permettant d&#8217;autres tours de magie de rails, tellement nombreux que je ne m&#8217;amuserai pas à les énumérer <img src='http://blog.olivier-elmekki.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> (ah, si : dans une invite de commande, tapez &#8220;rake stats&#8221; et demandez à vos développeurs comment il se fait que le <em>Code to test ratio</em> a une valeur si faible côté test).</p>
<h3>html.erb ?</h3>
<p>Vous vous êtes probablement déjà retrouvé confronté à du code PHP que vous avez dû tenter tant bien que mal de comprendre pour avoir une idée d&#8217;où placer vos <em>id</em> et vos <em>class</em> ( &#8220;mais d&#8217;où vient ce <em>div</em>?&#8221; ).</p>
<p>Du fait de la séparation MVC, cela est moins problématique en rails, mais il y a tout de même besoin de rajouter un peu de code dans le HTML. Le langage utilisé est Ruby. Si vos développeurs ont bien fait leur travail (je vais vraiment tous me les mettre à dos), ce code doit être parfaitement compréhensible, même si vous ne connaissez absolument pas Ruby.</p>
<p>La forme standard pour exécuter du code Ruby dans un <em>template erb</em> est :</p>
<blockquote>
<pre>&lt;% code %&gt;</pre>
</blockquote>
<p>Il y a néanmoins plusieurs variantes. La balise que je viens de vous montrer n&#8217;affiche normalement rien en sortie dans le HTML, sauf si une fonction le demande explicitement (ce qui doit normalement être évité, au profit de la balise suivante). Pour afficher du code, on utilise : &lt;%= %&gt;. Vous verrez ainsi souvent :</p>
<blockquote>
<pre>&lt;%= @var %&gt;</pre>
</blockquote>
<p>Cela signifie simplement qu&#8217;il faut écrire le contenu de la variable @var. Un autre modificateur est le signe moins ( - ) avant la fermeture de la balise, comme ceci :</p>
<blockquote>
<pre>&lt;p&gt;Nom: &lt;%= @user.name -%&gt;&lt;/p&gt;</pre>
</blockquote>
<p>Cela permet un formatage plus propre du code HTML : un balise sans &#8220;-&#8221; retourne à la ligne, une balise avec, non.</p>
<p>Le type de code le plus &#8220;complexe&#8221; que vous devrez voir est comme ceci :</p>
<blockquote>
<pre>&lt;!-- exemple 1 --&gt;
&lt;% if @user.logged? %&gt;
  &lt;p&gt;Salut &lt;%= @user.name -%&gt;&lt;/p&gt;
&lt;% end %&gt;

&lt;!-- exemple 2 --&gt;
&lt;ul id"product_list"&gt;
&lt;% @products.each do |prod| %&gt;
   &lt;li&gt;&lt;%= prod.name -%&gt;&lt;/li&gt;
&lt;% end %&gt;
&lt;/ul&gt;

&lt;!-- exemple 3 --&gt;
&lt;% form_for :vote, @vote do |f| %&gt;
  &lt;p&gt;&lt;%= f.label :rate, "Rate this" -%&gt; &lt;%= f.rate_radio :rate -%&gt;&lt;/p&gt;
  &lt;p&gt;&lt;%= f.label :username, "Your name" -%&gt; &lt;%= f.text_field :username -%&gt;&lt;/p&gt;
  &lt;p&gt;&lt;%= f.submit -%&gt;&lt;/p&gt;
&lt;% end %&gt;</pre>
</blockquote>
<p>L&#8217;exemple 1 est parfaitement compréhensible pour qui ne connaît pas Ruby, pour peu qu&#8217;on sache que <em>if</em> en anglais signifie <em>si</em> (condition). Si l&#8217;utilisateur est loggé, dire : salut <em>son_nom.</em></p>
<p>L&#8217;exemple 2 se comprend très bien aussi, dès lors qu&#8217;on sait que <em>each</em> signifie <em>chacun</em> : pour chaque produit, écrire un <em>li</em> avec son nom.</p>
<p>Le troisième exemple est plus problématique. C&#8217;est un vrai plaisir pour nous les développeurs, mais ça peut être très ennuyeux pour les designers. Je ne doute pas que vous compreniez ce qu&#8217;il fait : il s&#8217;agit de créer un formulaire. En fait, cela fait bien mieux : cela crée un formulaire en se basant sur un modèle de la base de donnée et en facilitant son interprétation à l&#8217;envoi (un autre tour de magie de rails). Le vrai problème pour un designer est que si vous voulez rajouter une <em>class</em> ou un <em>id</em> aux éléments générés ainsi, vous devrez probablement demander à un développeur de le faire (mince, vous n&#8217;auriez peut-être pas dû leur poser toutes ces questions sur les tests :] ).</p>
<p>Ce type de fonction est ce qu&#8217;on appelle des <em>helpers</em>, et ils nous sont effectivement, à nous, d&#8217;une grande aide pour accélérer le développement. Rassurez-vous cependant : j&#8217;ai pris un exemple extrême, et vous ne devrez pas être ennuyés plus que cela par eux. En fait, vous retrouverez la plupart du temps les même, et vous saurez vite les modifier vous même. <small>(mais bon, si les développeurs avaient bien fait leur boulot, vous n&#8217;auriez pas à les modifier&#8230;)</small>.</p>
<h3>Conclusion</h3>
<p>Je conclurai qu&#8217;il était vraiment temps de conclure. Oui, le premier contact avec ruby On Rails peut être un peu refroidissant, vis-à-vis du travail à faire pour le mettre en place, mais ce n&#8217;est pas peine perdue, vous en serez tout à fait satisfait (parole de développeur). Contrairement à ce que peut laisser penser l&#8217;installation, Ruby On Rails a été pensé pour tout accélérer.</p>
<p>Dans ce contexte d&#8217;effervecence de la production, vous apprécierez que chacun ait sa partie de l&#8217;application consacrée, ce qui permet de limiter les conflits de version svn. En plus comme ça, vous aurez moins à parler aux&#8230; Bon d&#8217;accord, j&#8217;arrête. :]</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=161" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2008/10/09/installation-de-ruby-on-rails-pour-designers/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Interview d&#8217;un créateur de framework javascript</title>
		<link>http://blog.olivier-elmekki.com/2008/10/04/interview-dun-createur-de-framework-javascript/</link>
		<comments>http://blog.olivier-elmekki.com/2008/10/04/interview-dun-createur-de-framework-javascript/#comments</comments>
		<pubDate>Sat, 04 Oct 2008 11:47:13 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=156</guid>
		<description><![CDATA[John Resig vient de publier depuis son blog une présentation sur l&#8217;état de JQuery en 2008 qui lui a servi d&#8217;appoint lors de récentes conférences. Cette présentation montre la position dominante qu&#8217;a gagné JQuery au fil des années et qu&#8217;il occupe aujourd&#8217;hui. Mais en dehors de JQuery, c&#8217;est tout le monde de javascript qui connaît [...]]]></description>
			<content:encoded><![CDATA[<p>John Resig vient de publier depuis <a href="http://ejohn.org/">son blog</a> une présentation sur <a href="http://www.slideshare.net/jeresig/state-of-jquery-08-presentation/">l&#8217;état de JQuery en 2008</a> qui lui a servi d&#8217;appoint lors de récentes conférences. Cette présentation montre la position dominante qu&#8217;a gagné JQuery au fil des années et qu&#8217;il occupe aujourd&#8217;hui. Mais en dehors de JQuery, c&#8217;est tout le monde de javascript qui connaît actuellement un renouveau, pour ne pas dire une renaissance.</p>
<p>Je vous propose aujourd&#8217;hui l&#8217;interview de <a href="http://emyller.net/">Evandro Myller</a>, le créateur d&#8217;un nouveau framework javascript : <a href="http://utmproject.org/">UTM</a>.</p>
<p><span id="more-156"></span></p>
<p>UTM est un framework qui se distingue sur ce qui constitue le point faibles des frameworks javascript : la vitesse d&#8217;exécution (de 40% à 60% plus rapide que JQuery sur les sélecteurs, selon mes benchmarks). Il offre déjà quelques effets intéressants (dans le domaine d&#8217;un scriptaculous ou d&#8217;un JQuery UI) dans un module qui ne demande qu&#8217;à être complété. Il propose un interface de construction du paquet lors du téléchargement en choisissant les composants et en proposant la compression, comme pour le téléchargement de JQuery UI. Mais laissons plutôt la parole à Evandro pour présenter UTM.</p>
<h3>D&#8217;abord, peux-tu te présenter un peu et expliquer à nos lecteurs ce qu&#8217;est UTM?</h3>
<p>Et bien, que dire à propos de moi&#8230; Je suis chrétien, développeur web se concentrant sur l&#8217;expérience utilisateur avec Javascript. J&#8217;ai commencé à apprendre ce langage il y a seulement deux ans, mais ça a été mes deux années les plus productives et amusantes.</p>
<p>À propos d&#8217;UTM, je suis dessus depuis un peu plus d&#8217;un an, quand j&#8217;ai commencé à développer quelques bouts de codes isolés pour m&#8217;aider (j&#8217;apprenais le JS, et je n&#8217;avais aucune idée qu&#8217;un jour, je construirai un library). Le projet à démarré réellement il y a quelques mois, sur cette idée d&#8217;il y a un an. Aujourd&#8217;hui, UTM (UlTiMate javascript library) est un projet dont le but est  de donner au programmeur (débutant ou expert) le pouvoir d&#8217;écrire des choses cool et puissantes avec quelques simples lignes de code.</p>
<h3>Quelle est à ton avis la différence principale entre UTM et les autres framework/libraries?</h3>
<p>Je crois que je peux répondre : ses performances. UTM peut faire ce que font les autres libraries, mais il a été conçu autour de conventions qui s&#8217;assurent que sa structure est réellement simple et rapide. Le core ne fait que le strict nécessaire pour fournir le bon résultat en moins de temps. C&#8217;est donc une bonne base pour tous les composants d&#8217;UTM (les effets, les modules supplémentaires, etc). Il a aussi quelque chose de différent et d&#8217;utile : un système de modules simple d&#8217;utilisation. Vous pouvez importer des modules et leur appliquer des thèmes externes d&#8217;un manière très simple : u.include(&#8217;your_module&#8217;) et, accessoirement, u.useTheme(&#8217;theme_name&#8217;).</p>
<h3>Est-ce qu&#8217;UTM s&#8217;intègre avec d&#8217;autres framework?</h3>
<p>Oui. Si vous avez vraiment besoin d&#8217;un autre library javascript sur votre site, il n&#8217;y a pas à s&#8217;en inquiéter. UTM conserve tout dans son namespace, &#8216;utm&#8217;. &#8216;u&#8217; est un raccourci vers UTM lui-même. Il n&#8217;y a donc aucun problème pour travailler avec une autre library, parce qu&#8217;il ne change rien du code natif. Et, tu sais, ni &#8216;utm&#8217; ni &#8216;u&#8217; ne sont des noms de variables utilisés couramment, n&#8217;est-ce pas? =]</p>
<h3>Peux-tu démontrer que UTM rox, en trois lignes de code?</h3>
<p>Wow, c&#8217;est vraiment dur de choisir quoi montrer ici&#8230; Mais essayons. Peut-être&#8230;</p>
<ol>
<li>u(&#8217;div#main p.text:contains(&#8221;some text&#8221;)&#8217;)</li>
<li> .append(&#8217;a.mainlink[href="page.html"]&#8216;, &#8216;Some link&#8217;)</li>
<li> .pulsate(5);</li>
</ol>
<p>Explications&#8230;</p>
<p>1 : C&#8217;est un sélecteur CSS3 qui récupère le paragraphe avec la classe &#8216;text&#8217; et &#8217;some text&#8217; quelque part à l&#8217;intérieur, depuis le div qui à l&#8217;id &#8216;main&#8217;.</p>
<p>2: Ensuite, ça ajoute un nouveau lien à la fin du paragraphe. Oui, on peut utiliser un sélecteur CSS ici aussi, pour spécifier l&#8217;id, la classe et les attributs.</p>
<p>3: Rien qu&#8217;un effet. Le nouveau lien va maintenant pulser (<em>fade out</em> puis <em>fade in</em>) cinq fois. =]</p>
<h3>Les sélecteurs de JQuery et de UTM sont vraiment plus rapides que ceux de Mootools, et les sélecteurs de UTM sont même encore plus rapide que ceux de JQuery. Peux-tu expliquer pourquoi?</h3>
<p>Bien sûr. À la base, UTM tourne plus vite pour trois raisons : la structure du code, le cache et la réutilisation des données des sélecteurs.</p>
<p>Quand je récupère un élément avec un nom de tag depuis un contexte, UTM stock un pointeur vers l&#8217;ensemble; donc, si j&#8217;ai besoin du même ensemble plus tard, UTM va simplement s&#8217;en resservir (ne vous inquiétez pas si un élément a été ajouté ou retiré: HTMLCollection est un objet natif de JS et n&#8217;a pas besoin d&#8217;être récupéré à nouveau).</p>
<p>Quant à la réutilisation des données, une fois que vous donnez un sélecteur à UTM, il est traité pas à pas et stocké en tant qu&#8217;objet. Il sera donc réutilisé par l&#8217;ensemble du moteur de sélection sans devoir être retraité à nouveau.</p>
<p>Et <strong>tout</strong> le code lié aux sélecteurs se trouve au même endroit. C&#8217;est simple à lire, toutes les fonctions sont placées au meilleur endroit possible.</p>
<h3>Tu m&#8217;as dit que la réponse à la question &#8220;quelle est la library la plus rapide&#8221; peut changer selon le navigateur et l&#8217;environnement. Peux-tu expliquer pourquoi et comment UTM gère ça?</h3>
<p>Cela dépend de deux facteurs : quelles fonctions du navigateur la library utilise et comment le navigateur gère le code. Par exemple, certains navigateurs ont une fonction appelée &#8216;document.getElementsByClassName&#8217;. C&#8217;est réellement plus rapide que n&#8217;importe quelle autre manière de récupérer des éléments à partir d&#8217;un nom de classe, et donc UTM l&#8217;utilise quand le navigateur la connaît.</p>
<p>Le navigateurs peuvent aussi avoir des comportements différents sur les même fonctions. IE6, par exemple, gère les instructions <em>switch</em> beaucoup plus lentement que Firefox. UTM essaie de s&#8217;adapter au navigateur tout en ayant le code le plus simple possible.</p>
<h3>Pourquoi UTM n&#8217;est pas entièrement orienté objet? Est-ce que ça a un impact sur les performances?</h3>
<p>L&#8217;objet principal <em>utm</em> est entièrement orienté objet. Le prototype principal possède toutes les méthodes que nous pouvons utiliser sur des éléments du DOM. Quelques fonctions simples ne sont pas orientées objet parce qu&#8217;elle ne doivent vraiment pas l&#8217;être, pour des raisons de simplicité.</p>
<p>Prenons par exemple u.Window (objet provenant du module <em>window</em>) et u.scrollTo (fonction non orientée objet provenant du module <em>scroll</em>). Nous pouvons faire :</p>
<p><em>var myWindow = new u.Window({ title: &#8216;a sample window&#8217; });</em></p>
<p>Cela a du sens, n&#8217;est-ce pas? Maintenant&#8230;</p>
<p><em>u(element).scrollTo(target);</em></p>
<p>Comment utiliserions-nous cela avec <em>new</em>? N&#8217;est-ce pas plus simple de cette façon? =]</p>
<p>La library est donc orientée objet quand c&#8217;est nécessaire pour des raisons d&#8217;usage/performance. Les fonctions les plus simples comme <em>u.trim</em> ou <em>u.clean</em> n&#8217;ont vraiment pas à être orientées objet, mais <em>u.Request</em> et <em>u.Window</em> le doivent.</p>
<h3>Est-ce qu&#8217;il est difficile d&#8217;élargir UTM avec de nouveaux modules?</h3>
<p>Non, c&#8217;est très simple. Il vous suffit d&#8217;ajouter une nouvelle fonction au core ou à la collection de ses méthodes d&#8217;éléments, ou d&#8217;écrire un module. En fait, il suffit d&#8217;ajouter du code dans le namespace utm, dans <em>utm.methods</em>, la collection de méthodes customs. Si vous écrivez un plugin, tout est déjà prévu pour que le code soit ajouté automatiquement au chargement.</p>
<h3>As-tu besoin d&#8217;une quelconque forme d&#8217;aide? Apprécierais-tu d&#8217;être rejoint par des codeurs français, et que peuvent-ils faire?</h3>
<p>Bien sûr! C&#8217;est un projet open-source qui a besoin de nous tous pour en faire le meilleur choix pour chacun. Je serai ravi si des codeurs français (et des gens de partout) étaient intéressés par le projet et commençaient à jouer avec. Tout type d&#8217;aide serait le bienvenu - opinions, suggestions, code, design de thèmes, tout.</p>
<h3>Merci d&#8217;avoir sacrifié un peu de ton temps à cet exercice. Bon courage pour la suite <img src='http://blog.olivier-elmekki.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </h3>
<p>Merci pour cette opportunité de répandre UTM et de le montrer à tes lecteurs! J&#8217;espère que le projet sera de plus en plus utile à tous. =]</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=156" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2008/10/04/interview-dun-createur-de-framework-javascript/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Optimiser l&#8217;utilisation des sélecteurs JQuery</title>
		<link>http://blog.olivier-elmekki.com/2008/09/30/optimiser-lutilisation-des-selecteurs-jquery/</link>
		<comments>http://blog.olivier-elmekki.com/2008/09/30/optimiser-lutilisation-des-selecteurs-jquery/#comments</comments>
		<pubDate>Tue, 30 Sep 2008 15:10:07 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=135</guid>
		<description><![CDATA[Dans un article précédent, je vous ai montré comment construire des sélections complexes avec JQuery. Il est temps maintenant de déconstruire.
Staicu Ionut a récemment publié un article dans lequel il revient sur une &#8220;grosse erreur&#8221; dans la considération des performances des sélecteurs de JQuery : considérer que la sélection est plus rapide lorsque l&#8217;expression de [...]]]></description>
			<content:encoded><![CDATA[<p>Dans <a href="http://blog.olivier-elmekki.com/2008/09/25/utilisation-avancee-des-selecteurs-jquery/">un article précédent</a>, je vous ai montré comment construire des sélections complexes avec JQuery. Il est temps maintenant de déconstruire.</p>
<p><a href="http://dev.iamntz.com/">Staicu Ionut</a> a récemment publié <a href="http://dev.iamntz.com/78/which-selector-is-faster">un article</a> dans lequel il revient sur une &#8220;grosse erreur&#8221; dans la considération des performances des sélecteurs de JQuery : considérer que la sélection est plus rapide lorsque l&#8217;expression de recherche est plus spécifique.</p>
<p><span id="more-135"></span></p>
<h3>Huge mistake!</h3>
<p>Pour ceux qui ne saisissent pas bien le terme, être plus spécifique, c&#8217;est être plus précis. Soit le code HTML suivant :</p>
<blockquote><pre>&lt;body&gt;
  &lt;ul id="menu"&gt;
    &lt;li&gt;&lt;a href="lien"&gt;lien&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="lien"&gt;lien&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="lien"&gt;lien&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;paragraphe&lt;/p&gt;
  &lt;p&gt;paragraphe&lt;/p&gt;
&lt;/body&gt;</pre>
</blockquote>
<p>On considérait que pour sélectionner les liens, il valait mieux utiliser :</p>
<blockquote><pre>$( "ul li a" )</pre>
</blockquote>
<p>Plutôt que le moins spécifique :</p>
<blockquote><pre>$( "a" )</pre>
</blockquote>
<p>Je soupçonne cette recommandation d&#8217;être dérivée des pratiques du CSS, où il est préférable de toujours être le plus spécifique possible si on ne veut pas avoir des surprises dans l&#8217;ordre de priorité des règles.</p>
<p>Selon les tests de Staicu, réalisés avec la fonction profile() de firebug, la seconde forme est pourtant significativement plus rapide.</p>
<p>La raison en est, après coup, évidente : dans la première forme, JQuery cherche d&#8217;abord tous les <em>ul</em>, puis tous les <em>li</em> internes, puis tous les <em>a</em> internes.</p>
<h3>Les solutions</h3>
<p>Pour commencer, il est toujours préférable d&#8217;utiliser un <em>id</em> ou une <em>class</em> plutôt qu&#8217;une chaîne de sélection. Ainsi, plutôt que de faire <em>$( &#8220;#menu li a&#8221; )</em>, il est préférable de donner la classe <em>.menuLink</em> aux <em>a</em> et de faire <em>$( &#8220;.menuLink&#8221; )</em>. Cela semble évident pour ce cas simple, ça l&#8217;est moins dans des chaînes complexes. Une règle simple à retenir : <em>la chaîne la plus courte est toujours la meilleure</em>.</p>
<p>Une autre possibilité d&#8217;optimisation apparaît alors. Si on place à la base de chaque sélecteur un <em>id</em> ou une <em>class</em>, pourquoi ne pas directement passer par les fonctions builtins de javascript? J&#8217;ai moi-même effectué des tests avec le profiler de firebug et j&#8217;ai obtenu des résultats significatifs me laissant penser ceci : <strong>il est plus rapide d&#8217;utiliser getElementById ou getElementsByClassName puis de s&#8217;en servir comme contexte dans un sélecteur JQuery</strong>, plutôt que de selectionner le tout en une expression JQuery.</p>
<p>Ainsi :</p>
<blockquote><pre>$( "#menu li" )</pre>
</blockquote>
<p>peut être remplacé, pour optimiser les performances, par :</p>
<blockquote><pre>var context = document.getElementById( "menu" ) ;
$( "li", $(context) ) ;</pre>
<p>Voici les deux fonctions que j&#8217;ai utilisé dans firebug pour faire mes tests :</p>
<pre>function a(){ for (var i=0;i&lt;10;i++){ $( "#menu li" ) } }
function b(){ for (var i=0;i&lt;10;i++){ var c=document.getElementById( "menu" ) ; $( "li", $(c) ) } }</pre>
</blockquote>
<p>Après avoir profilé ces deux fonctions individuellement une dizaine de fois, il s&#8217;avère que la fonction a() s&#8217;execute généralement dans le double du temps de la fonction b().</p>
<p>Plutôt refroidissant&#8230; Un petit bémol pourtant : nos machines double processeurs avec un giga de RAM peuvent <em>très bien</em> utiliser les techniques les plus lentes de sélection sans même que nous nous en rendions compte. Ce problème ne risque en fait que d&#8217;affecter les applications desktop-like de type web3 (comme greader, ou le promis google desktop), qui font un usage intensif de javascript. De quoi nous laisser le temps de voir venir, surtout qu&#8217;il y a&#8230;</p>
<h3>Une bonne nouvelle</h3>
<p><a href="http://ejohn.org/">John Resig</a> (le créateur de JQuery) travaille actuellement sur <a href="http://ajaxian.com/archives/sizzle-john-resig-has-a-new-selector-engine">un nouveau moteur de sélection</a>. Il estime qu&#8217;il sera quatre fois plus rapide que le moteur actuel. Time will tell&#8230;</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=135" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2008/09/30/optimiser-lutilisation-des-selecteurs-jquery/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Test Driven Development avec Ruby on Rails</title>
		<link>http://blog.olivier-elmekki.com/2008/09/27/test-driven-development-avec-ruby-on-rails/</link>
		<comments>http://blog.olivier-elmekki.com/2008/09/27/test-driven-development-avec-ruby-on-rails/#comments</comments>
		<pubDate>Sat, 27 Sep 2008 13:11:53 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=127</guid>
		<description><![CDATA[Matt Moore a récemment publié une checklist permettant de vérifier la qualité de son code rails. La plupart des développeurs la liront avec satisfaction en se disant : &#8220;la séparation de la logique et des vues, c&#8217;est bon&#8230; La simplification des requêtes à la db, c&#8217;est fait&#8230; Le maintient de la simplicité des contrôleurs, bien [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.matthewpaulmoore.com/">Matt Moore</a> a récemment publié une <a href="http://www.matthewpaulmoore.com/articles/1276-ruby-on-rails-code-quality-checklist">checklist</a> permettant de vérifier la qualité de son code rails. La plupart des développeurs la liront avec satisfaction en se disant : &#8220;la séparation de la logique et des vues, c&#8217;est bon&#8230; La simplification des requêtes à la db, c&#8217;est fait&#8230; Le maintient de la simplicité des contrôleurs, bien entendu&#8230;&#8221;. Puis vient la question des tests. &#8220;Ah oui, euh&#8230; boaf&#8221;.</p>
<p><span id="more-127"></span></p>
<p>Il y a plusieurs raisons qui causent la désaffection des outils de tests de ruby on rails :</p>
<ul>
<li>C&#8217;est un ensemble de méthodes nouvelles à prendre en mains. Ces méthodes ne sont jamais utilisées dans une application normale et il faut donc d&#8217;abord s&#8217;y familiariser.</li>
<li>Dans une première approche, ces outils semblent particulièrement mal documentés.</li>
<li>On ne voit pas l&#8217;intérêt de perdre du temps à écrire une batterie de test alors qu&#8217;on vient de tester manuellement son code au fur et à mesure qu&#8217;on l&#8217;écrivait. C&#8217;est tout sauf &#8220;<a href="http://fr.wikipedia.org/wiki/DRY">DRY</a>&#8220;-ant ou <a href="http://fr.wikipedia.org/wiki/M%C3%A9thode_agile">agile</a>.</li>
</ul>
<p>Cette dernière raison est particulièrement défendable et on en vient vite à se demander comment <a href="http://fr.wikipedia.org/wiki/David_Heinemeier_Hansson">David Heinemeier Hansson</a> peut à la fois répéter si souvent qu&#8217;il <strong>faut</strong> écrire des tests et en même temps souscrire aux recommandation du <a href="http://gettingreal.37signals.com/"><em>getting real</em></a>.</p>
<h3>Quand dois-je écrire mes tests?</h3>
<p>C&#8217;est en effet des différentes réponses à cette question que vient le malentendu. Deux choix courants conduisent à rapidement négliger les tests :</p>
<ul>
<li>Écrire ses tests lorsqu&#8217;on a terminé son modèle ou son contrôleur.</li>
<li>Écrire ses tests après avoir fini d&#8217;écrire une méthode.</li>
</ul>
<p>Le premier choix décourage vite en face du laborieux travail à exécuter, qui se montre parfois plus conséquent que l&#8217;écriture première du code, particulièrement si on ne fait pas une application à base de <a href="http://fr.wikipedia.org/wiki/CRUD">CRUD</a>. Le second choix est plus flexible, mais on se voit obligé de revenir souvent dans le code des tests parce qu&#8217;à l&#8217;écriture de la méthode suivante, on se rend compte qu&#8217;il faut finalement modifier un peu la précédente.</p>
<p>Il y a heureusement une troisième option, et c&#8217;est celle qui constitue le sujet de ce billet : <a href="http://fr.wikipedia.org/wiki/Test_Driven_Development"><em>le développement piloté par tests</em></a>.</p>
<p>Le développement piloté par tests inverse radicalement la conception que nous avons des tests. Au lieu de les écrire <em>a posteriori</em> lorsque nous avons terminé un pan de code, il nous conseille d&#8217;écrire les tests préalablement à tout code.</p>
<h3>Quel intérêt?</h3>
<p>L&#8217;idée de tester du code qui n&#8217;existe pas encore peut paraître étrange, mais c&#8217;est pourtant une technique puissante de développement agile et solide.</p>
<p>Lorsque vous vous lancez dans l&#8217;écriture de votre code, vous devez déjà avoir une idée des différents éléments qui vont composer votre application et de la manière dont ils vont se comporter. Je ne parle bien sûr pas des nouvelles fonctionnalités qui viendront étendre votre application par la suite lorsque le besoin s&#8217;en fera ressentir, mais de la stricte base : mon application contient des <em>User</em>, des <em>Article</em> et des <em>Comment</em> ; chacun doit pouvoir être créé, montré, modifié et effacé, les <em>Article</em> doivent être rattachés à un <em>User</em> et les <em>Comment</em> à un <em>Article</em>. Rajoutez à cela les quelques fonctionnalités particulières à votre application.</p>
<p>Vous pouvez écrire ce design original dans un fichier texte, ou vous pouvez en faire des tests.</p>
<p>Et c&#8217;est là tout l&#8217;intérêt des tests : ils servent de todo list. En les écrivant <em>avant</em> le code, vous vous assurez:</p>
<ul>
<li>d&#8217;avoir une idée claire de ce que vous allez faire.</li>
<li>de savoir précisément où vous en êtes dans votre processus de développement (en faisant signaler les fonctions non écrites ou en faisant échouer leur test).</li>
<li>que la nouvelle méthode que vous avez implémentée ne casse pas les précédentes.</li>
</ul>
<p>C&#8217;est donc bel et bien un atout pour le développement agile, car cela permet d&#8217;assurer la simplicité, l&#8217;abstraction et la cohérence de votre code sans devoir revenir sur chaque méthode chaque fois que vous ajoutez un nouveau block de code : les tests vous préviendront si vous devez modifier quelque chose en amont. Cela n&#8217;exclue bien sûr pas la nécessité de faire des vrais tests manuels lorsque vous avez terminé une version de votre application, cela permet juste de rendre le développement plus rapide.</p>
<h3>Mais où est la documentation?</h3>
<p>Si vous avez déjà jeté un bref regard au fonctionnement des tests, vous avez sûrement été frustré de ne pas trouver les méthodes dans <a href="http://api.rubyonrails.com/">la documentation officielle de rails</a>. Où est cet <em>assert</em> partout utilisé? Il y a bien toute une collection de assert_* dans <a href="http://api.rubyonrails.com/classes/ActionController/Assertions.html">ActionController::Assertions</a>, mais les fonctions de base sont introuvables.</p>
<p>La raison en est simple : les outils de tests font partie d&#8217;un framework de tests indépendant et intégré dans rails (et faisant aujourd&#8217;hui partie de la librairie standard de ruby), <a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html">Test::Unit</a>. Vous trouverez dans sa documentation tous les <a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit/Assertions.html">éléments de base</a> dont vous avez besoin.</p>
<p>Rails étend ensuite ces tests avec ses propres ajouts, et particulièrement pour les tests fonctionnels (tests effectués sur les contrôleurs).</p>
<p>Je n&#8217;ai pas trouvé d&#8217;articles à jour et de qualité en français expliquant en détail la marche à suivre pour utiliser les tests dans rails, je reviendrai donc dessus par la suite avec deux articles, l&#8217;un sur les tests unitaires (pour tester les modèles) et l&#8217;autre sur les tests fonctionnels (pour tester les contrôleurs).</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=127" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2008/09/27/test-driven-development-avec-ruby-on-rails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Utilisation avancée des sélecteurs JQuery</title>
		<link>http://blog.olivier-elmekki.com/2008/09/25/utilisation-avancee-des-selecteurs-jquery/</link>
		<comments>http://blog.olivier-elmekki.com/2008/09/25/utilisation-avancee-des-selecteurs-jquery/#comments</comments>
		<pubDate>Thu, 25 Sep 2008 00:46:21 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=114</guid>
		<description><![CDATA[Après avoir utilisé longtemps Prototype et Scriptaculous qui forment le framework Javascript par défaut dans Ruby on Rails, les sélecteurs de JQuery m&#8217;ont convaincu de passer à ce dernier (enfin, ça et la possibilité de ne charger qu&#8217;une partie du DOM de la réponse dans les requêtes ajax replace).
Dans un article récent faisant partie d&#8217;un [...]]]></description>
			<content:encoded><![CDATA[<p>Après avoir utilisé longtemps Prototype et Scriptaculous qui forment le framework Javascript par défaut dans Ruby on Rails, les sélecteurs de JQuery m&#8217;ont convaincu de passer à ce dernier (enfin, ça et la possibilité de ne charger qu&#8217;une partie du DOM de la réponse dans les requêtes ajax <em>replace</em>).</p>
<p>Dans <a href="http://www.pckult.net/category-table/1350-apprendre-jquery-lecon--introduction-aux-selecteurs">un article récent</a> faisant partie d&#8217;un ensemble d&#8217;articles d&#8217;initiation à JQuery, <span class="createby"><a href="http://www.pckult.net/">Dave Lizotte</a> à fait une présentation rapide des sélecteurs. J&#8217;y reviens maintenant pour présenter les fonctionnalités avancées.</span></p>
<p><span id="more-114"></span></p>
<h3>Le DOM, c&#8217;est quoi?</h3>
<p>Au préalable, il est important que vous ayez saisi <a href="http://fr.wikipedia.org/wiki/Document_Object_Model">ce qu&#8217;est le DOM</a>, car c&#8217;est sur lui qu&#8217;agissent les sélecteurs. Je ne vais pas réécrire ici <a href="http://www.w3.org/DOM/">la documentation du w3c</a>, sachez simplement, si vous êtes étranger à cette notion, qu&#8217;il s&#8217;agit d&#8217;une structure représentant votre fichier HTML.</p>
<p>Imaginez-vous une vue en arborescence, avec l&#8217;<strong>élément</strong> <em>html</em> à la racine, et en enfants, les <strong>éléments</strong> <em>head </em>et <em>body</em>. En dépliant encore, vous trouverez les différents <strong>éléments</strong> enfants, par exemple un <em>div</em> dans le <em>body</em>, puis un <em>p</em> dans ce <em>div</em>, etc. Pour chacun, vous aurez accès à des attributs (<em>title, id, class</em>, etc) et à un contenu (le <em>innerHTML</em>).</p>
<p>Il vous suffit en fait de vous représenter ça, vous n&#8217;avez rien à apprendre. Le DOM n&#8217;est pas un langage, juste une interface. Au final, vous aurez l&#8217;impression d&#8217;agir directement sur le code HTML, et c&#8217;est ce que vous ferez, mais par l&#8217;intermédiaire du DOM.</p>
<p>Si vous voulez vous représenter cela plus visuellement et vous familiariser à la manipulation du DOM, je vous conseille l&#8217;excellente extension firefox qu&#8217;on ne présente plus : <a href="http://getfirebug.com/">firebug</a>.</p>
<h3>On sélectionne quoi, au fait?</h3>
<p>Les sélecteurs de JQuery servent à isoler des éléments du DOM. C&#8217;est en fait ce que font la plupart du temps les frameworks Javascript : modifier les éléments du DOM pour changer dynamiquement la page. Pour pouvoir faire cela, il est nécessaire de pouvoir cibler précisément un élément en particulier, ou un groupe d&#8217;éléments. C&#8217;est le travail du sélecteur.</p>
<p>Notez tout de suite qu&#8217;un sélecteur ne renvoie pas nécessairement un unique élément. Si vous utilisez le sélecteur <em>$( &#8216;p&#8217; )</em>, vous obtiendrez en retour tous les &lt;p&gt; de la page. Il est possible d&#8217;itérer sur chacun grâce à la fonction <a href="http://docs.jquery.com/Core/each#callback">each</a>, mais si vous désirez un élément précis, soyez vous-même le plus précis possible dans votre code (la manière la plus simple étant de sélectionner un élément à partir de son <em>id</em>, comme par exemple <em>$( &#8216;#footer&#8217; )</em> ).</p>
<h3>On avait pas dit : &#8220;avancé&#8221; ?</h3>
<p>Si. Que ceux qui connaissaient déjà tout cela m&#8217;excusent, ce préambule me semblait indispensable pour être sûr que ce soit clair pour tout le monde.</p>
<p>Dans un usage basique, on se content de sélectionner un <em>id</em>, une <em>classe</em> ou un <em>élément.</em> Les sélecteurs JQuery permettent pourtant d&#8217;utiliser de puissantes et complexes expressions qui raviront les adeptes d&#8217;expressions régulières illisibles. Les outils de ces expressions se classent en deux familles : les selecteurs par hiérarchie et les sélecteurs par filtre. Le mélange savant de ces outils vous permettra de faire des sélections riches et précises.</p>
<h3>La sélection par hiérarchie</h3>
<p>Comme je l&#8217;ai dit plus haut, il faut penser le DOM sur le mode d&#8217;une arborescence. Il y a donc des nœuds enfants et des nœuds parents. JQuery permet de naviguer précisément dans cet arbre. Nous allons voir comment au travers de quelques exemples.</p>
<p><em>Note</em>: j&#8217;ai d&#8217;abord pensé faire un fichier HTML d&#8217;exemple complexe auquel chaque exemple de sélecteur ferait référence, mais cela vous obligerait à remonter dans la page à chaque fois. Je vais donc dupliquer du code pour chaque exemple, au coût d&#8217;une page plus longue.</p>
<p><strong>La sélection des descendants</strong> est la plus commune. Soit le code :</p>
<blockquote>
<pre>&lt;div id="header"&gt;
  &lt;img src="logo" /&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="lien"&gt;lien1&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="lien2"&gt;lien2&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;div id="content"&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;img src="photo1.jpg" /&gt;&lt;/li&gt;
    &lt;li&gt;&lt;img src="photo2.jpg" /&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;</pre>
</blockquote>
<p>(au passage, je signale qu&#8217;un <em>img</em> doit toujours avoir un attribut <em>alt</em> pour être valide en xhtml strict, et que chaque fois que vous utilisez un div inutile, <a href="http://blog.olivier-elmekki.com/2008/09/08/soyez-moderne-faites-du-html-des-90/">vous tuez un chaton</a>, mais j&#8217;utilise ici des raccourcis pour l&#8217;exemple).</p>
<p>Comment vais-je faire si je veux sélectionner les deux photos? Rien n&#8217;est plus simple :</p>
<blockquote>
<pre>$( '#content img' )</pre>
</blockquote>
<p><em>img</em> placé après <em>#content </em>signifie qu&#8217;il faut selectionner tous les <em>img </em>descendant de <em>#content</em>. Ici, les <em>img </em>ne sont pas directement enfants de <em>#content</em>, mais puisqu&#8217;ils sont enfants de <em>li</em> eux-même enfants d&#8217;un <em>ul</em> lui-même enfant de <em>#content</em>, ils en sont descendants.</p>
<p>Si on ne veut pas sélectionner tous les descendants mais seulement <strong>les enfants directs</strong>, on utilise &#8220;&gt;&#8221;. Ainsi :</p>
<blockquote>
<pre>&lt;div id="content"&gt;
  &lt;img src="viagra.jpg" /&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;img src="photo1.jpg" /&gt;&lt;/li&gt;
    &lt;li&gt;&lt;img src="photo2.jpg" /&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;</pre>
</blockquote>
<p>Si je veux sélectionner la publicité pour l&#8217;envoyer aux oubliettes, mais pas les photos (de préférences), je peux utiliser ceci :</p>
<blockquote>
<pre>$( '#content &gt; img' )</pre>
</blockquote>
<p>Cela ne prenant en compte que les enfants directs, les photos, à la charge des <em>li</em>, sont ignorées sur le testament.</p>
<p>Vous devez maintenant saisir un peu mieux la nature des sélecteurs, nous allons pouvoir aller un peu plus vite. Les deux sélecteurs hiérarchiques suivants sont plus amusants, mais je vous dois une mise en garde : ils sont aussi plus sensibles aux modifications de votre code et peuvent causer des bugs difficiles à repérer.</p>
<p><strong>Le sélecteur par proximité</strong> permet de sélectionner un élément directement adjacent à un autre.</p>
<blockquote>
<pre>$( 'li + img' )</pre>
</blockquote>
<p>Cela permet de sélectionner un <em>img</em> directement adjacent à un <em>li</em> (attention: le <em>li </em>lui-même n&#8217;est pas sélectionné).</p>
<p><strong>Le sélecteur de fratrie </strong>permet de sélectionner tous les éléments de même type ayant un même parent, situé directement après un frère de référence :</p>
<blockquote>
<pre>&lt;ul id="famille"&gt;
  &lt;li id="premier"&gt;enfant 1&lt;/li&gt;
  &lt;li id="second"&gt;enfant 2&lt;/li&gt;
  &lt;li id="troisieme"&gt;enfant 3&lt;/li&gt;
  &lt;li id="quatrieme"&gt;enfant 4&lt;/li&gt;
&lt;ul&gt;</pre>
</blockquote>
<p>Ici, pour sélectionner tous les enfants qui ne sont pas l&#8217;ainé, on utilisera :</p>
<blockquote>
<pre>$( '#premier ~ li' )</pre>
</blockquote>
<p>Il faut aussi noter que certaines fonctions, ne relevant pas directement des sélecteurs, permettent d&#8217;aller encore plus loin, comme la fonction <em>parent()</em>, qui retourne le parent de l&#8217;élément sélectionné.</p>
<p>Vous savez donc maintenant traverser précisément l&#8217;arborescence du DOM. Des expressions complexes telles que <em>$( &#8216;#content &gt; ul p span + img&#8217; )</em> sont tout à fait possible et vous permettent de manipuler des pages complexes. Mais ce n&#8217;est ici encore que de la sélection intermédiaire, JQuery nous offre encore d&#8217;avantage.</p>
<h3>Les filtres</h3>
<p>JQuery possède une très vaste collection de filtres permettant d&#8217;affiner vos sélections. Je ne vais pas tous les énumérer tant ils sont nombreux, mais je vais vous présenter ceux qui me semblent les plus utiles. Une fois que vous y serez familiarisés, et avec ce qui précède, la <a href="http://docs.jquery.com/Selectors">documentation officielle</a> vous suffira à trouver votre chemin (oui, ce qu&#8217;on vient de voir ne représente pas un dixième de la page :] ).</p>
<p><strong>:first</strong> est sans doute le filtre le plus utile lorsque vous voulez être certain de ne sélectionner qu&#8217;un seul élément. Il s&#8217;utilise ainsi : <em>$( &#8216;#content ul:first&#8217; )</em>. Quelque soit le nombre de <em>ul</em> que contient <em>#content</em>, seul le premier sera sélectionné. Dans le même genre, il y a <strong>:last</strong>.</p>
<p><strong>:eq(index)</strong> permet de sélectionner un élément comme si c&#8217;était l&#8217;élément d&#8217;un tableau (pour ceux qui ne sont pas familiarisés avec les tableaux en informatique, sachez qu&#8217;on compte à partir de 0). Je peux donc facilement sélectionner le troisième <em>li</em> du <em>ul#items</em> en faisant : <em>$( &#8216;#items li:eq(2)&#8217; )</em>. De la même manière, il y a <strong>:gt(index)</strong> pour <em>plus grand que</em> (greater than) et <strong>:lt(index)</strong> pour <em>plus petit que</em> (lesser than).</p>
<p><strong>:contains(text)</strong> permet de sélectionner un élément sur la base de son contenu. Ainsi, je peux sélectionner toutes mes notes en faisant : <em>$( &#8216;p:contains(&#8221;N.B.&#8221;)&#8217; ).</em></p>
<p><strong>[attribut]</strong> permet de filtrer sur la base de l&#8217;existence d&#8217;un attribut. Cela prend tout son sens dans la forme <strong>[attribut=valeur]. </strong>Ainsi, je peux sélectionner toutes les images de ma maison en faisant : <em>$( &#8216;img[src="images/maison.jpg"]&#8216; )</em>. Une autre forme intéressante est <strong>[attribut*=valeur]</strong>, le wildcard permettant de préciser une valeur qui ne soit pas exacte. Cela me permet par exemple de sélectionner tous les liens vers le site <em>exemple.fr</em>, quelque soit la page liée, ainsi : <em>$( &#8216;a[href*="exemple.fr"]&#8216; ) .</em></p>
<p>Enfin, si vous codez du CSS, vous avez forcément déjà été ennuyé par l&#8217;impossibilité de faire référence à tous les titres en même temps, mais de devoir utiliser <em>h1,h2,h3</em> ou encore ennuyé par le fait qu&#8217;un <em>textfield</em> et un <em>submit</em> sont tous les deux un élément <em>input</em>. JQuery facilite tout ça, grâce au filtre <strong>:heading</strong> et aux filtres de formulaire.</p>
<p>Pour sélectionner tous les titres, utilisez simplement <em>$( &#8216;:heading&#8217; ) .</em> Pour sélectionner le bouton d&#8217;envoi d&#8217;un formulaire de commentaire, on utilise, par exemple : <em>$( &#8216;#comment_form :submit&#8217; )</em>. Il existe un équivalent pour chaque type de <em>input.</em></p>
<h3>La cerise sur le gâteau : le contexte.</h3>
<p>J&#8217;espère que vous avez digéré tout cela, c&#8217;était copieux. Après avoir joué un peu avec ces sélecteurs, vous devez entrevoir de vastes et complexes possibilités pour sélectionner précisément ce <em>li</em> caché au fin fond d&#8217;une série de <em>div</em>, et les <em>div</em> voisins ne vous ennuieront pas grâce à la puissante chaîne de filtres que vous avez organisée&#8230;</p>
<p>Oubliez tout.</p>
<p>JQuery, c&#8217;est la puissance, mais c&#8217;est aussi la simplicité. Pour éviter d&#8217;avoir à écrire des sélecteurs de trois lignes, un système de sélection en contexte a été développé. Imaginons le sélecteur suivant :</p>
<blockquote>
<pre>$( '#content ul:first &gt; li:eq(3) &gt; div.hilighted:gt(2) ul' )</pre>
</blockquote>
<p>Si je veux opérer sur plusieurs éléments dépendant de ces <em>ul</em> en plusieurs étapes, il serait fastidieux de réécrire ce sélecteur en le complexifiant encore. Le contexte permet de faire ceci :</p>
<blockquote>
<pre>var context = $( '#content ul:first &gt; li:eq(3) &gt; div.hilighted:gt(2) ul' ) ;
$( 'li:eq(3)', context ).hide() ;
$( 'li:first &gt; a', context ).css( 'color', '#A37BCF' ) ;</pre>
</blockquote>
<p>Rien ne vous empêche ensuite de coder une fonction dont le contexte sera variable.</p>
<p>Voilà, j&#8217;espère que cette explication aura été éclairante, n&#8217;hésitez pas à me faire part de vos réactions.</p>
<p>Entraînez-vous à utiliser des selecteurs complexes puis, lorsque vous maîtriserez leurs différentes possibilités, vous pourrez passer à un autre niveau de compréhension. <a href="http://boagworld.com/">Paul Boag et Marcus Lillington</a> ont avancé dans <a href="http://boagworld.com/podcast/136/">un podcast</a> l&#8217;idée que lorsqu&#8217;une application correctement lancée s&#8217;approche de la maturité, elle connaît une période de stagnation et que pour sortir de cette stagnation, il faut <em>simplifier</em>. C&#8217;est ce que je vous propose dans un <a href="http://blog.olivier-elmekki.com/2008/09/30/optimiser-lutilisation-des-selecteurs-jquery/">prochain article</a>.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=114" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2008/09/25/utilisation-avancee-des-selecteurs-jquery/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
