<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Jérémy Lecour &#187; PLUG</title>
	<atom:link href="http://jeremy.wordpress.com/category/informatique/plug/feed/" rel="self" type="application/rss+xml" />
	<link>http://jeremy.wordpress.com</link>
	<description>Concepteur et développeur d&#039;applications web</description>
	<lastBuildDate>Thu, 23 May 2013 14:43:45 +0000</lastBuildDate>
	<language>fr</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='jeremy.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Jérémy Lecour &#187; PLUG</title>
		<link>http://jeremy.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://jeremy.wordpress.com/osd.xml" title="Jérémy Lecour" />
	<atom:link rel='hub' href='http://jeremy.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Redis et la séparation des données entre les projets</title>
		<link>http://jeremy.wordpress.com/2012/04/25/redis-et-la-separation-des-donnees-entre-les-projets/</link>
		<comments>http://jeremy.wordpress.com/2012/04/25/redis-et-la-separation-des-donnees-entre-les-projets/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 12:44:30 +0000</pubDate>
		<dc:creator>Jérémy Lecour</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[PLUG]]></category>
		<category><![CDATA[redis]]></category>

		<guid isPermaLink="false">http://jeremy.wordpress.com/?p=391</guid>
		<description><![CDATA[Le 24 avril, Geoffrey Grosenbach demandait si on utilise des bases Redis (internes à une instance du serveur) différentes pour chaque projet, ou bien une seule, en espérant qu&#8217;il n&#8217;y ait pas de collision de clés. Cet article présente la &#8230; <a href="http://jeremy.wordpress.com/2012/04/25/redis-et-la-separation-des-donnees-entre-les-projets/">Lire la suite <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=391&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Le 24 avril, <a href="http://twitter.com/#!/topfunky/status/194934050241253376">Geoffrey Grosenbach demandait</a> si on utilise des bases Redis (internes à une instance du serveur) différentes pour chaque projet, ou bien une seule, en espérant qu&#8217;il n&#8217;y ait pas de collision de clés. Cet article présente la manière de faire que j&#8217;ai adopté.</p>
<h2 id="rappel">Rappel</h2>
<p>Redis est une base de données &#8220;clés/valeurs&#8221;. C&#8217;est une manière de stocker et accéder aux données très différente des système relationnels tels que MySQL, Oracle, …</p>
<p>Pour comprendre le fonctionnement de Redis, je conseille la lecture du livre de <a href="http://openmymind.net/">Karl Seguin</a> : <a href="https://github.com/karlseguin/the-little-redis-book">The Little Redis Book</a>.</p>
<p>Le serveur Redis (<code>redis-server</code>) est une application autonome, qui fonctionne avec un seul thread, accessible via un port TCP ou bien un socket système.</p>
<p>Il dispose de plusieurs bases internes, dont la seule distinction est un numéro d&#8217;ordre. Il y en a 16 par défaut (c&#8217;est configurable) et si le client ne spécifie pas de base particulière, il est connecté à la première (numérotée 0).</p>
<p>Au sein d&#8217;une base, Redis stocke des <a href="http://redis.io/topics/data-types">objets typés</a> (les <strong>valeurs</strong>), accessibles par un index unique (les <strong>clés</strong>). Une clé est une simple suite de caractère, par exemple &#8220;metrics:users:count&#8221;. Le choix du &#8220;:&#8221; comme séparateur &#8220;sémantique&#8221; est totalement arbitraire et laissé au choix du développeur et permet de facilement reconstituer mentalement une arborescence de clés. Aux yeux de Redis, l&#8217;exemple précédent est strictement identique à &#8220;metrics/users/count&#8221;, &#8220;MetricsUsersCount&#8221; ou même &#8220;hello&#8221;.</p>
<h2 id="sparer_ses_donnes">Séparer ses données</h2>
<p>Lorsqu&#8217;on manipule des données dans des contextes différents le risque est de contaminer les données d&#8217;un contexte depuis un autre contexte. Il convient alors d&#8217;utiliser un système qui permet de ne pas mélanger les données selon le contexte. Pour un projet qui peut fonctionner dans des environnements de test, développement et de production, les données doivent être partitionnées.<br />
Si on a plusieurs projets en simultané, il faut également séparer leurs données.</p>
<p>La première approche est d&#8217;utiliser un espace de nommage. Encore une fois, pour Redis ça n&#8217;est pas une fonction particulière, mais juste une convention de nommage des clés. On peut alors préfixer nos clés par le nom du projet et son environnement : &#8220;projet1:dev:metrics:users:count&#8221; sera alors bien séparé de &#8220;projet2:prod:metrics:users:count&#8221;.</p>
<p>Le problème avec cette approche est que pour Redis, tout est dans le même panier. Il devient impossible de supprimer toutes les clés du &#8220;projet 1&#8221; uniquement. De même parcourir le contenu de la base à la recherche d&#8217;une clé est moins facile.</p>
<p>On peut alors utiliser une base interne différente pour chaque projet. Il conviendra alors au client de se connecter à la bonne base, mais ensuite tout est bien séparé.</p>
<p>Le problème est que Redis ne permet pas de nommer les bases internes, elles sont simplement numérotées. Il n&#8217;y a pas non plus de configuration particulière pour les bases (persistance, sécurité, …). Rien n&#8217;empêche un client de se connecter à la mauvaise base d&#8217;y mettre la pagaille.</p>
<p>De plus, le support des bases internes multiples <del>va être déprécié</del> ne sera pas supporté dans Redis Cluster, il est donc prudent d&#8217;étudier une autre alternative.</p>
<p>Il reste une troisième solution ; 1 serveur Redis par projet.</p>
<h2 id="configurer_et_utiliser_plusieurs_instances">Configurer et utiliser plusieurs instances</h2>
<p>Le serveur Redis est un simple binaire qui n&#8217;a aucun mal a être lancé plusieurs fois en parallèle. Par défaut il va chercher sa configuration à un emplacement prédéfini, mais rien n&#8217;empêche de le lancer avec une configuration spécifique à chaque fois. </p>
<p>Les variations minimales à faire entre les configurations sont au moins le moyen d&#8217;accéder à l&#8217;instance (port TCP ou socket système) et l&#8217;emplacement des données.</p>
<p>Il suffit de créer un fichier de configuration et un script d&#8217;initialisation pour chaque instance et le tour est joué.</p>
<p>Le choix d&#8217;en faire une pour chaque environnement au sein d&#8217;un même projet n&#8217;est pas si compliqué :</p>
<ul>
<li>sur un serveur il n&#8217;y a le plus souvent que l&#8217;instance de &#8220;production&#8221; ;</li>
<li>sur le poste d&#8217;un développeur, il peut y avoir une instance de &#8220;développement&#8221; (permanente ou lancée au besoin) ;</li>
<li>pour un environnement de &#8220;test&#8221;, on peut avoir une instance démarrée à la volée, sans persistance sur le disque. Elle est donc re-initialisée à chaque fois, ce qui convient assez bien à ce type d&#8217;usage ;</li>
</ul>
<h2 id="avantages_des_instances_multiples">Avantages des instances multiples</h2>
<p>Il existe plusieurs grands avantages à utiliser Redis de cette manière</p>
<p>Une <strong>séparation stricte des données</strong> ; une fois connecté à un serveur, seules les données qu&#8217;il gère sont accessibles, sans risque de pollution. La sauvegarde/copie/déplacement des fichiers de persistance devient triviale, le vidage éventuel d&#8217;une base devient sans risque pour les autres données.</p>
<p>Une <strong>configuration adaptée</strong> ; il est possible de gérer la persistance des données de manière différente pour chaque instance, mais aussi d&#8217;utiliser un socket système pour certaines et un port TCP pour d&#8217;autre, des protections par authentification (ou pas), ou tout autre paramètre de configuration.</p>
<p>Une <strong>utilisation à la demande</strong> ; il est possible de ne lancer telle ou telle instance du serveur que lorsque c&#8217;est nécessaire. Sur un serveur en production, elles seront probablement toutes lancées en même temps, mais en développement ou sur un serveur d&#8217;intégration continue ça peut être utile (avec <a href="http://ddollar.github.com/foreman/">Foreman</a> par exemple).</p>
<p>Une <strong>supervision spécifique</strong> ; on peut mettre en place des outils de supervision adaptés à chaque instance en fonction de son niveau de criticité. Une instance critique pourra être suivie de très près (y compris avec des tests sur la présence de clés/valeurs spécifiques), avec des graphiques exhaustifs sur les ressources, … Dans le même temps, une autre instance pourra être simplement testée sur le fait que son processus est bien présent et rien d&#8217;autre. </p>
<p>Il est important de noter que chaque instance du serveur <a href="http://stackoverflow.com/questions/7651537/one-redis-server-per-rails-app/7672709#7672709">Redis n&#8217;occupe qu&#8217;environ 1 Mo de ram</a> (hors données stockées). le surcoût est donc minime, voire négligeable.</p>
<h2 id="conclusion">Conclusion</h2>
<p>À partir du moment où plus d&#8217;un projet doit accéder à une base de données Redis, je ne vois que des avantages à disposer d&#8217;une instance de <code>redis-server</code> pour chaque projet.</p>
<br /> Tagged: <a href='http://jeremy.wordpress.com/tag/redis/'>redis</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jeremy.wordpress.com/391/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jeremy.wordpress.com/391/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=391&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jeremy.wordpress.com/2012/04/25/redis-et-la-separation-des-donnees-entre-les-projets/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7d1caf9df777b3b2cf474ff743494335?s=96&#38;d=&#38;r=PG" medium="image">
			<media:title type="html">jeremy</media:title>
		</media:content>
	</item>
		<item>
		<title>Tutorat technique : tiens, c&#8217;est cadeau !</title>
		<link>http://jeremy.wordpress.com/2011/10/28/tutorat-technique-tiens-c-est-cadeau/</link>
		<comments>http://jeremy.wordpress.com/2011/10/28/tutorat-technique-tiens-c-est-cadeau/#comments</comments>
		<pubDate>Fri, 28 Oct 2011 08:57:15 +0000</pubDate>
		<dc:creator>Jérémy Lecour</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[laboate]]></category>
		<category><![CDATA[Personnel]]></category>
		<category><![CDATA[PLUG]]></category>

		<guid isPermaLink="false">http://jeremy.wordpress.com/?p=362</guid>
		<description><![CDATA[Je fais partie de ceux qui croient que lorsqu&#8217;on débute ou qu&#8217;on cherche à se perfectionner dans une pratique, être accompagné d&#8217;un &#34;mentor&#34; (ou tuteur, si vous préférez) est une grande aide. J&#8217;ai pu en bénéficier quelques fois à mes &#8230; <a href="http://jeremy.wordpress.com/2011/10/28/tutorat-technique-tiens-c-est-cadeau/">Lire la suite <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=362&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Je fais partie de ceux qui croient que lorsqu&rsquo;on débute ou qu&rsquo;on cherche à se perfectionner dans une pratique, être accompagné d&rsquo;un &quot;mentor&quot; (ou tuteur, si vous préférez) est une grande aide.</p>
<p>J&rsquo;ai pu en bénéficier quelques fois à mes débuts (trop peu à mon goût, d&rsquo;ailleurs) et ça m&rsquo;a beaucoup servi.</p>
<p>C&rsquo;est pourquoi je voudrais consacrer un peu de mon temps, régulièrement (et gratuitement), pour accompagner des personnes qui souhaiterais avoir un œil extérieur sur leur code, leurs pratiques, leurs méthodes, leurs outils, …</p>
<p>Il ne s&rsquo;agit pas de formation au sens institutionnel du terme, mais plutôt d&rsquo;observation, de critique et de conseil, dégagé de tout troll (dans la mesure du plus possible).</p>
<p>Je propose donc de passer 30 minutes à 1h en tête-à-tête, lors de chaque réunion du PLUG, avec une personne pour une séance de pair-programming, ou de discussion technique sur un sujet, … Ça peut être sur mes technos de prédilection, mais aussi sur n&rsquo;importe quel langage, framework, … ou sur des méthodes de travail car il ne s&rsquo;agit pas forcément de décortiquer le détail de chaque ligne, mais pourquoi pas d&rsquo;avoir un regard critique d&rsquo;ensemble, …</p>
<p>Faites moi signe (en commentaire, par e-mail, via <a title="jlecour : Jérémy Lecour sur Twitter" href="http://twitter.com/jlecour">Twitter</a>, …) si vous êtes intéressé. On peut faire une tentative dès la prochaine <a href="http://plugfr.org/r/188/">réunion du PLUG, le 4 novembre</a>. En cas de demandes multiples, je me réserve la liberté de choisir le sujet avec lequel je me sentirai le plus à l&rsquo;aise ou le plus intéressé.</p>
<p><strong>Mise à jour (21/11/2011)</strong> : La première tentative est concluante (pour moi au moins), donc je propose de recommencer dès la <a href="http://plugfr.org/r/189">réunion du PLUG le 2 décembre</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jeremy.wordpress.com/362/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jeremy.wordpress.com/362/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=362&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jeremy.wordpress.com/2011/10/28/tutorat-technique-tiens-c-est-cadeau/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7d1caf9df777b3b2cf474ff743494335?s=96&#38;d=&#38;r=PG" medium="image">
			<media:title type="html">jeremy</media:title>
		</media:content>
	</item>
		<item>
		<title>Un proxy qui annule l&#8217;authentification, pourquoi pas ?</title>
		<link>http://jeremy.wordpress.com/2011/01/21/un-proxy-qui-annule-authentification-pourquoi-pas/</link>
		<comments>http://jeremy.wordpress.com/2011/01/21/un-proxy-qui-annule-authentification-pourquoi-pas/#comments</comments>
		<pubDate>Fri, 21 Jan 2011 08:09:51 +0000</pubDate>
		<dc:creator>Jérémy Lecour</dc:creator>
				<category><![CDATA[Autrement]]></category>
		<category><![CDATA[Informatique]]></category>
		<category><![CDATA[PLUG]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[hotelhotel]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[s3]]></category>

		<guid isPermaLink="false">http://jeremy.wordpress.com/?p=327</guid>
		<description><![CDATA[Le contexte Voilà une idée bien saugrenue, je vous l&#8217;accorde. Pour comprendre, voyons un peu le contexte. Nous avons développé une application iPhone pour HotelHotel (le site sur lequel je travaille). Elle fonctionne en interrogeant notre API interne pour effectuer &#8230; <a href="http://jeremy.wordpress.com/2011/01/21/un-proxy-qui-annule-authentification-pourquoi-pas/">Lire la suite <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=327&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<h3>Le contexte</h3>
<p>Voilà une idée bien saugrenue, je vous l&rsquo;accorde. Pour comprendre, voyons un peu le contexte.</p>
<p>Nous avons développé une application iPhone pour <a href="http://www.hotelhotel.com/">HotelHotel</a> (le site sur lequel je travaille). Elle fonctionne en interrogeant notre API interne pour effectuer des recherches d&rsquo;hôtels. L&rsquo;API interroge nos partenaires compare les prix et compose une liste de résultats renvoyée à l&rsquo;application iPhone.</p>
<p>Pour les hôtels, nous disposons de plusieurs photos, qui aident à se faire un avis sur les hôtels proposés. Ces photos sont gérées par nous mêmes, nous indiquons juste leur URL à l&rsquo;application distante.</p>
<p>Jusqu&rsquo;à ces derniers jours, nous stockions ces photos sur notre propre serveur, mais pour différentes raisons, nous les avons déportées vers le service <a href="http://aws.amazon.com/fr/s3/">Amazon S3</a>. Il y a plein d&rsquo;avantages à utiliser ce service : haute disponibilité des contenus, bande passante très importante, pas de soucis de croissance de l&rsquo;espace utilisé, … pour un coût très raisonnable.</p>
<p>Nous avons donc modifié les différentes parties de notre système pour que les fichiers soient placés sur Amazon S3 et les URL renvoyées aux navigateurs, application iPhone, … soient celle sur Amazon S3 et plus sur notre serveur.</p>
<h3>Le problème</h3>
<p>Jusqu&rsquo;ici tout va bien, ou presque. Nos différents sites web (public, admin, …) fonctionnent bien, en lecture comme en écriture. Pa contre, l&rsquo;<strong>appli iPhone plante</strong> et quitte dès qu&rsquo;on veux <strong>charger une photo</strong>.</p>
<p>Après une séance de debuggage un peu déconcertante, on fini par trouver la source du problème. Pour bien comprendre, je rembobine un peu.</p>
<p>Pendant la phase de développement de l&rsquo;appli iPhone, nous utilisions une version privée de l&rsquo;API, sur un sous-domaine spécial, protégé par une <a href="http://fr.wikipedia.org/wiki/HTTP_Authentification">authentification HTTP Basic</a>. Juste avant la publication sur l&rsquo;<a href="http://www.apple.com/fr/iphone/apps-for-iphone/">AppStore</a>, nous avons changé le réglage pour pointer sur l&rsquo;API de &quot;production&quot;, mais nous avons oublié d&rsquo;enlever les en-têtes d&rsquo;authentification.<br />
On ne s&rsquo;en est pas rendu compte car le serveur de production les ignorait. Il n&rsquo;en attendait pas donc peu importe, il laissait tout passer.</p>
<p>Maintenant que les URL des images sont chez Amazon S3, et plus chez nous, ce sont leurs serveurs qui reçoivent les informations d&rsquo;authentification. Manque de bol, leur serveur HTTP n&rsquo;aime pas du tout les authentification de type HTTP Basic et il renvoi systématiquement une erreur <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">400 (Bad Request)</a>. Le contenu de la réponse est quant à lui une  portion XML indiquant plus d&rsquo;infos sur la requête, et c&rsquo;est probablement ça qui fait planter l&rsquo;appli. La <a href="http://allseeing-i.com/ASIHTTPRequest/">librairie</a> utilisée n&rsquo;arrive probablement pas à gérer un contenu XML au lieu d&rsquo;un contenu image.</p>
<p>Corriger l&rsquo;appli iPhone pour supprimer l&rsquo;authentification est très simple, mais il faut ensuite soumettre une nouvelle version à Apple (plusieurs jours de délai pour la valider) puis attendre que l&rsquo;extrême majorité de nos utilisateurs mettent à jour l&rsquo;appli, … Ce délai n&rsquo;était pas envisageable.</p>
<h3>La solution</h3>
<p>Il m&rsquo;est donc venue l&rsquo;idée bizarre de mettre en place un moyen d&rsquo;intercepter les URL demandées par l&rsquo;iPhone, de les nettoyer des en-têtes d&rsquo;authentification et de les transmettre à Amazon S3.</p>
<p>La mise en œuvre a été simple et rapide (grâce à l&rsquo;aide de <a href="http://gcolpart.evolix.net/">Grégory Colpart</a> de <a href="http://evolix.fr">Evolix</a>). Nous avons créé un VirtualHost Apache sur un sous-domaine, dans lequel nous avons paramétré un <a href="http://httpd.apache.org/docs/2.0/mod/mod_proxy_http.html">reverse proxy</a>. Toutes les requêtes envoyées à ce sous-domaines sont transmises de manière transparent à Amazon S3, et la directive <a href="http://httpd.apache.org/docs/2.2/mod/mod_headers.html#requestheader">RequestHeader</a> supprime les en-têtes d&rsquo;authentification.</p>
<p>Voilà la config du VirtualHost :</p>
<pre><code>    &lt;VirtualHost *:80&gt;
      ServerAdmin webmaster@example.com
      ServerName s3tmp.example.com

      ProxyRequests Off
      &lt;Proxy *&gt;
        Order deny,allow
        Allow from all
      &lt;/Proxy&gt;  

      ProxyPass / http://s3.example.com/
      ProxyPassReverse / http://s3.example.com/

      RequestHeader unset authorization
    &lt;/VirtualHost&gt;
</code></pre>
<p>NB : &quot;s3tmp.example.com&quot; est le sous-domaine du proxy, &quot;s3.example.com&quot; est un alias vers Amazon S3</p>
<br /> Tagged: <a href='http://jeremy.wordpress.com/tag/amazon/'>amazon</a>, <a href='http://jeremy.wordpress.com/tag/apache/'>apache</a>, <a href='http://jeremy.wordpress.com/tag/hotelhotel/'>hotelhotel</a>, <a href='http://jeremy.wordpress.com/tag/iphone/'>iphone</a>, <a href='http://jeremy.wordpress.com/tag/proxy/'>proxy</a>, <a href='http://jeremy.wordpress.com/tag/s3/'>s3</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jeremy.wordpress.com/327/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jeremy.wordpress.com/327/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=327&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jeremy.wordpress.com/2011/01/21/un-proxy-qui-annule-authentification-pourquoi-pas/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7d1caf9df777b3b2cf474ff743494335?s=96&#38;d=&#38;r=PG" medium="image">
			<media:title type="html">jeremy</media:title>
		</media:content>
	</item>
		<item>
		<title>grep, cut, awk et compagnie</title>
		<link>http://jeremy.wordpress.com/2011/01/06/grep-cut-awk-et-compagnie/</link>
		<comments>http://jeremy.wordpress.com/2011/01/06/grep-cut-awk-et-compagnie/#comments</comments>
		<pubDate>Thu, 06 Jan 2011 10:58:53 +0000</pubDate>
		<dc:creator>Jérémy Lecour</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[PLUG]]></category>
		<category><![CDATA[cli]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://jeremy.wordpress.com/?p=321</guid>
		<description><![CDATA[C&#8217;est vraiment puissant et agréable d&#8217;utiliser des systèmes Linux/Unix. Voilà un nouvel exemple que je veux partager. Contexte Je souhaite quantifier le volume d&#8217;images transférées depuis un de mes serveurs. Le meilleur endroit pour trouver cette info me semble être &#8230; <a href="http://jeremy.wordpress.com/2011/01/06/grep-cut-awk-et-compagnie/">Lire la suite <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=321&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>C&rsquo;est vraiment puissant et agréable d&rsquo;utiliser des systèmes Linux/Unix. Voilà un nouvel exemple que je veux partager.</p>
<h3>Contexte</h3>
<p>Je souhaite quantifier le volume d&rsquo;images transférées depuis un de mes serveurs. Le meilleur endroit pour trouver cette info me semble être les fichiers de logs d&rsquo;Apache (ou autre serveur web) puisqu&rsquo;ils indiquent l&rsquo;URL demandée, le code HTTP et la taille du fichier transmis.</p>
<p>Une fois isolés les logs que je souhaite analyser, il ne me restait plus qu&rsquo;à extraire les bons chiffres et en faire une somme.</p>
<h3>Solution</h3>
<p><code>grep '/system' * | grep -o -E '\b200 [0-9]+\b' | cut -f 2 -d ' ' | awk '{sum+=$0} END{print sum/1024/1024}'</code><br />
Je vous décortique chaque étape du processus, séparées par le &quot;pipe&quot; (tuyau) qui sert à transmettre le résultat d&rsquo;une commande à la suivante.</p>
<p><strong>grep &lsquo;/system&rsquo; *</strong></p>
<p><tt>grep</tt> permet de lire le contenu d&rsquo;un fichier ou d&rsquo;un flux et d&rsquo;en extraire des parties, selon des règles et filtres. Je lui demande donc de lire tous les fichiers logs (le * à la fin), à la recherche de &quot;/system&quot; (la base des URLs qui m&rsquo;intéressent).</p>
<p>J&rsquo;obtiens donc toutes les lignes de log où une URL qui contient &quot;/system&quot; a été demandée.</p>
<p>Exemple :</p>
<p><code>178.48.252.123 - - [12/Dec/2010:07:12:11 +0100] "GET /system/images/missing-sq128.jpg HTTP/1.1" 200 2237 "http://www.hotelhotel.com/stylesheets/hh.css?1291888120" "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12"</code></p>
<p><strong>grep -o -E &lsquo;\b200 [0-9]+\b&rsquo;</strong></p>
<p>Les lignes sont analysées une nouvelle fois avec <tt>grep</tt> à la recherche d&rsquo;une expression régulière qui permettra d&rsquo;isoler les requêtes soldées par un code HTTP 200, indiquant que l&rsquo;image a été effectivement téléchargée.</p>
<p>On utilise l&rsquo;option <tt>-E</tt> pour indiquer qu&rsquo;on veut les expressions régulières &quot;étendues&quot;. L&rsquo;option <tt>-o</tt> indique qu&rsquo;on ne veut renvoyer que ce qui a été capturé par l&rsquo;expression, et pas tout la ligne.</p>
<p>L&rsquo;expression indique qu&rsquo;on souhaite capturer ce qui commence par &quot;200&quot;, précédé d&rsquo;une rupture de mot (donc un espace, une ponctuation, …), puis un espace, une suite de chiffres, et une rupture de mot.</p>
<p>Exemple :<br />
<code>200 2237</code></p>
<p><strong>cut -f 2 -d &lsquo; &lsquo;</strong></p>
<p>cut permet de découper la chaîne de caractère et de renvoyer seulement certaines portions de cette chaîne.</p>
<p>L&rsquo;option <tt>-d</tt> on indique qu&rsquo;on veut découper selon les espaces. L&rsquo;option <tt>-f</tt> indique qu&rsquo;on veut renvoyer le 2ème segment (la taille de l&rsquo;image)</p>
<p>Exemple :<br />
<code>2237</code></p>
<p>À ce stade, on obtient une série de ligne qui contiennent les tailles des images téléchargées, il reste à en faire la somme</p>
<p><strong>awk &lsquo;{sum+=$0} END{print sum/1024/1024}&rsquo;</strong></p>
<p><tt>awk</tt> est un outil aussi génial que les autres utilisés ici, mais je le connais très mal. C&rsquo;est <a href="http://twitter.com/colinux">Colin</a> qui m&rsquo;a proposé cette dernière commande.</p>
<p>On demande donc à awk de faire la somme des valeurs trouvées à chaque ligne, de renvoyer cette somme, préalablement convertie en mega-octets (dans les logs Apache, ce sont des octets)</p>
<h3>Conclusion</h3>
<p>J&rsquo;ai donc pu faire des opérations pas trop complexes, mais pas non plus triviales, en une seule ligne et avec un résultat immédiat.</p>
<p>Encore fois, ça prouve que bien connaître ses outils permet de travailler efficacement.</p>
<p>Inutile de dire que j&rsquo;ai passé plus de temps à écrire ce petit article que pour construire cet enchaînement de commande, avec tous les essais/erreurs.</p>
<br /> Tagged: <a href='http://jeremy.wordpress.com/tag/cli/'>cli</a>, <a href='http://jeremy.wordpress.com/tag/linux/'>linux</a>, <a href='http://jeremy.wordpress.com/tag/unix/'>unix</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jeremy.wordpress.com/321/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jeremy.wordpress.com/321/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=321&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jeremy.wordpress.com/2011/01/06/grep-cut-awk-et-compagnie/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7d1caf9df777b3b2cf474ff743494335?s=96&#38;d=&#38;r=PG" medium="image">
			<media:title type="html">jeremy</media:title>
		</media:content>
	</item>
		<item>
		<title>Advice on using Ruby, RVM, Passenger, Rails, Bundler, … in development</title>
		<link>http://jeremy.wordpress.com/2010/08/19/ruby-rvm-passenger-rails-bundler-in-development/</link>
		<comments>http://jeremy.wordpress.com/2010/08/19/ruby-rvm-passenger-rails-bundler-in-development/#comments</comments>
		<pubDate>Thu, 19 Aug 2010 12:29:30 +0000</pubDate>
		<dc:creator>Jérémy Lecour</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[PLUG]]></category>
		<category><![CDATA[bundler]]></category>
		<category><![CDATA[mac os x]]></category>
		<category><![CDATA[passenger]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rvm]]></category>

		<guid isPermaLink="false">http://jeremy.wordpress.com/?p=273</guid>
		<description><![CDATA[A description of those "new tools" — RVM, Bundler and Passenger — and some advice on how to efficiently use them (beyond the roughness of their beta versions) in a development environment for Ruby and Rails. <a href="http://jeremy.wordpress.com/2010/08/19/ruby-rvm-passenger-rails-bundler-in-development/">Lire la suite <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=273&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>This article is the english version of “<a href="http://jeremy.wordpress.com/2010/08/13/ruby-rvm-passenger-rails-bundler-en-developpement/">Conseils pour utiliser Ruby, RVM, Passenger, Rails, Bundler, … en développement</a>”, originally written in French.<br />
If you have a better translation, I’d be happy to use it (full or parts) and credit you.</p>
<p>Last updated on March 3rd, 2011 : Rails 3 and Bundler are stable, versions of Passenger and REE are up-to-date.</p>
<h2 id="introduction_why_this_advice">Introduction : Why this advice</h2>
<p>The dev team I’m working in is composed of 3 people who use Ruby.<br />
Besides me, who’s is spending the most part of my time on Ruby and became “the one who knows” about this stuff, my co-workers don’t use Ruby the whole day, and use some others languages/frameworks (mostly Objective-C/iPhone and PHP/Symfony).</p>
<p>I’ve chosen to use some quite “bleeding edge” technologies for some reasons (I hope good ones) about performance, features, comfort, … but their beta nature is not very easy to deal with on a daily basis.<br />
It’s especially the case when there are some bugs, frequent changes in APIs, (temporary) incompatibilities, … and when you don’t want to learn and understand every detail at every change. Sometimes, you just need it to work to “get things done”.</p>
<p>I’ll introduce briefly those tools and how they work together with the minimum effort and pain and how to get the most of them.</p>
<p>I emphasize the fact that I’m describing here a <strong>development context</strong>. I’ve not yet used RVM in production, even if I know that it seems to work really well.</p>
<h2 id="the_not_so_usual_suspects">The (not so) usual suspects</h2>
<h3 id="ruby">Ruby</h3>
<p>“Wait, What ? Ruby is not stable yet ?”</p>
<p>Of course it is, but it’s also in a transition from 1.8 to 1.9 (<a href="http://www.ruby-lang.org/en/news/2010/08/18/ruby-1-9-2-is-released/">1.9.2 released a few months ago</a>). And there are many implementations (JRuby, Rubinius, …). It is very useful to be able to test your code in those different implementations, with RVM.</p>
<h3 id="rvm_ruby_version_manager">RVM &#8211; <a href="http://rvm.beginrescueend.com/">Ruby Version Manager</a></h3>
<p>The main idea behind <a href="http://rvm.beginrescueend.com/">RVM</a> is to have several different rubies on the same system, in a separate environment from the default ruby installed by the OS vendor, and being able to switch very easily between them.</p>
<p>For each Ruby, it allows to have different groups of gems (Gemsets) to avoid version conflicts between projects.</p>
<p>RVM is rich and powerful, but it introduces some concepts and tools that are not so simple to use in the beginning.<br />
If you’re not completely in phase with it, you can easily use the wrong Ruby and/or Gemset and quickly make quite a mess.</p>
<p>Happily, <a href="http://rvm.beginrescueend.com/">the documentation</a> is really great and quite up-to-date, and the dev team (<a href="http://twitter.com/wayneeseguin">@wayneeseguin</a> and his mentee <a href="http://twitter.com/sutto">@Sutto</a>) is awesome and always available on <a href="irc://irc.freenode.net/#rvm">IRC</a>.</p>
<h3 id="ruby_on_rails"><a href="http://rubyonrails.org/">Ruby on Rails</a></h3>
<p>I won’t describe <a href="http://rubyonrails.org/">Rails</a> in details, it’s a well known web development framework written in Ruby.</p>
<p>Since version 3, some parts have stopped being compatible with the previous stable version (2.3), mostly about the “rails” command and the scripts installed in applications. It’ become difficult to use Rails 2 and Rails 3 on the same computer without RVM.</p>
<p>Rails 3 also brings a brand new dependency management tool called Bundler, as a required gem.</p>
<h3 id="bundler"><a href="http://gembundler.com/">Bundler</a></h3>
<p><a href="http://gembundler.com/">Bundler</a> is a gem, written in Ruby whose purpose is to manage dependencies in a Ruby project, for example a Rails application.<br />
Much better than the “old” way when dealing with the dependency tree, it is especially excellent to quickly install all the gems required by a project in a restricted area, without interfering with others projects and vice versa.</p>
<p>Its stable version is 1.0 (1.0.10 to be accurate).</p>
<h3 id="phusion_passenger"><a href="http://modrails.com/">Phusion Passenger</a></h3>
<p><a href="http://modrails.com/">Phusion Passenger</a> connects Rack or Rails apps with Apache (or Nginx), allowing to host this kind of Ruby apps almost as easily as PHP scripts/apps.</p>
<p>It is now a stable piece of software, but using it with RVM and Bundler is not always obvious, especially if you want to use a different Gemset (and the gems inside it) for each hosted application.</p>
<h2 id="issues_we_had">Issues we had</h2>
<p>Those past few months, we mostly had issues with following properly versions changes and dealing with incompatibilities. Although I managed to keep the pace, my co-workers had better things to do than spending hours each week to make all this stuff work. Some changes that I was committing in our repositories were leading to non-working projects on their side or at least some headaches for them. Some hair were pulled, and occasionally, all these beautiful tools were called with improper names ;-)</p>
<h2 id="recommendations">Recommendations</h2>
<p>I’m going to describe the setup from a developer point of view (no production right now), with Mac OS X. It should probably be quite the same with Linux, even if some tools may not come pre-installed, or with different versions, … For Windows, it’s a whole different thing. I have no viable information about what is working or not and this part of the universe is quite hostile with web development (especially Ruby).</p>
<p>Apple has been shipping Mac OS X with Ruby since Leopard (at least). This pre-installed version is not useful here, but it’s good to know that it exists, at least to differentiate from other rubies installed with RVM. Right now, on Mac OS X 10.6.4, Ruby 1.8.7-p174 is installed.</p>
<p>If you start from a state where you’ve never done anything regarding Ruby, gems, … I advise not to instal any gem at all. Everything will be dealt with RVM.</p>
<h3 id="install_rvm">Install RVM</h3>
<p>The installation process for RVM is quite simple et <a href="http://rvm.beginrescueend.com/rvm/install/">well documented</a>. You’d rather read it there than copy/paste from here.</p>
<p>Once RVM is installed, you can install other “rubies”. I suggest using Ruby Enterprise Edition instead of a regular 1.8.7 :</p>
<pre><code>$ rvm install ree
</code></pre>
<p>I also suggest to make it the <a href="http://rvm.beginrescueend.com/rubies/default/">default</a> RVM Ruby and the preferred on for <a href="http://rvm.beginrescueend.com/integration/passenger/">Passenger</a>.</p>
<pre><code>$ rvm use ree --default --passenger
</code></pre>
<p>From now on, every new shell will use this version of Ruby and a wrapper script will allow Passenger to use it.</p>
<p>To update RVM itself you just have to</p>
<pre><code>$ rvm get latest
</code></pre>
<p>If you want to use the latest from the Git repository instead of the latest release :</p>
<pre><code>$ rvm get head
</code></pre>
<h3 id="how_to_use_rvm_gemsets">How to use RVM Gemsets</h3>
<h4 id="the_gemset_concept">The Gemset concept</h4>
<p>As a reminder, a <a href="http://rvm.beginrescueend.com/gemsets/basics/">Gemset</a> is a hermetic environment, dedicated to the installation and use of gems.<br />
Each Ruby installed with RVM has at least 2 Gemsets : <em>default</em> (unnamed in fact), and <em>global</em>. By default, we are in the unnamed Gemset. The <em>global</em> Gemset makes every gem installed in it available for all other Gemsets of the current Ruby. Then you can create as many Gemsets as you like, for example 1 for each development project.</p>
<p>Here is an attempt to represent this visually :</p>
<pre><code>/--------------------------|------------------|------------------\
|           Ruby EE        |     Ruby 1.9.2   |    other Ruby    |
|--------------------------|------------------|------------------|
|           @global        |      @global     |     @global      |
|--------------------------|------------------|------------------|
| @default | @app1 | @appX | @default | @appX | @default | @appX |
\--------------------------|------------------|------------------/
</code></pre>
<h4 id="a_gemset_by_project">A Gemset by project</h4>
<p>For every web sites/apps I’m working on, I create a Gemset. The gems the projects can “see” are isolated from others, it’s like a specific environment for the project. For those managed with Bundler, the interest is slightly smaller, but for others (Rails 2, other frameworks or no framework at all) the interest is considerable.</p>
<p>One of RVM’s features is to recognize the presence of a <a href="http://rvm.beginrescueend.com/workflow/rvmrc/"><em>.rvmrc</em> file</a> in a directory when you enter it (with <code>cd</code> for example). If this file refers to a Ruby and/or a Gemset, RVM makes the switch automatically. Each one of my projects has its <em>.rvmrc</em> file containing at least this line :</p>
<pre><code>rvm --create use default@projectX &gt; /dev/null
</code></pre>
<p>In short, it will use the  default Ruby (defined earlier, but changeable any time) and the Gemset “projectX” if it exists. If not, it is created right away. Redirecting to /dev/null hides the RVM’s output, otherwise it’s annoying to see it each time you enter such a directory.</p>
<p>Since <a href="http://wayneeseguin.beginrescueend.com/2010/08/22/ruby-environment-version-manager-rvm-1-0-0/">version 1.0</a> (released on august 22nd, exactly 1 year after the <a href="http://github.com/wayneeseguin/rvm/commit/038781c9bbe885f25178145e7dc76f60ba135234">first commit</a>), each time RVM will find a new <em>.rvmrc</em> file, it will ask if you trust it or not. It&rsquo;s a security feature.</p>
<h4 id="gems_in_the_global_gemset">Gems in the <em>global</em> Gemset</h4>
<p>I always install some gems in the <em>global</em> Gemset to have them available, whatever project Gemset I’m in (or if I’m outside any specific project) including the <em>default</em> one.</p>
<ul>
<li>passenger</li>
<li>capistrano + capistrano-ext</li>
<li>bundler</li>
<li>git_remote_branch</li>
<li>awesome_print</li>
<li>g</li>
<li>wirble</li>
</ul>
<p>Those gems will be available in any Gemset inside the  Ruby associated with this <em>global</em> Gemset.</p>
<h3 id="make_rvm_and_phusion_passenger_a_happy_couple">Make RVM and Phusion Passenger a happy couple</h3>
<p>Usually, Passenger uses a defined ruby binary and the “normal” environment variables to look for gems required by hosted applications.</p>
<p>When you install Passenger, you have to configure the webserver (here Apache, but there is a similar configuration for Nginx) with (at least) those 3 directives :</p>
<pre class="brush: plain; title: ; notranslate">
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-3.0.4/ext/apache2/mod_passenger.so
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-3.0.4
PassengerRuby /usr/bin/ruby1.8
</pre>
<p>The key point is to tell Passenger to use the right Ruby, where the modules are, … Here is my setup (adapted from RVM documentation) :</p>
<pre class="brush: plain; title: ; notranslate">
LoadModule passenger_module /Users/jlecour/.rvm/gems/ree-1.8.7-2011.03@global/gems/passenger-3.0.4/ext/apache2/mod_passenger.so
PassengerRoot /Users/jlecour/.rvm/gems/ree-1.8.7-2011.03@global/gems/passenger-3.0.4
PassengerRuby /Users/jlecour/.rvm/wrappers/ree-1.8.7-2011.03/ruby
</pre>
<p>With this, Passenger will use the module from the <em>passenger</em> gem, installed in the <em>global</em> Gemset of the default Ruby and the defined wrapper as a Ruby binary.</p>
<p>OK, but how Passenger will be able to use the right Gemset depending on the application ?</p>
<p>With Passenger &gt;= 2.2.14 and RVM &gt;= 0.1.42 it is possible to use (in Ruby) an API for RVM and adjust the environment variables for the hosted application. It will then know where to look for gems. It’s explained in details by Darcy Laycock (Sutto) in his blog post <a href="http://blog.ninjahideout.com/posts/the-path-to-better-rvm-and-passenger-integration">The Path to Better RVM &amp; Passenger Integration</a>.</p>
<p>Currently, Passenger has a limitation to use only 1 Ruby interpreter. Check out <a href="http://rvm.beginrescueend.com/integration/passenger/">the documentation</a> for more info.</p>
<p>For a Rails 3 application, with Bundler, here is my <em>config/setup_load_paths.rb</em> file :</p>
<pre class="brush: ruby; title: ; notranslate">
if ENV['MY_RUBY_HOME'] &amp;&amp; ENV['MY_RUBY_HOME'].include?('rvm')
  begin
    rvm_path     = File.dirname(File.dirname(ENV['MY_RUBY_HOME']))
    rvm_lib_path = File.join(rvm_path, 'lib')
    $LOAD_PATH.unshift rvm_lib_path
    require 'rvm'
    RVM.use_from_path! File.dirname(File.dirname(__FILE__))
  rescue LoadError
    # RVM is unavailable at this point.
    raise &quot;RVM ruby lib is currently unavailable.&quot;
  end
end

ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__))
require 'bundler/setup'
</pre>
<p>For a Rails 2 application without Bundler, you just have to delete the last 2 lines.</p>
<p>With this, I can host several Rails 2 and Rails 3 application with Passenger, on the same webserver, without any version conflicts.</p>
<h3 id="use_bundler_for_dependencies_management">Use Bundler for dependencies management</h3>
<p>I summarize once again ; Bundler allow to specify which gems (and their versions) required by a project, to install them (with dependency management) and load them exclusively in the project. The result is : easy installation, confidence in the used versions and no conflicts.</p>
<p>If you’ve been using Bundler &lt;= 0.9.6, I strongly recommend to uninstall the previous versions, (unless you explicitly need them), install the pre-release version, then make Bundler re-install the required gems.</p>
<pre><code>$ gem uninstall bundler
$ gem install bundler
$ bundle install
</code></pre>
<p>When you <code>bundle install</code>, the <em>Gemfile</em> is processed to build the dependency tree and a <em>Gemfile.lock</em> is created. It is used to know exactly which version of what gems has to be installed.<br />
As long as this file is not modified, the project will only see those gems. It guaranties that the development environment (including other developers) will use the same gems as those for tests, staging, production, …</p>
<p>A developer who wants to update a gem or install a new one has to modify the <em>Gemfile</em> file accordingly then do a <code>bundle install</code> from the root directory of the project (where the <em>Gemfile</em> file is). Then he can commit the changes in the repository for the other developers.</p>
<p>A developer who doesn’t want to manage gem version changes just has to let the <em>Gemfile</em> and <em>Gemfile.lock</em> files like they are. To verify he has every gem the project needs (in the right version), after an update of the codebase, or if the application doesn’t work, he just has to do a <code>bundle install</code> from the root directory of the project. This way, he’s sure to be up-to-date.</p>
<p>Using RVM make all this even easier, faster and reliable. In <em>normal</em> mode, Bundler installs the gems system wide, with all the other gems, but since what he sees as the whole system is only a Gemset, everyone is stays in its yard.<br />
In <em>deployment</em> mode, it installs gems in a cache directory, inside the application. It looks like a Gemset. It is possible to optimize this step with Capistrano</p>
<h3 id="bundler_and_capistrano_for_an_easy_depoyment">Bundler and Capistrano for an easy depoyment</h3>
<p>An application managed with Bundler doesn’t use the usual require methods to  load the gems. Bundler takes care of this when the application is initializing. To do this, the gems have to be accessible to Bundler on the application server. We have to check if everything is OK after each deployment and if possible share the gems between releases of the application to avoid unnecessary downloads and disk usage.</p>
<p>Since version 1.0.0.rc.5, Bundler has a <a href="http://github.com/carlhuda/bundler/blob/master/lib/bundler/capistrano.rb">Capistrano task</a> (in fact since rc.4 but it had some bugs). You just have to add the line <code>require 'bundler/capistrano'</code> in your deployment recipe (<em>deploy.rb</em>). You can tweak some parameters, but by default, the gems are going into <em>shared/bundle</em>.</p>
<h3 id="other_major_packages">Other major packages</h3>
<p>For the management of additional packages  that Apple does not provide, I usually suggest to use <a href="http://mxcl.github.com/homebrew/">Homebrew</a>. Contrary to MacPorts, it doesn’t install every library or package systematically. If it finds what it needs in the Apple provided libraries (like OpenSSL, …) it’s going to use them instead of downloading/compiling/installing them. It’s faster, more coherent and lighter.</p>
<p>Homebrew also install everything it needs with the user’s permissions, without <code>sudo</code>. It seems a little disturbing for a sysadmin, but in a development context, it makes a lot of sense.</p>
<p>I’ve used Homebrew to install major packages as <em>MySQL</em>, <em>Git</em>, <em>ImageMagick</em>, <em>MongoDB</em>, … and numerous small tools like <code>tree</code>, <code>wget</code>, <code>ack</code>, …</p>
<h2 id="credits">Credits</h2>
<p>First, I’d like to thank all the developers and contributors of those awesome tools.</p>
<p>A special thank you for <a href="http://twitter.com/wayneeseguin">Wayne E Seguin</a> and <a href="http://twitter.com/jmettraux">John Mettraux</a> for the meticulous typo hunting,  <a href="http://twitter.com/thibaut_barrere">Thibaut Barrère</a> and <a href="http://twitter.com/sgruhier">Sébastien Gruhier</a> for their support and additional tips.</p>
<br /> Tagged: <a href='http://jeremy.wordpress.com/tag/bundler/'>bundler</a>, <a href='http://jeremy.wordpress.com/tag/mac-os-x/'>mac os x</a>, <a href='http://jeremy.wordpress.com/tag/passenger/'>passenger</a>, <a href='http://jeremy.wordpress.com/tag/rails/'>rails</a>, <a href='http://jeremy.wordpress.com/tag/ruby/'>ruby</a>, <a href='http://jeremy.wordpress.com/tag/rvm/'>rvm</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jeremy.wordpress.com/273/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jeremy.wordpress.com/273/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=273&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jeremy.wordpress.com/2010/08/19/ruby-rvm-passenger-rails-bundler-in-development/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7d1caf9df777b3b2cf474ff743494335?s=96&#38;d=&#38;r=PG" medium="image">
			<media:title type="html">jeremy</media:title>
		</media:content>
	</item>
		<item>
		<title>Conseils pour utiliser Ruby, RVM, Passenger, Rails, Bundler, … en développement</title>
		<link>http://jeremy.wordpress.com/2010/08/13/ruby-rvm-passenger-rails-bundler-en-developpement/</link>
		<comments>http://jeremy.wordpress.com/2010/08/13/ruby-rvm-passenger-rails-bundler-en-developpement/#comments</comments>
		<pubDate>Fri, 13 Aug 2010 14:18:42 +0000</pubDate>
		<dc:creator>Jérémy Lecour</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[PLUG]]></category>
		<category><![CDATA[bundler]]></category>
		<category><![CDATA[mac os x]]></category>
		<category><![CDATA[passenger]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rvm]]></category>

		<guid isPermaLink="false">http://jeremy.wordpress.com/?p=262</guid>
		<description><![CDATA[Une descriptions de ces "nouveaux outils" que sont RVM, Bundler et Passenger ainsi que quelques conseils pour bien les harmoniser (et dépasser les difficultés liées aux versions bêta) dans son environnement de développement Ruby et Rails. <a href="http://jeremy.wordpress.com/2010/08/13/ruby-rvm-passenger-rails-bundler-en-developpement/">Lire la suite <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=262&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><a href="http://jeremy.wordpress.com/2010/08/19/ruby-rvm-passenger-rails-bundler-in-development/">Cet article existe en anglais</a>. Ma propre traduction n&#8217;est probablement pas la meilleure, donc si vous avez des améliorations à suggérer, je suis preneur.</p>
<p>Dernière mise à jour le 3 mars 2011 : Rails 3 et Bundler sont en version stable, et les versions de Passenger et REE sont actualisées.</p>
<h2 id="intro_pourquoi_ces_conseils">Intro : Pourquoi ces conseils</h2>
<p>L&#8217;équipe de dev dans laquelle je travaille est composée de 3 personnes qui bossent avec Ruby.<br />
À part moi qui ne fait presque que ça et qui suis de fait un peu le &#8220;référent&#8221; sur ces questions, mes 2 très chers collègues n&#8217;utilisent pas Ruby toute la journée et utilisent donc d&#8217;autres environnements de travail (Objective-C/iPhone et PHP/Symfony principalement).</p>
<p>J&#8217;ai choisi d&#8217;utiliser un certain nombre de technologies un peu &#8220;bleeding edge&#8221; pour des vraies (j&#8217;espère des bonnes) raisons de performance, de fonctionnalités, de confort, … mais leur nature &#8220;beta&#8221; ne les rend pas toujours faciles à comprendre et à manipuler, …<br />
C&#8217;est surtout le cas quand il y a des bugs, des changements fréquents de fonctionnement, des incompatibilités (temporaires), … et qu&#8217;on n&#8217;a pas envie (et c&#8217;est normal) de se prendre la tête à tout comprendre. Des fois il faut juste que ça marche.</p>
<p>Je vais donc vous présenter rapidement ces différents outils et comment les faire fonctionner ensemble avec le minimum de souffrance et le maximum d&#8217;intérêt.<br />
Je précise que je présente ici un usage de ces outils en <strong>environnement de développement</strong>. Je n&#8217;ai pas utilisé RVM en production, bien que ça soit tout à fait possible, et même conseillé.</p>
<h2 id="les_outils_du_boucher">Les outils du boucher</h2>
<h3 id="ruby">Ruby</h3>
<p>&#8220;Ah bon, Ruby n&#8217;est pas encore stable ?&#8221;</p>
<p>Si si, mais Ruby est dans une phase de transition entre la version 1.8 et la 1.9 (<a href="http://www.ruby-lang.org/en/news/2010/08/18/ruby-1-9-2-is-released/">la 1.9.2 est sortie il y a quelques mois</a>). Et puis il y a plusieurs implémentations (notamment JRuby et Rubinius). Il est donc intéressant de pouvoir facilement tester son code dans ces différentes implémentations, via RVM.</p>
<h3 id="rvm_ruby_version_manager">RVM &#8211; <a href="http://rvm.beginrescueend.com/">Ruby Version Manager</a></h3>
<p>Le principe de RVM est de permettre d&#8217;installer plusieurs versions de Ruby sur une même machine, dans un environnement hermétique à une éventuelle version installée sur l&#8217;OS et de pouvoir basculer de l&#8217;une à l&#8217;autre facilement.</p>
<p>Il permet aussi, pour chaque Ruby, d&#8217;avoir des ensembles de gems bien séparés (Gemset) pour éviter les conflits de versions entre différents projets.</p>
<p>L&#8217;outil est très riche et fonctionnellement très puissant, mais il introduit des concepts et des outils pas si simples que ça.<br />
Si on n&#8217;est pas complètement en phase avec, on a vite fait de se tromper de version de Ruby et/ou de Gemset.</p>
<p>Heureusement <a href="http://rvm.beginrescueend.com/">la doc</a> est très bien faite et l&#8217;équipe de dev (<a href="http://twitter.com/wayneeseguin">@wayneeseguin</a> et <a href="http://twitter.com/sutto">@Sutto</a>) est super disponible sur <a href="irc://irc.freenode.net/#rvm">IRC</a>.</p>
<h3 id="ruby_on_rails"><a href="http://rubyonrails.org/">Ruby on Rails</a></h3>
<p>Je ne présente pas plus en détail <a href="http://rubyonrails.org/">Ruby on Rails</a> : c&#8217;est un framework de développement d&#8217;applications web, écrit en Ruby.</p>
<p>Depuis sa version 3, il apporte énormément de nouveautés, mais aussi certaines incompatibilités par rapport à sa version stable précédente (2.3), surtout au niveau des commandes &#8220;rails&#8221; et scripts dans les applis. Il n&#8217;est donc pas simple du tout d&#8217;utiliser Rails 2 et Rails 3 sur une même machine sans utiliser RVM.</p>
<p>Cette version 3 apporte aussi un nouveau système de gestion de dépendances : Bundler, sous forme d&#8217;une gem requise.</p>
<h3 id="bundler"><a href="http://gembundler.com/">Bundler</a></h3>
<p><a href="http://gembundler.com/">Bundler</a> est une Gem écrite en Ruby, permettant de gérer les dépendances d&#8217;un projet écrit en Ruby, par exemple une application Rails.<br />
Beaucoup plus efficace que l&#8217;ancien procédé au niveau de la gestion de l&#8217;arbre des dépendances il est surtout excellent pour installer rapidement les gems nécessaires à un projet dans un espace limité à ce projet, sans que les éventuelles autres gems installées sur le système ne puisse le perturber.</p>
<p>Sa version stable actuelle est la 1.0 (1.0.10 exactement).</p>
<h3 id="phusion_passenger"><a href="http://modrails.com/">Phusion Passenger</a></h3>
<p><a href="http://modrails.com/">Phusion Passenger</a> sert à connecter des applis Rack ou Rails avec Apache (ou Nginx), permettant d&#8217;héberger ces applis presque aussi facilement que des applis/scripts en PHP.</p>
<p>C&#8217;est un composant logiciel maintenant bien stable, mais son usage en conjonction avec RVM et Bundler n&#8217;est pas toujours évident, surtout si on veut qu&#8217;il utilise un Gemset (et les gems qui sont dedans) différent pour chaque applis.</p>
<h2 id="les_difficults_rencontres">Les difficultés rencontrées</h2>
<p>Ces derniers mois, on a surtout rencontré des difficultés avec le suivi des versions et les incompatibilités que ça a révélé. Alors que j&#8217;arrivais à peut près à suivre le rythme des changements, … mes collègues avaient mieux à faire. Des modifs que je mettais en commun rendaient certaines fois les projets inutilisables pour les autres, ou en tous cas difficile à remettre en ordre. Ça débouchait sur des cheveux arrachés, des insultes aux outils :-), …</p>
<h2 id="recommandations">Recommandations</h2>
<p>Je vais décrire une situation de poste de développement (donc pas de production), sous Mac OS X. La situation sous Linux sera probablement très proche, à la différence près que les certains composants ne seront pas pré-installés. Pour Windows, c&#8217;est tout autre chose, mais je n&#8217;ai aucune info fiable sur ce qui marche ou pas dans cet univers assez hostile au développement web (Ruby en particulier).</p>
<p>Apple fourni Ruby en standard depuis Leopard (peut-être même avant). Cette version pré-installée ne nous sera pas utile, mais il est bien de savoir qu&#8217;elle existe, ne serait-ce que pour la différencier des autres qui seront installées via RVM. Actuellement, sous Mac OS X 10.6.4, c&#8217;est Ruby 1.8.7-p174 qui est installé.</p>
<p>Si on part d&#8217;un système &#8220;vierge&#8221; au niveau de l&#8217;utilisation de Ruby, je conseille de n&#8217;installer aucune gem particulière et de ne pas toucher à ce qui est présent. On va tout confier à RVM.</p>
<h3 id="installer_rvm">Installer RVM</h3>
<p>La procédure d&#8217;install de RVM est assez simple et <a href="http://rvm.beginrescueend.com/rvm/install/">bien documentée</a>. Suivez la, c&#8217;est plus sûr que si je la recopie ici.</p>
<p>Un fois cette install faite, vous pouvez commencer à installer d&#8217;autres &#8220;rubies&#8221;. Je conseille particulièrement l&#8217;utilisation de Ruby Enterprise Edition :</p>
<pre><code>$ rvm install ree
</code></pre>
<p>Je conseille aussi d&#8217;en faire la version <a href="http://rvm.beginrescueend.com/rubies/default/">par défaut</a>, et celle pour <a href="http://rvm.beginrescueend.com/integration/passenger/">Passenger</a>. </p>
<pre><code>$ rvm use ree --default --passenger
</code></pre>
<p>Dorénavant, tout nouveau shell utilisera cette version de Ruby et un script &#8220;wrapper&#8221; permettra à Passenger de l&#8217;utiliser.</p>
<p>Pour mettre à jour RVM, il suffit de faire :</p>
<pre><code>$ rvm get latest
</code></pre>
<p>Pour utiliser la dernière version Git de RVM plutôt que la dernière version publiée :</p>
<pre><code>$ rvm get head
</code></pre>
<h3 id="utilisation_des_gemsets_de_rvm">Utilisation des Gemsets de RVM</h3>
<h4 id="concept_des_gemsets">Concept des Gemsets</h4>
<p>Pour rappel, un <a href="http://rvm.beginrescueend.com/gemsets/basics/">Gemset</a> est un environnement hermétique dédié à l&#8217;installation et l&#8217;utilisation de gems.<br />
Chaque version de Ruby connue de RVM dispose d&#8217;au moins 2 Gemsets : <em>default</em> (sans nom, en fait), et <em>global</em>. Par défaut on est dans le Gemset sans nom. Le Gemset <em>global</em> permet de rendre disponibles les gems qui y sont installées dans tous les autres Gemsets de la version courante de Ruby.<br />
On peut ensuite créer autant de Gemsets que l&#8217;on souhaite, par exemple 1 pour chaque projet de dev.</p>
<p>Voilà une tentative de représentation visuelle :</p>
<pre><code>/--------------------------|------------------|------------------\
|           Ruby EE        |     Ruby 1.9.2   |    autre Ruby    |
|--------------------------|------------------|------------------|
|           @global        |      @global     |     @global      |
|--------------------------|------------------|------------------|
| @default | @app1 | @appX | @default | @appX | @default | @appX |
\--------------------------|------------------|------------------/
</code></pre>
<h4 id="un_gemset_par_projet">Un Gemset par projet</h4>
<p>Pour chacun des sites sur lesquels je travaille, je crée donc un Gemset. Ça permet d&#8217;isoler les gems qu&#8217;il a à disposition et ainsi de simuler un environnement spécifique à ce projet. Pour les projets qui utilisent Bundler l&#8217;intérêt est légèrement moindre, mais pour les autres (Rails 2, autres frameworks ou pas de framework) le bénéfice est immédiat.</p>
<p>Une des fonctionnalités de RVM est de reconnaître la présence d&#8217;un <a href="http://rvm.beginrescueend.com/workflow/rvmrc/">fichier <em>.rvmrc</em></a> dans un répertoire lorsqu&#8217;on s&#8217;y rend (avec <code>cd</code> par exemple). Si ce fichier de config indique qu&#8217;il faut choisir un Ruby et un Gemset, il bascule tout seul.<br />
Chacun de mes projets dispose donc d&#8217;un fichier <em>.rvmrc</em> contenant au moins cette ligne :</p>
<pre><code>rvm --create use default@projetX &gt; /dev/null
</code></pre>
<p>En résumé, il va utiliser la version par défaut de Ruby (définie plus haut, mais modifiable à tout instant) et le Gemset &#8220;projetX&#8221; s&#8217;il existe. S&#8217;il n&#8217;existe pas, il est créé automatiquement. Le renvoi sur /dev/null permet que cette opération ne génère aucune sortie, ce qui est le cas sinon et c&#8217;est vite casse-pieds lorsqu&#8217;on navigue beaucoup via le terminal.</p>
<p>Depuis la <a href="http://wayneeseguin.beginrescueend.com/2010/08/22/ruby-environment-version-manager-rvm-1-0-0/">version 1.0</a> (sortie le 22 août, 1 an exactement après le <a href="http://github.com/wayneeseguin/rvm/commit/038781c9bbe885f25178145e7dc76f60ba135234">premier commit</a>), RVM va demander confirmation la première fois qu&rsquo;il rencontre un fichier <em>.rvmrc</em> dans un répertoire. C&rsquo;est une précaution de sécurité.</p>
<h4 id="des_gems_dans_le_gemset_global">Des gems dans le Gemset <em>global</em></h4>
<p>J&#8217;installe un certains nombre de gems dans le Gemset global pour les avoir toujours sous la main, quelque soit le projet dans lequel je travail ou si je suis simplement dans un shell hors projet.</p>
<ul>
<li>passenger</li>
<li>capistrano + capistrano-ext</li>
<li>bundler</li>
<li>git_remote_branch</li>
<li>awesome_print</li>
<li>wirble</li>
<li>g</li>
</ul>
<p>Ces gems seront donc dispo pour tous les Gemsets de la version de Ruby associée au Gemset <em>global</em> en cours.</p>
<h3 id="couplage_harmonieux_de_rvm_et_phusion_passenger">Couplage harmonieux de RVM et Phusion Passenger</h3>
<p>Dans son fonctionnement normal, Passenger utilise une version définie de Ruby et les variables d&#8217;environnement &#8220;normales&#8221; pour savoir où trouver les gems, …</p>
<p>Lorsqu&#8217;on install Passenger, on doit indiquer au serveur web (ici c&#8217;est Apache mais il y a une variante pour Nginx) ces 3 directives :</p>
<pre class="brush: plain; title: ; notranslate">
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-3.0.4/ext/apache2/mod_passenger.so
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-3.0.4
PassengerRuby /usr/bin/ruby1.8
</pre>
<p>La clé est d&#8217;indiquer à Passenger la bonne version de Ruby et l&#8217;emplacement des modules, … Voilà ma propre config :</p>
<pre class="brush: plain; title: ; notranslate">
LoadModule passenger_module /Users/jlecour/.rvm/gems/ree-1.8.7-2011.03@global/gems/passenger-3.0.4/ext/apache2/mod_passenger.so
PassengerRoot /Users/jlecour/.rvm/gems/ree-1.8.7-2011.03@global/gems/passenger-3.0.4
PassengerRuby /Users/jlecour/.rvm/wrappers/ree-1.8.7-2011.03/ruby
</pre>
<p>En l&#8217;état, Passenger utilisera donc le module présent dans la gem installée dans le Gemset <em>global</em> et la version de Ruby définie par le wrapper <em>passenge_ruby</em>.</p>
<p>C&#8217;est bien, mais comment va-t-il utiliser le bon Gemset selon l&#8217;application ?</p>
<p>Avec un Passenger &gt;= 2.2.14 et RVM &gt;= 0.1.42 il est désormais possible d&#8217;utiliser (en Ruby) une API interne à RVM et forcer les variables d&#8217;environnement pour l&#8217;application lancée et qu&#8217;elle sache où chercher les gems dont elle a besoin. Le procédé est détaillé dans l&#8217;article <a href="http://blog.ninjahideout.com/posts/the-path-to-better-rvm-and-passenger-integration">The Path to Better RVM &amp; Passenger Integration</a>.<br />
En résumé, au chargement de l&#8217;application Ruby, on demande à RVM quelques sont les variables à utiliser.</p>
<p>Pour le moment, Passenger est limité à un seul interprêteur Ruby. Voir <a href="http://rvm.beginrescueend.com/integration/passenger/">la doc</a> pour plus d&#8217;info.</p>
<p>Pour une appli en Rails 3, avec Bundler, voilà mon fichier <em>config/setup_load_paths.rb</em> :</p>
<pre class="brush: ruby; title: ; notranslate">
if ENV['MY_RUBY_HOME'] &amp;amp;&amp;amp; ENV['MY_RUBY_HOME'].include?('rvm')
  begin
    rvm_path     = File.dirname(File.dirname(ENV['MY_RUBY_HOME']))
    rvm_lib_path = File.join(rvm_path, 'lib')
    $LOAD_PATH.unshift rvm_lib_path
    require 'rvm'
    RVM.use_from_path! File.dirname(File.dirname(__FILE__))
  rescue LoadError
    # RVM is unavailable at this point.
    raise &quot;RVM ruby lib is currently unavailable.&quot;
  end
end

ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__))
require 'bundler/setup'
</pre>
<p>Pour une application Rails, sans Bundler, il suffit de supprimer les 2 dernières lignes.</p>
<p>De cette manière, j&#8217;arrive à héberger avec Passenger des applis Rails 2, Rails 3 et Rack sur le même serveur web, sans conflit de version.</p>
<h3 id="utiliser_bundler_pour_la_gestion_des_dpendances">Utiliser Bundler pour la gestion des dépendances</h3>
<p>Je résume une fois de plus ; Bundler permet de spécifier les gems (et leur version) nécessaires à un projet, de les installer (avec prise en charge des dépendances) et de ne &#8220;proposer&#8221; au projet en question que ces gems là. Le résultat est donc : facilité d&#8217;installation, confiance dans les versions utilisées, absence de conflits.</p>
<p>Si vous avez utilisé une version de Bundler &lt;= 0.9.6, je ne peux que vous conseiller de désinstaller les version actuelles (sauf si vous en avez explicitement besoin), installer la version 1.0.rc puis recalculer les dépendances.</p>
<pre><code>$ gem uninstall bundler
$ gem install bundler
$ bundle install
</code></pre>
<p>La version 1.0 (même depuis sa première beta) a apporté de gros changement, dont certains sont incompatibles, mais elle simplifie la gestion des déploiements en production, …</p>
<p>Lorsque dans un terminal, à la racine d&#8217;un projet géré avec Bundler, on fait un <code>bundle install</code>, le fichier de config <em>Gemfile</em> est analysé pour déterminer l&#8217;arbre des dépendances et un fichier <em>Gemfile.lock</em> est créé. Il est ensuite utilisé pour connaître l&#8217;exacte version de chaque gem à installer/utiliser.<br />
Tant que ce fichier n&#8217;est pas modifié, le projet d&#8217;utilisera que ces gems là, ce qui garanti une cohérence entre l&#8217;environnement de développement (y compris d&#8217;un développeur à l&#8217;autre) et ceux de test, pre-production, production, … </p>
<p>Un développeur qui souhaite mettre à jour une gem ou en installer une nouvelle doit modifier le fichier <em>Gemfile</em> en conséquence, puis faire un <code>bundle install</code>. Il peut enfin versionner ces changements pour les rendre disponibles aux autres développeurs. </p>
<p>Un développeur qui ne veut pas gérer les changements de version de gems du projet en cours ne doit juste pas toucher aux fichiers <em>Gemfile</em> et <em>Gemfile.lock</em>. Pour s&#8217;assurer qu&#8217;il dispose en local des gems nécessaires à l&#8217;exécution de l&#8217;application ou bien si après une mise à jour du code il rencontre un &#8220;plantage&#8221; indiquant une erreur de gem, le 1er réflexe doit être de faire un <code>bundle install</code> depuis la racine du projet. Ainsi il s&#8217;assure d&#8217;être à jour au niveau des gems et de leur version.</p>
<p>L&#8217;utilisation de RVM rend ces processus encore plus faciles, rapides et fiables. En effet en mode <em>normal</em>, Bundler va installer au niveau système les gems nécessaires, mais comme le niveau système qu&#8217;il voit est en fait un Gemset, il ne pollue pas les autres projets.<br />
En mode <em>déploiement</em>, il installe les gems dans un dossier de cache au sein de l&#8217;application, ce qui revient à peut près au même qu&#8217;un Gemset. Il est possible d&#8217;optimiser cette phase avec Capistrano.</p>
<h3 id="bundler_et_capistrano_pour_un_dploiement_rapide_et_facile">Bundler et Capistrano pour un déploiement rapide et facile</h3>
<p>Une appli gérée avec Bundler n&#8217;utilise plus les mécanismes classiques de <code>require</code> pour charger ses gems, c&#8217;est Bundler qui s&#8217;en charge à l&#8217;initialisation de l&#8217;appli. Il faut donc que les gems soient installées et accessibles à Bundler sur le serveur d&#8217;application. Il faut donc vérifier que tout est OK après chaque déploiement, et si possible mutualiser les gems d&#8217;une fois sur l&#8217;autre pour éviter des téléchargements et une consommation inutiles.</p>
<p>Depuis la version 1.0.0.rc.5, Bundler dispose d&#8217;une <a href="http://github.com/carlhuda/bundler/blob/master/lib/bundler/capistrano.rb">tache pour Capistrano</a> (en réalité c&#8217;est depuis la rc.4 mais elle contenait des bugs). Il suffit d&#8217;ajouter <code>require 'bundler/capistrano'</code> dans sa recette de déploiement (<em>deploy.rb</em>). On peut éventuellement spécifier l&#8217;emplacement d&#8217;installation des gems, mais par défaut, c&#8217;est dans <em>shared/bundle</em>.</p>
<h3 id="autres_paquets_majeurs">Autres paquets majeurs</h3>
<p>Pour la gestion courante des paquets additionnels non fournis par Apple, je conseille d&#8217;une manière générale l&#8217;utilisation de <a href="http://mxcl.github.com/homebrew/">Homebrew</a>. Contrairement à MacPorts, il ne réinstalle pas toutes les dépendances systématiquement. S&#8217;il trouve son bonheur dans les paquets et librairies installés par Apple, il va les utiliser. Ça assure une plus grande cohérence, rapidité d&#8217;install et légèreté d&#8217;ensemble.</p>
<p>Homebrew installe aussi tout ce qui lui est nécessaire dans l&#8217;environnement utilisateur, sans nécessité d&#8217;utiliser sudo. C&#8217;est un peu déroutant pour un sysadmin, mais dans un contexte de développement, c&#8217;est plus pratique et plus simple.</p>
<p>J&#8217;ai utilisé Homebrew sur mon Mac pour installer <em>MySQL</em>, <em>Git</em>, <em>ImageMagick</em>, <em>MongoDB</em>, … et nombre de petits outils tels que <code>tree</code>, <code>wget</code>, <code>ack</code>, …, avec beaucoup de satisfaction.</p>
<h2 id="crdits">Crédits</h2>
<p>En priorité, je souhaite remercier les développeurs de ces outils géniaux et l&#8217;armée de contributeurs qui a participé.</p>
<p>Merci à <a href="http://twitter.com/wayneeseguin">Wayne E Seguin</a> et <a href="http://twitter.com/jmettraux">John Mettraux</a> pour une méticuleuse relecture, <a href="http://twitter.com/thibaut_barrere">Thibaut Barrère</a> et <a href="http://twitter.com/sgruhier">Sébastien Gruhier</a> pour leur soutien et des astuces additionnelles</p>
<br /> Tagged: <a href='http://jeremy.wordpress.com/tag/bundler/'>bundler</a>, <a href='http://jeremy.wordpress.com/tag/mac-os-x/'>mac os x</a>, <a href='http://jeremy.wordpress.com/tag/passenger/'>passenger</a>, <a href='http://jeremy.wordpress.com/tag/rails/'>rails</a>, <a href='http://jeremy.wordpress.com/tag/ruby/'>ruby</a>, <a href='http://jeremy.wordpress.com/tag/rvm/'>rvm</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jeremy.wordpress.com/262/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jeremy.wordpress.com/262/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=262&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jeremy.wordpress.com/2010/08/13/ruby-rvm-passenger-rails-bundler-en-developpement/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7d1caf9df777b3b2cf474ff743494335?s=96&#38;d=&#38;r=PG" medium="image">
			<media:title type="html">jeremy</media:title>
		</media:content>
	</item>
		<item>
		<title>4 juin : Club de lecture &#8211; épisode 2, Git branching</title>
		<link>http://jeremy.wordpress.com/2010/05/19/club-de-lecture-episode-2-git-branching/</link>
		<comments>http://jeremy.wordpress.com/2010/05/19/club-de-lecture-episode-2-git-branching/#comments</comments>
		<pubDate>Wed, 19 May 2010 19:13:20 +0000</pubDate>
		<dc:creator>Jérémy Lecour</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[laboate]]></category>
		<category><![CDATA[Personnel]]></category>
		<category><![CDATA[PLUG]]></category>
		<category><![CDATA[book-club]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://jeremy.wordpress.com/?p=254</guid>
		<description><![CDATA[Après l&#8217;épisode pilote du Club de lecture, nous avons décidé de produire la suite et on espère qu&#8217;il y a aura de nombreux épisodes, voire plusieurs saisons. Pour ceux qui auraient raté un wagon, l&#8217;idée vient de là. Cette fois, &#8230; <a href="http://jeremy.wordpress.com/2010/05/19/club-de-lecture-episode-2-git-branching/">Lire la suite <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=254&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Après l&rsquo;épisode pilote du <strong>Club de lecture</strong>, nous avons décidé de produire la suite et on espère qu&rsquo;il y a aura de nombreux épisodes, voire plusieurs saisons.</p>
<p>Pour ceux qui auraient raté un wagon, <a href="http://jeremy.wordpress.com/2010/03/15/un-club-de-lecture-technique/">l&rsquo;idée vient de là</a>.</p>
<p>Cette fois, nous allons nous aventurer sur les terres un peu plus techniques de <a href="http://git-scm.org/">Git</a>, le célèbre système de contrôle de version pour les développeurs (et pas que).</p>
<h3>Quel livre pour cette fois ?<a href="http://progit.org/"><img class="alignright size-full wp-image-257" title="Pro Git" src="http://jeremy.files.wordpress.com/2010/05/20100410-ksdhut3fethu63nu6n8bt898g7.png?w=640" alt=""   /></a></h3>
<p>Le livre s&rsquo;appelle <strong><a href="http://progit.org/"><em>Pro Git</em></a></strong>, écrit par <strong>Scott Chacon</strong> et édité par <strong>APress</strong>. On le trouve en version papier ou gratuitement en html. Les <a href="http://github.com/progit">sources sont mêmes disponibles</a> sur Github.</p>
<p><em>Pro Git</em> détaille le fonctionnement de Git, depuis les concepts de bases du versionning jusqu’aux dernières subtilités d’utilisation de ce formidable outil qui change la vie de ceux qui l’utilisent.</p>
<p>C’est un livre écrit par une des personnes qui connaissent le mieux Git — Scott Chacon — guru de Git chez Github. Ses talents de pédagogue et la qualité du contenu font de Progit un livre clé pour appréhender le vaste sujet du contrôle de version. Les chapitres sont focalisés et concis, illustrés de séquences de lignes de commande et d’illustrations.</p>
<p>Même si je conseille vivement la lecture intégrale du livre, nous avons choisi d&rsquo;étudier en particulier le <a href="http://progit.org/book/ch3-0.html">chapitre 3 : </a><strong><a href="http://progit.org/book/ch3-0.html">Git Branching</a>.</strong></p>
<h3>Où et quand ?</h3>
<p>Le rendez-vous est à <a href="http://laboate.com/">La Bo[a]te</a>, le <strong>vendredi 4 juin à 17h30</strong></p>
<p>Utilisez les commentaires pour donner votre avis, poser des questions, … N&rsquo;hésitez pas.</p>
<br /> Tagged: <a href='http://jeremy.wordpress.com/tag/book-club/'>book-club</a>, <a href='http://jeremy.wordpress.com/tag/git/'>git</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jeremy.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jeremy.wordpress.com/254/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=254&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jeremy.wordpress.com/2010/05/19/club-de-lecture-episode-2-git-branching/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7d1caf9df777b3b2cf474ff743494335?s=96&#38;d=&#38;r=PG" medium="image">
			<media:title type="html">jeremy</media:title>
		</media:content>

		<media:content url="http://jeremy.files.wordpress.com/2010/05/20100410-ksdhut3fethu63nu6n8bt898g7.png" medium="image">
			<media:title type="html">Pro Git</media:title>
		</media:content>
	</item>
		<item>
		<title>Club de lecture &#8211; épisode pilote &#8211; date et sujet fixés</title>
		<link>http://jeremy.wordpress.com/2010/04/25/club-de-lecture-episode-pilote-date-et-sujet-fixes/</link>
		<comments>http://jeremy.wordpress.com/2010/04/25/club-de-lecture-episode-pilote-date-et-sujet-fixes/#comments</comments>
		<pubDate>Sun, 25 Apr 2010 18:51:20 +0000</pubDate>
		<dc:creator>Jérémy Lecour</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[laboate]]></category>
		<category><![CDATA[Personnel]]></category>
		<category><![CDATA[PLUG]]></category>

		<guid isPermaLink="false">http://jeremy.wordpress.com/?p=239</guid>
		<description><![CDATA[Ceci est la suite de l&#8217;article d&#8217;annonce du premier &#34;épisode&#34; du club de lecture dans lequel vous trouverez les infos générales. D&#8217;après les commentaires et avis donnés ces derniers jours, on a donc fixé la date et le sujet de &#8230; <a href="http://jeremy.wordpress.com/2010/04/25/club-de-lecture-episode-pilote-date-et-sujet-fixes/">Lire la suite <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=239&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><a href="http://gettingreal.37signals.com/"><img class="wp-image-240 alignright" title="Getting Real, by 37signals" src="http://jeremy.files.wordpress.com/2010/04/homecover.jpg?w=200&#038;h=133" alt="" width="200" height="133" /></a></p>
<p>Ceci est la suite de l&rsquo;<a href="http://jeremy.wordpress.com/2010/04/20/club-de-lecture-episode-pilote/">article d&rsquo;annonce</a> du premier &quot;épisode&quot; du club de lecture dans lequel vous trouverez les <strong>infos générales</strong>.</p>
<p>D&rsquo;après les commentaires et avis donnés ces derniers jours, on a donc<strong> fixé la date et le sujet</strong> de lecture/discussion</p>
<ul>
<li>Date : mercredi <strong>12 mai</strong>, à <strong><a href="http://laboate.com/">La Bo[a]te</a></strong>, à partir de <strong>17h30</strong></li>
<li>Sujet : <strong><em>Getting Real</em></strong> par 37signals</li>
</ul>
<p>Je rappelle ce que  disais dans mon article d&rsquo;annonce :</p>
<blockquote><p>Même si je conseille évidemment à tout le monde de lire la totalité du bouquin, je propose qu’on se focalise sur les chapitres « <strong>Priorities</strong> » et « <strong>Feature Selection</strong> » (pages 37 à 58).</p>
<p>Outre les versions PDF et papier qui sont payantes, il existe une version gratuite en ligne. <a href="http://gettingreal.37signals.com/"><br />
http://gettingreal.37signals.com/<br />
</a></p></blockquote>
<p style="text-align:center;">
<p>Il est important que chacun prenne le peu de temps nécessaire pour <strong>lire au moins ces 2 chapitres</strong>, pour qu&rsquo;on puisse avoir une vraie <strong>discussion active</strong>. Ça n&rsquo;empêche par contre personne de venir en curieux pour juste regarder comment ça se passe.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jeremy.wordpress.com/239/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jeremy.wordpress.com/239/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=239&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jeremy.wordpress.com/2010/04/25/club-de-lecture-episode-pilote-date-et-sujet-fixes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7d1caf9df777b3b2cf474ff743494335?s=96&#38;d=&#38;r=PG" medium="image">
			<media:title type="html">jeremy</media:title>
		</media:content>

		<media:content url="http://jeremy.files.wordpress.com/2010/04/homecover.jpg" medium="image">
			<media:title type="html">Getting Real, by 37signals</media:title>
		</media:content>
	</item>
		<item>
		<title>Djangocong 2010</title>
		<link>http://jeremy.wordpress.com/2010/04/25/djangocong-2010/</link>
		<comments>http://jeremy.wordpress.com/2010/04/25/djangocong-2010/#comments</comments>
		<pubDate>Sun, 25 Apr 2010 15:07:58 +0000</pubDate>
		<dc:creator>Jérémy Lecour</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[PLUG]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[djangocong]]></category>
		<category><![CDATA[marseille]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://jeremy.wordpress.com/?p=247</guid>
		<description><![CDATA[Par curiosité, j&#8217;ai passé une partie de mon week-end dans une conférence Django (Djangocong 2010, à Marseille). Ceux qui me connaissent peuvent être étonnés. &#34;Qu&#8217;est-ce qu&#8217;un développeur Ruby, si passionné par ce langage peut bien aller faire chez des pythonistes &#8230; <a href="http://jeremy.wordpress.com/2010/04/25/djangocong-2010/">Lire la suite <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=247&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Par curiosité, j&rsquo;ai passé une partie de mon week-end dans une conférence Django (<a href="http://rencontres.django-fr.org/">Djangocong 2010, à Marseille</a>).</p>
<p>Ceux qui me connaissent peuvent être étonnés.</p>
<blockquote><p>&quot;Qu&rsquo;est-ce qu&rsquo;un développeur Ruby, si passionné par ce langage peut bien aller faire chez des pythonistes ?&quot;</p></blockquote>
<p>J&rsquo;avoue que je me suis moi aussi posé la question, mais je ne regrette pas de l&rsquo;avoir fait.</p>
<h2>Des gens bien</h2>
<p>J&rsquo;avais déjà <a href="http://blog.peepcode.com/tutorials/2010/what-pythonistas-think-of-ruby">lu sur le net</a> que la communauté des pythonistes est accueillante, pas sectaire, … et j&rsquo;ai clairement pu le vérifier. Déjà j&rsquo;étais pas inscrit, c&rsquo;était complet, et on m&rsquo;a quand même fait une place.</p>
<p>Le samedi après-midi, je me suis plutôt fait discret, du moins par rapport à Ruby. Je ne voulais pas avoir l&rsquo;air du cow-boy qui vient pour foutre la merde dans un saloon où on ne le connaît pas. J&rsquo;ai posé quelques questions et fait quelques remarques, mais sur des sujets que je connais, sans dire &quot;oui en Python, mais en Ruby c&rsquo;est mieux&quot;.</p>
<p>Quand il a été question de fixer le programme des lightning-talks, <a href="http://twitter.com/jlecour/status/12766009060">je me suis proposé</a>, pour rigoler, de faire une présentation Ruby, et on m&rsquo;a pris au sérieux et fait une place parmi les autres.</p>
<p>J&rsquo;ai donc préparé un peu en urgence une <a href="http://www.slideshare.net/jlecour/rails-djangocong">mini présentation (4 minutes) de Rails 3</a>, pour rester dans l&rsquo;univers framework plutôt que langage.</p>
<p><a href="http://twitter.com/jlecour/status/12789500403">Je pensais me faire siffler</a>, … mais en fait il semblerait que ça ait intéressé du monde et même évoqué des curiosités et des envies de voir plus loin, pour certains. Il paraît que j&rsquo;ai même un créneau pour une présentation complète pour l&rsquo;édition 2011. Attention, je suis pas du genre à me défiler ;-)</p>
<p>Tout le temps que j&rsquo;ai passé parmi cette bande de geeks, j&rsquo;ai plutôt eu l&rsquo;impression d&rsquo;être un cousin éloigné, mais avec qui on a beaucoup de choses en commun.</p>
<h2>La technologie</h2>
<p>Pendant les moments de pause, et au repas, … j&rsquo;ai pu discuter de manière très ouverte et détendue avec pas mal de monde, tous des gens bien, curieux, ouverts, … J&rsquo;ai pu parler de Ruby, de ses forces, de ses quelques faiblesses, de son écosystème. J&rsquo;au aussi pu entendre plein de choses intéressantes sur Python et Django. On a aussi pu parler abondamment de versionning en général et de Git en particulier.</p>
<p>Je le savais déjà, mais j&rsquo;ai pu le vérifier, il y a finalement beaucoup de similitudes entre ces 2 mondes.</p>
<p>Les sujets des conférences étaient appliqués à Django, mais certains pouvaient abstraits à d&rsquo;autres contextes. J&rsquo;ai donc appris certains trucs, mais rien de complètement nouveau. Ça n&rsquo;est pas le fait d&rsquo;être venu là qui me fait changer d&rsquo;avis sur Python et Django, mais au moins j&rsquo;en ai une idée plus précise.</p>
<h2><strong>Conclusion</strong></h2>
<p>Ce que je retient c&rsquo;est le plaisir d&rsquo;avoir passé un moment très geek, avec des gens sympa, d&rsquo;avoir pu parler de ma passion et écouter celle des autres, confronter des convictions, et s&rsquo;ouvrir l&rsquo;esprit à des choses nouvelles.</p>
<p>Rendez-vous donc l&rsquo;année prochaine pour un plat de résistance plus copieux autour de Ruby et de Rails.</p>
<p>D&rsquo;ici là, et pour ceux qui sont ou viennent à Marseille, il y a les réunions du <a href="http://plugfr.org/">PLUG</a>, tous les mois, pour discuter de développement, de langages, frameworks, infrastructures, …</p>
<br /> Tagged: <a href='http://jeremy.wordpress.com/tag/django/'>django</a>, <a href='http://jeremy.wordpress.com/tag/djangocong/'>djangocong</a>, <a href='http://jeremy.wordpress.com/tag/marseille/'>marseille</a>, <a href='http://jeremy.wordpress.com/tag/python/'>python</a>, <a href='http://jeremy.wordpress.com/tag/rails/'>rails</a>, <a href='http://jeremy.wordpress.com/tag/ruby/'>ruby</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jeremy.wordpress.com/247/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jeremy.wordpress.com/247/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=247&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jeremy.wordpress.com/2010/04/25/djangocong-2010/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7d1caf9df777b3b2cf474ff743494335?s=96&#38;d=&#38;r=PG" medium="image">
			<media:title type="html">jeremy</media:title>
		</media:content>
	</item>
		<item>
		<title>Club de lecture &#8211; épisode pilote</title>
		<link>http://jeremy.wordpress.com/2010/04/20/club-de-lecture-episode-pilote/</link>
		<comments>http://jeremy.wordpress.com/2010/04/20/club-de-lecture-episode-pilote/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 22:02:56 +0000</pubDate>
		<dc:creator>Jérémy Lecour</dc:creator>
				<category><![CDATA[Autrement]]></category>
		<category><![CDATA[Informatique]]></category>
		<category><![CDATA[Personnel]]></category>
		<category><![CDATA[PLUG]]></category>
		<category><![CDATA[37signals]]></category>
		<category><![CDATA[book-club]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>

		<guid isPermaLink="false">http://jeremy.wordpress.com/?p=230</guid>
		<description><![CDATA[Il y a quelques semaines, j&#8217;ai évoqué mon idée d&#8217;organiser un club de lecture technique. Sur mon blog et &#34;dans la vraie vie&#34; j&#8217;ai eu plutôt des bons retours de personnes qui en résumé veulent bien tenter l&#8217;expérience pour voir &#8230; <a href="http://jeremy.wordpress.com/2010/04/20/club-de-lecture-episode-pilote/">Lire la suite <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=230&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Il y a quelques semaines, j&rsquo;ai <a href="http://jeremy.wordpress.com/2010/03/15/un-club-de-lecture-technique/">évoqué mon idée d&rsquo;organiser un club de lecture</a> technique. Sur mon blog et &quot;dans la vraie vie&quot; j&rsquo;ai eu plutôt des bons retours de personnes qui en résumé veulent bien tenter l&rsquo;expérience pour voir ce que ça peut donner.</p>
<p>La plupart des questions que je posais lors de l&rsquo;exposé de mon idée n&rsquo;a pas trouvé de réponse à cette heure, mais c&rsquo;est pas grave, on va se lancer avec le bon sens comme point de départ — enfin le mien donc j&rsquo;espère que c&rsquo;est le bon.</p>
<h2>Quelle date ?</h2>
<p>Je propose donc le vendredi <strong>30 avril à partir de 17h30</strong>, jusqu&rsquo;à 18h30-19h.</p>
<p>Ça n&rsquo;est qu&rsquo;une proposition et il y a finalement peu de contraintes sur la date, à part l&rsquo;idée à laquelle je tiens, qu&rsquo;il faut que ne ça soit pas sur du temps personnel, mais plus sur du temps de boulot. Je vous renvoie à mes arguments sur la question si besoin.</p>
<p>Si vous êtes intéressé(e) mais que la date pose un problème, dites le en commentaire, on trouvera ce qui convient le mieux.</p>
<h2>Quel livre ?</h2>
<p>J&rsquo;ai bien dans l&rsquo;idée d&rsquo;aborder des sujets assez avancés : certaines techniques de programmation, d&rsquo;organisation des projets, … mais ça me paraissait risqué de partir trop vite, trop fort. Il suffit que le sujet soit trop axé sur tel ou tel langage ou approche pour que les timides soient refroidis et que la sauce ne prenne pas.</p>
<p>J&rsquo;ai donc cherché un sujet qui concerne tout le public, à savoir les <strong>geeks intéressés à découvrir de nouvelles pratiques</strong> : innovation techno, optimisation des méthodes et perfectionnement des outils.</p>
<p>J&rsquo;ai dit que ça n&rsquo;était pas &quot;mon&quot; club de lecture, même si j&rsquo;en suis à l&rsquo;origine, donc je propose 2 livres, bien différents. Ceux qui souhaiteraient participer n&rsquo;ont qu&rsquo;à donner leur avis, on choisira en fonction.</p>
<h3><em>Getting Real</em> par 37signals</h3>
<p><em>Getting Real</em> expose les concepts de l&rsquo;équipe de 37signals sur le travail d&rsquo;une équipe qui produit une application web. De l&rsquo;émergence de l&rsquo;idée, jusqu&rsquo;au marketing et support client en passant par la conception, le financement, la création des interfaces, le développement du code et l&rsquo;organisation de l&rsquo;équipe qui porte le projet.</p>
<p>C&rsquo;est un ensemble de très courts essais, illustrant chacun une idée simple, organisés en chapitres cohérents. Ça se lit très vite (160 pages de 200/300 mots chacune). Il m&rsquo;a suffit de 4 à 5 heures de lecture pour le boucler, et je ne lis pas vite.</p>
<p>Même si je conseille évidemment à tout le monde de lire la totalité du bouquin, je propose qu&rsquo;on se focalise sur les chapitres &quot;<strong>Priorities</strong>&quot; et &quot;<strong>Feature Selection</strong>&quot; (pages 37 à 58).</p>
<p>Outre les versions PDF et papier qui sont payantes, il existe une version gratuite en ligne. <a href="http://gettingreal.37signals.com/"><br />
http://gettingreal.37signals.com/<br />
</a></p>
<h3><em>Progit</em> par Scott Chacon</h3>
<p><em>Progit</em> détaille le fonctionnement de Git, un système de contrôle de version, depuis les concepts de bases du versionning jusqu&rsquo;aux dernières subtilités d&rsquo;utilisation de ce formidable outil qui change la vie de ceux qui l&rsquo;utilisent.</p>
<p>C&rsquo;est un livre écrit par une des personnes qui connaissent le mieux Git — Scott Chacon — guru de Git chez Github. Ses talents de pédagogue et la qualité du contenu font de Progit un livre clé pour appréhender le vaste sujet du contrôle de version. Les chapitres sont focalisés et concis, illustrés de séquences de lignes de commande et d&rsquo;illustrations.</p>
<p>Je propose de se focaliser sur un seul chapitre à choisir entre &quot;<strong>Git Branching</strong>&quot; et &quot;<strong>Distributed Git</strong>&quot;. Les deux sujets sont très différents et méritent chacun une pleine discussion.</p>
<p>Le livre existe en version PDF et papier chez Apress, mais il est également disponible gratuitement en ligne (HTML ou sources). <a href="http://progit.org/"><br />
http://progit.org/<br />
</a></p>
<h3>Au Choix</h3>
<div>
<p>Je suis très attaché aux 2 sujets et j&rsquo;y trouve autant d&rsquo;intérêt, mais ça n&rsquo;est pas forcément le cas de tout le monde.</p>
<p><em>Getting Real</em> cible tous les profils dans une entreprise qui développe des produits en ligne, mais n&rsquo;est pas strictement un sujet technique.</p>
<p><em>Progit</em> est beaucoup plus orienté développeur mais quels que soient les produits qu&rsquo;on développe, Git change tellement la vie que c&rsquo;en est un sujet incontournable.</p>
<p>Je vous propose donc de donner votre avis, surtout si l&rsquo;un ou l&rsquo;autre des sujets vous ferait venir à coup sûr ou au contraire zapper la première.</p>
</div>
<br /> Tagged: <a href='http://jeremy.wordpress.com/tag/37signals/'>37signals</a>, <a href='http://jeremy.wordpress.com/tag/book-club/'>book-club</a>, <a href='http://jeremy.wordpress.com/tag/git/'>git</a>, <a href='http://jeremy.wordpress.com/tag/github/'>github</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jeremy.wordpress.com/230/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jeremy.wordpress.com/230/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jeremy.wordpress.com&#038;blog=430&#038;post=230&#038;subd=jeremy&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jeremy.wordpress.com/2010/04/20/club-de-lecture-episode-pilote/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7d1caf9df777b3b2cf474ff743494335?s=96&#38;d=&#38;r=PG" medium="image">
			<media:title type="html">jeremy</media:title>
		</media:content>
	</item>
	</channel>
</rss>
