<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>jbbarth's corner</title>
    <link></link>
    <language>en</language>
    <webMaster>jeanbaptiste.barth*AT*gmail*DOT*com (jbbarth)</webMaster>
    <copyright>Copyright 2010</copyright>
    <ttl>60</ttl>
    <pubDate>Fri, 21 May 2010 23:09:00 GMT</pubDate>
    <description></description>
    <item>
      <title>Diaspora &amp; panurgisme</title>
      <link>/archives/2010/5/17/diaspora_panurgisme/</link>
      <pubDate>Mon, 17 May 2010 06:30:00 GMT</pubDate>
      <guid>/archives/2010/5/17/diaspora_panurgisme/</guid>
      <author>jeanbaptiste.barth@gmail.com (JB)</author>
      <description>&lt;p&gt;&lt;a href=&quot;http://joindiaspora.com/&quot;&gt;Diaspora&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;C&amp;#8217;est le truc qui m&amp;#8217;aura &amp;eacute;nerv&amp;eacute; dans les news informatiques des 2 derni&amp;egrave;res semaines. De nombreux signaux tendent &amp;agrave; montrer que &lt;a href=&quot;http://facebook.com/&quot;&gt;Facebook&lt;/a&gt; se soucie de moins en moins du respect des donn&amp;eacute;es priv&amp;eacute;es de ses utilisateurs. 60% des utilisateurs penseraient m&amp;ecirc;me &lt;a href=&quot;http://www.pcinpact.com/actu/news/57080-facebook-parametres-vie-privee-sondage.htm&quot;&gt;&amp;agrave; quitter Facebook&lt;/a&gt;. Et voil&amp;agrave; qu&amp;#8217;on a droit &amp;agrave; un festival d&amp;#8217;articles sur 4 gus qui ont lev&amp;eacute; 170k&amp;euro; et des bananes pour monter une alternative libre &amp;agrave; Facebook, Diaspora.&lt;/p&gt;
&lt;p&gt;Libre ? Ah euh oui, enfin un jour quoi. D&amp;eacute;j&amp;agrave; quand il y aura quelque chose &amp;agrave; montrer. Pour l&amp;#8217;instant, il n&amp;#8217;y a rien, il y a de la com&amp;#8217; et c&amp;#8217;est tout. Les formats d&amp;#8217;&amp;eacute;change ? Les technos qui seront employ&amp;eacute;es/support&amp;eacute;es ? On n&amp;#8217;en sait rien. Il y a l&amp;agrave; juste du buzz, juste des mecs qui ont lev&amp;eacute; du fric sur rien. M&amp;ecirc;me le grand Tristant Nitot se fait prendre &lt;a href=&quot;http://standblog.org/blog/post/2010/05/12/apres-Facebook-Diaspora&quot;&gt;&amp;agrave; un enthousiasme un peu absurde&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Seulement la messe semble dite, ce projet va dans le mur. Comme je n&amp;#8217;ai pas eu le temps d&amp;#8217;&amp;eacute;crire cet article en temps et en heure, d&amp;#8217;autre ont bien r&amp;eacute;sum&amp;eacute; la situation pour moi, et je ne peux qu&amp;#8217;approuver :&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://t37.net/7-raisons-pour-lesquelles-diaspora-le-facebook-ouvert-est-condamne-davance.html&quot;&gt;7 raisons pour lesquelles Diaspora, l&amp;#8217;alternative ouverte &amp;agrave; Facebook est condamn&amp;eacute;e d&amp;#8217;avance&lt;/a&gt; chez Fr&amp;eacute;d&amp;eacute;ric de Villamil, mister Typo&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://37signals.com/svn/posts/2330-diasporas-curse&quot;&gt;Diaspora&amp;#8217;s Curse&lt;/a&gt; par Jason Fried de chez 37signals&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;C&amp;#8217;est lamentable qu&amp;#8217;on fasse de la pub &amp;agrave; quelque chose qui n&amp;#8217;est &lt;strong&gt;rien&lt;/strong&gt;, juste parce que le Times en a fait un article. Qui plus est quand on voit fleurir les alternatives tangibles, comme &lt;a href=&quot;http://movim.eu&quot;&gt;Movim&lt;/a&gt;, avec du vrai code, des trucs qu&amp;#8217;on peut essayer, tout &amp;ccedil;a..&lt;/p&gt;
&lt;p&gt;B&amp;ecirc;&amp;ecirc;&amp;ecirc;&amp;ecirc;h !&lt;/p&gt;</description>
      <category domain="/archives/tags/actu">actu</category>
      <category domain="/archives/tags/thoughts">thoughts</category>
    </item>
    <item>
      <title>Redmine Plugins #3 : supporter plusieurs langues</title>
      <link>/archives/2010/4/26/redmine_plugins_supporter_plusieurs_langues/</link>
      <pubDate>Mon, 26 Apr 2010 11:10:00 GMT</pubDate>
      <guid>/archives/2010/4/26/redmine_plugins_supporter_plusieurs_langues/</guid>
      <author>jeanbaptiste.barth@gmail.com (JB)</author>
      <description>&lt;p&gt;Redmine supporte &amp;agrave; ce jour 37 langues. Si vous souhaitez diffuser votre plugin, c&amp;#8217;est une bonne id&amp;eacute;e de respecter les m&amp;ecirc;mes conventions que le core, pour en faciliter les traductions, voire proposer plusieurs traductions de votre plugin directement. C&amp;#8217;est ce que je fais par exemple pour mon plugin &amp;#8220;Datacenter&amp;#8221; que je livre en anglais et en fran&amp;ccedil;ais (voir &lt;a href=&quot;http://code.jbbarth.com/projects/redmine-datacenter/wiki/FrWiki&quot;&gt;la page de wiki fran&amp;ccedil;aise&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Pour cela, Redmine utilise l&amp;#8217;internationalisation de Rails. Chaque mot ou groupe de mot qui doit &amp;ecirc;tre traduit est associ&amp;eacute; &amp;agrave; une cl&amp;eacute; unique. Chaque langue a son fichier &lt;span class=&quot;caps&quot;&gt;YAML&lt;/span&gt; dans le dossier &lt;code&gt;config/locales/&lt;/code&gt;, et dans ce fichier on indique que telle cl&amp;eacute; correspond &amp;agrave; telle chaine de caract&amp;egrave;res. Par exemple, plut&amp;ocirc;t que d&amp;#8217;&amp;eacute;crire &amp;#8220;Mon super plugin&amp;#8221; directement dans vos vus et helpers, vous allez lui associer une cl&amp;eacute; de votre choix, mettons &lt;code&gt;text_my_super_plugin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Dans la vue, vous pourrez utiliser le helper &lt;code&gt;l()&lt;/code&gt; (un L minuscule) de cette fa&amp;ccedil;on :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;&amp;lt;%=&lt;/span&gt; l(&lt;span class=&quot;sy&quot;&gt;:text_my_super_plugin&lt;/span&gt;) &lt;span class=&quot;idl&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Ensuite vous devrez associer cette cl&amp;eacute; &amp;agrave; sa valeur pour chaque langue. Pour le fran&amp;ccedil;ais, le fichier &lt;code&gt;config/locales/fr.yml&lt;/code&gt; de votre plugin ressemblera &amp;agrave; &amp;ccedil;a :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;ke&quot;&gt;fr&lt;/span&gt;:
  &lt;span class=&quot;ke&quot;&gt;text_my_super_plugin&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;Mon super plugin&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Et vous pouvez traduire votre appli en anglais, en ajoutant un fichier &lt;code&gt;config/locales/en.yml&lt;/code&gt; contenant :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;ke&quot;&gt;en&lt;/span&gt;:
  &lt;span class=&quot;ke&quot;&gt;text_my_super_plugin&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;My great plugin&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Pour un texte accentu&amp;eacute; ou comportant des caract&amp;egrave;res sp&amp;eacute;ciaux, il suffira de mettre la chaine entre quotes pour &amp;eacute;viter toute confusion lors de l&amp;#8217;analyse du fichier. Attention &amp;agrave; ce que votre fichier reste bien en UTF8 tout de m&amp;ecirc;me.&lt;/p&gt;
&lt;p&gt;Si la traduction n&amp;#8217;existe pas (fichier de langue manquant ou cl&amp;eacute; inexistante dans la langue de l&amp;#8217;utilisateur), Redmine affichera une erreur. C&amp;#8217;est la que le helper &lt;code&gt;l_or_humanize&lt;/code&gt; peut &amp;ecirc;tre utile :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;&amp;lt;%=&lt;/span&gt; l_or_humanize(&lt;span class=&quot;sy&quot;&gt;:super_plugin&lt;/span&gt;) &lt;span class=&quot;idl&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Si la cl&amp;eacute; existe, elle sera remplac&amp;eacute;e par sa traduction. Si non, Rails tentera d&amp;#8217;en faire une chaine pour humain (remplacement des underscores par des espaces, majuscule &amp;agrave; la premi&amp;egrave;re lettre, etc.). En l&amp;#8217;occurrence &lt;code&gt;Super plugin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Pour les affichages de dates, heures, temps ou intervalles de temps, il existe des helpers beaucoup plus &amp;eacute;volu&amp;eacute;s que ceux pr&amp;eacute;sent&amp;eacute;s ci-dessus. Ils sont d&amp;eacute;finis dans &lt;code&gt;lib/redmine/i18n.rb&lt;/code&gt;. En voici une liste, ainsi que comment les tester dans une console Rails :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;% &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ruby&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt; &lt;/span&gt;&lt;/span&gt;script/console
&lt;span class=&quot;co&quot;&gt;Loading&lt;/span&gt; production environment (&lt;span class=&quot;co&quot;&gt;Rails&lt;/span&gt; &lt;span class=&quot;fl&quot;&gt;2.3&lt;/span&gt;.&lt;span class=&quot;i&quot;&gt;5&lt;/span&gt;)
&amp;gt;&amp;gt; include &lt;span class=&quot;co&quot;&gt;Redmine&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;I18n&lt;/span&gt;
=&amp;gt; &lt;span class=&quot;co&quot;&gt;Object&lt;/span&gt;
&amp;gt;&amp;gt; set_language_if_valid(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fr&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)
=&amp;gt; &lt;span class=&quot;sy&quot;&gt;:fr&lt;/span&gt;
&amp;gt;&amp;gt; l_hours(&lt;span class=&quot;i&quot;&gt;5&lt;/span&gt;)
=&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;5.00 heures&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&amp;gt;&amp;gt; format_date(&lt;span class=&quot;co&quot;&gt;Time&lt;/span&gt;.now)
=&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;26/04/2010&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&amp;gt;&amp;gt; format_time(&lt;span class=&quot;co&quot;&gt;Time&lt;/span&gt;.now)
=&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;26/04/2010 19:55&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&amp;gt;&amp;gt; day_name(&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;)
=&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lundi&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&amp;gt;&amp;gt; month_name(&lt;span class=&quot;i&quot;&gt;3&lt;/span&gt;)
=&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mars&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A des fins de test, le helper &lt;code&gt;ll()&lt;/code&gt; permet de pr&amp;eacute;ciser d&amp;#8217;abord la locale avant la cl&amp;eacute; et ainsi de tester une cl&amp;eacute; dans une locale particuli&amp;egrave;re :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&amp;gt;&amp;gt; ll(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:field_mail&lt;/span&gt;)
=&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;S&amp;auml;hk&amp;ouml;posti&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Derni&amp;egrave;re chose, il est possible d&amp;#8217;utiliser des variables dans vos fichiers de langue. Ils seront interpol&amp;eacute;s lors du rendu de la vue. Si vous n&amp;#8217;avez qu&amp;#8217;une variable &amp;agrave; mettre, vous pouvez utiliser le nom &amp;#8220;value&amp;#8221; et passer la valeur dans votre vue directement en 2e argument de votre &lt;code&gt;l()&lt;/code&gt;. Si vous avez 2 variables ou plus, il faut leur donner un nom et passer un hash en 2e argument de &lt;code&gt;l()&lt;/code&gt; dans votre vue. Evidemment ces valeurs peuvent elles-m&amp;ecirc;me faire appel &amp;agrave; vos traductions pour &amp;eacute;viter de dupliquer des traductions.&lt;/p&gt;
&lt;p&gt;Un exemple vaut mieux qu&amp;#8217;un long discours. Avec ce fichier de langue :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;ke&quot;&gt;fr&lt;/span&gt;:
  &lt;span class=&quot;ke&quot;&gt;label_draft_saved_time&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Brouillon sauvegard&amp;eacute; &amp;agrave; {{value}}&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;ke&quot;&gt;label_draft_pending&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Brouillon en attente, sauvegard&amp;eacute; il y a {{time}} : {{restore}} ou {{delete}}&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;ke&quot;&gt;label_draft_restore&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;restaurer&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;ke&quot;&gt;label_draft_delete&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;supprimer&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Je peux faire appel &amp;agrave; ceci dans mes vues (les valeurs de temps sont bidon) :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;&amp;lt;%=&lt;/span&gt; l(&lt;span class=&quot;sy&quot;&gt;:label_draft_saved_time&lt;/span&gt;, format_time(&lt;span class=&quot;co&quot;&gt;Time&lt;/span&gt;.now)) &lt;span class=&quot;idl&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;&amp;lt;%=&lt;/span&gt; l(&lt;span class=&quot;sy&quot;&gt;:label_draft_pending&lt;/span&gt;, {&lt;span class=&quot;sy&quot;&gt;:time&lt;/span&gt; =&amp;gt; format_time(&lt;span class=&quot;co&quot;&gt;Time&lt;/span&gt;.now),
                             &lt;span class=&quot;sy&quot;&gt;:restore&lt;/span&gt; =&amp;gt; l(&lt;span class=&quot;sy&quot;&gt;:label_draft_restore&lt;/span&gt;),
                             &lt;span class=&quot;sy&quot;&gt;:delete&lt;/span&gt; =&amp;gt; l(&lt;span class=&quot;sy&quot;&gt;:label_draft_delete&lt;/span&gt;)}) &lt;span class=&quot;idl&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;J&amp;#8217;essaierai de documenter tout &amp;ccedil;a en anglais dans le wiki Redmine un de ces 4.&lt;/p&gt;</description>
      <category domain="/archives/tags/rails">rails</category>
      <category domain="/archives/tags/redmine">redmine</category>
      <category domain="/archives/tags/ruby">ruby</category>
    </item>
    <item>
      <title>Redmine Plugins #2 : patcher une classe de Redmine</title>
      <link>/archives/2010/4/20/redmine_plugins_patcher_une_classe/</link>
      <pubDate>Tue, 20 Apr 2010 15:36:00 GMT</pubDate>
      <guid>/archives/2010/4/20/redmine_plugins_patcher_une_classe/</guid>
      <author>jeanbaptiste.barth@gmail.com (JB)</author>
      <description>&lt;p&gt;Il peut arriver qu&amp;#8217;une classe de Redmine ne se comporte pas exactement comme vous le voudriez, ou que vous souhaitiez lui ajouter des propri&amp;eacute;t&amp;eacute;s.&lt;/p&gt;
&lt;p&gt;C&amp;#8217;est d&amp;eacute;crit en anglais sur la page &lt;a href=&quot;http://www.redmine.org/wiki/1/Plugin_Internals#Extending-the-Redmine-Core&quot;&gt;Plugin Internals / Extending the Redmine Core&lt;/a&gt; du wiki officiel, qui renvoie vers la lecture de certains plugins d&amp;#8217;Eric Davis pour des exemples.&lt;/p&gt;
&lt;p&gt;Petit appart&amp;eacute;, je partage assez l&amp;#8217;analyse selon laquelle il est quasi inutile de maintenir une &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; pour surcharger les mod&amp;egrave;les / controlleurs. Cela dit, parfois les m&amp;eacute;thodes sont extr&amp;ecirc;mement longues et/ou sujettes &amp;agrave; de fr&amp;eacute;quents changements. Toute surcharge dans un plugin induit donc un risque pour les futures versions du core&amp;#8230;&lt;/p&gt;
&lt;p&gt;Retour &amp;agrave; nos moutons : admettons qu&amp;#8217;on veuille ajouter au mod&amp;egrave;le &lt;code&gt;Issue&lt;/code&gt; une m&amp;eacute;thode d&amp;#8217;instance &lt;code&gt;whoami&lt;/code&gt; qui retournerait &amp;#8220;Je suis le ticket #&lt;span class=&quot;caps&quot;&gt;XXX&lt;/span&gt;&amp;#8221;. Exemple bidon, c&amp;#8217;est pour la science.&lt;/p&gt;
&lt;p&gt;Si on applique ce que pr&amp;eacute;conise Eric, &amp;ccedil;a donne quelque chose de ce genre :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;#init.rb&lt;/span&gt;
require_dependency &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;issue_patch&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;co&quot;&gt;Dispatcher&lt;/span&gt;.to_prepare &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;co&quot;&gt;Issue&lt;/span&gt;.send(&lt;span class=&quot;sy&quot;&gt;:include&lt;/span&gt;, &lt;span class=&quot;co&quot;&gt;IssuePatch&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;Issue&lt;/span&gt;.included_modules.include? &lt;span class=&quot;co&quot;&gt;IssuePatch&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;


&lt;span class=&quot;c&quot;&gt;#lib/issue_patch.rb&lt;/span&gt;
require_dependency &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;IssuePatch&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.included(base)
    base.extend(&lt;span class=&quot;co&quot;&gt;ClassMethods&lt;/span&gt;)
    base.send(&lt;span class=&quot;sy&quot;&gt;:include&lt;/span&gt;, &lt;span class=&quot;co&quot;&gt;InstanceMethods&lt;/span&gt;)
    base.class_eval &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;
      unloadable &lt;span class=&quot;c&quot;&gt;#permet de d&amp;eacute;charger la classe en mode dev&lt;/span&gt;
    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;c&quot;&gt;#ici nos m&amp;eacute;thodes de classe&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ClassMethods&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;c&quot;&gt;#ici nos m&amp;eacute;thodes d'instance&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;InstanceMethods&lt;/span&gt;
    &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;whoami&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Je suis le ticket #&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.id&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;    
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Classique, mais comme diraient certains amis &amp;#8220;on voit pas trop ce que &amp;ccedil;a fait&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Personnellement je pr&amp;eacute;f&amp;egrave;re r&amp;eacute;ouvrir la classe Issue, et &amp;ccedil;a a l&amp;#8217;air de marcher tout aussi bien (en dev et  en prod) :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;#init.rb&lt;/span&gt;
config.to_prepare &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;
  require_dependency &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;issue_patch&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;


&lt;span class=&quot;c&quot;&gt;#lib/issue_patch.rb&lt;/span&gt;
require_dependency &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Issue&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;whoami&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Je suis le ticket #&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.id&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Diff&amp;eacute;rences :&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;utilisation de &amp;#8220;config&amp;#8221; au lieu de &amp;#8220;Dispatcher&amp;#8221; ; sans importance &amp;agrave; mon avis. C&amp;#8217;est discut&amp;eacute; un peu &lt;a href=&quot;http://robots.thoughtbot.com/post/159805560/tips-for-writing-your-own-rails-engine&quot;&gt;ici&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;r&amp;eacute;-ouverture de la classe plut&amp;ocirc;t qu&amp;#8217;inclusion d&amp;#8217;un module ; je trouve &amp;ccedil;a plus lisible pour ce coup-ci&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Attention, je ne dis pas que ce que fait Eric fonctionne moins bien. Au contraire, c&amp;#8217;est peut-&amp;ecirc;tre plus &amp;#8220;propre&amp;#8221;, mais n&amp;#8217;&amp;eacute;tant pas un d&amp;eacute;veloppeur confirm&amp;eacute;, si je ne comprends pas au premier coup d&amp;#8217;oeil ce que j&amp;#8217;ai fait, j&amp;#8217;ai plus de mal &amp;agrave; maintenir mon code.&lt;/p&gt;
&lt;p&gt;Au passage, c&amp;#8217;est une mauvaise id&amp;eacute;e d&amp;#8217;appeler son patch &amp;#8220;lib/issue_patch.rb&amp;#8221;. Si tout le monde fait &amp;ccedil;a, on ne pourra pas faire fonctionner 2 plugins qui patchent la m&amp;ecirc;me classe en m&amp;ecirc;me temps. Beurk. D&amp;#8217;ailleurs, c&amp;#8217;&amp;eacute;tait le cas pour des plugins &amp;agrave; moi, donc autant utiliser des noms &lt;em&gt;a priori uniques&lt;/em&gt; : &lt;a href=&quot;http://github.com/jbbarth/redmine_drafts/commit/ec06b82818cf0f49466b1b6404da02683e9bea16&quot;&gt;commit redmine_drafts/ec06b8&lt;/a&gt;&lt;/p&gt;</description>
      <category domain="/archives/tags/rails">rails</category>
      <category domain="/archives/tags/redmine">redmine</category>
      <category domain="/archives/tags/ruby">ruby</category>
    </item>
    <item>
      <title>Execute, chef : oui mais par qui ?</title>
      <link>/archives/2010/4/17/execute_chef_oui_mais_par/</link>
      <pubDate>Sat, 17 Apr 2010 22:00:00 GMT</pubDate>
      <guid>/archives/2010/4/17/execute_chef_oui_mais_par/</guid>
      <author>jeanbaptiste.barth@gmail.com (JB)</author>
      <description>&lt;p&gt;Un billet en forme de petite note pour moi-m&amp;ecirc;me, relatif &amp;agrave; mes d&amp;eacute;couvertes de la soir&amp;eacute;e.&lt;/p&gt;
&lt;p&gt;J&amp;#8217;ai besoin d&amp;#8217;ex&amp;eacute;cuter des commandes avec &lt;a href=&quot;http://wiki.opscode.com/display/chef/Home&quot;&gt;Chef&lt;/a&gt;. Pour cela, il y a la ressource &lt;a href=&quot;http://wiki.opscode.com/display/chef/Resources#Resources-Execute&quot;&gt;Execute&lt;/a&gt; :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;execute &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ma commande&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Mais la documentation pr&amp;eacute;vient bien :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;By their nature, Execute resources are not idempotent, as they are completely up to the user&amp;#8217;s imagination. Use the not_if or only_if meta parameters to guard the resource for idempotence.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;OK, allons-y :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;execute &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ma commande&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;
  not_if &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ma condition shell&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Si la commande doit &amp;ecirc;tre ex&amp;eacute;cut&amp;eacute;e avec un user particulier :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;execute &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ma commande&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;
  user &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tom&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  not_if &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ma condition shell&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Mais la condition, elle, sera ex&amp;eacute;cut&amp;eacute;e dans un contexte root (puisqu&amp;#8217;il vaut mieux lancer chef-solo ou chef-client en root si l&amp;#8217;on veut que la plupart des ressources fonctionnent). En g&amp;eacute;n&amp;eacute;ral la condition serait &amp;agrave; ex&amp;eacute;cuter avec le m&amp;ecirc;me user. D&amp;#8217;o&amp;ugrave; :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;execute &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ma commande&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;
  user &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tom&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  not_if &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ma condition shell&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:user&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tom&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Je trouve pas &amp;ccedil;a tr&amp;egrave;s joli. A r&amp;eacute;fl&amp;eacute;chir.&lt;/p&gt;
&lt;p&gt;PS: si on veut se convaincre que &amp;ccedil;a se passe bien comme je dis :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;execute &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;whoami &amp;gt; /tmp/whoami.execute&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;
  user &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tom&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  only_if &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;whoami &amp;gt; /tmp/whoami.only_if&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;</description>
      <category domain="/archives/tags/chef">chef</category>
      <category domain="/archives/tags/ruby">ruby</category>
      <category domain="/archives/tags/tech">tech</category>
    </item>
    <item>
      <title>Chef la recette !</title>
      <link>/archives/2010/3/23/chef_la_recette/</link>
      <pubDate>Tue, 23 Mar 2010 18:52:00 GMT</pubDate>
      <guid>/archives/2010/3/23/chef_la_recette/</guid>
      <author>jeanbaptiste.barth@gmail.com (JB)</author>
      <description>&lt;p&gt;Apr&amp;egrave;s avoir compar&amp;eacute; au boulot 3 outils de gestion de conf, j&amp;#8217;en retiens les &amp;eacute;l&amp;eacute;ments suivants :&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.cfengine.org/&quot;&gt;Cfengine&lt;/a&gt; : &lt;span class=&quot;caps&quot;&gt;DSL&lt;/span&gt; sp&amp;eacute;cifique et horrible &amp;agrave; apprendre, orientations peu claire (&lt;em&gt;&amp;agrave;-la-Nagios&lt;/em&gt;), une communaut&amp;eacute; amorphe, pas hackable. Poubelle.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://reductivelabs.com/products/puppet/&quot;&gt;Puppet&lt;/a&gt; : en ruby, un &lt;span class=&quot;caps&quot;&gt;DSL&lt;/span&gt; sp&amp;eacute;cifique pour les confs (bof), a fait ses preuves, une bonne doc, de plus en plus hackable (la doc s&amp;#8217;am&amp;eacute;liore de jour en jour), une communaut&amp;eacute; dynamique, et le projet est g&amp;eacute;r&amp;eacute; sous &lt;a href=&quot;http://redmine.org&quot;&gt;redmine&lt;/a&gt;. Sympa.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.opscode.com/chef&quot;&gt;Chef&lt;/a&gt; : en ruby, &lt;em&gt;tout&lt;/em&gt; en ruby, donc pas de &lt;span class=&quot;caps&quot;&gt;DSL&lt;/span&gt; &amp;agrave; apprendre (yeah!), une doc pas mal, hackable &amp;agrave; l&amp;#8217;infini, le projet est hyper mega dynamique, et ils ont des r&amp;eacute;f&amp;eacute;rences &amp;eacute;normes dans le monde ruby, du genre 37signals ou Engine Yard. Adopt&amp;eacute; !&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Seul d&amp;eacute;faut de Chef, &amp;ccedil;a bouge vite, tr&amp;egrave;s vite. Et les versions 0.7 pr&amp;eacute;sentes dans mes distrib pr&amp;eacute;f&amp;eacute;r&amp;eacute;es commencent &amp;agrave; &amp;ecirc;tre vraiment d&amp;eacute;pass&amp;eacute;es.&lt;/p&gt;
&lt;p&gt;Hier je me prends donc par la main, en m&amp;#8217;inspirant de l&amp;#8217;article de &lt;a href=&quot;http://akitaonrails.com/2010/02/20/cooking-solo-with-chef&quot;&gt;akitaonrails&lt;/a&gt;, et je cherche comment installer une 0.8. Miracle, tout est dans &lt;a href=&quot;http://wiki.opscode.com/display/chef/Package+Installation+on+Debian+and+Ubuntu&quot;&gt;leur wiki&lt;/a&gt;, et ils proposent m&amp;ecirc;me des d&amp;eacute;p&amp;ocirc;ts pour ma Ubuntu Lucid.&lt;/p&gt;
&lt;p&gt;Voici un script chef-install pondu en 3 secondes :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;#installation
add-apt-repository ppa:jtimberman/opschef
aptitude update
aptitude -y install chef
service chef-client stop
update-rc.d chef-client disable &amp;gt;/dev/null

#configuration
sed -i -e 's#^file.*#file_cache_path &amp;quot;/tmp/chef-solo&amp;quot;#' \
    -e 's#^cook.*#cookbook_path [&amp;quot;/var/chef-solo/cookbooks&amp;quot;]#' /etc/chef/solo.rb

#cookbooks (install 'git-core' if needed)
mkdir -p /var/chef-solo
cd /var/chef-solo
git clone http://github.com/opscode/cookbooks.git

#hyperspace!
cat &amp;gt;/etc/chef/recipes.json &amp;lt;&amp;lt;EOF
{
  &amp;quot;resolver&amp;quot;: {&amp;quot;nameservers&amp;quot;:[&amp;quot;192.168.0.1&amp;quot;], &amp;quot;search&amp;quot;:&amp;quot;home&amp;quot;},
  &amp;quot;recipes&amp;quot;: [&amp;quot;resolver&amp;quot;]
}
EOF&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Go ?&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;% sudo chef-solo -j /etc/chef/recipes.json
[Tue, 23 Mar 2010 13:47:37 +0100] INFO: Starting Chef Solo Run
[Tue, 23 Mar 2010 13:47:42 +0100] WARN: Missing gem 'right_aws'
[Tue, 23 Mar 2010 13:47:42 +0100] WARN: Missing gem 'mysql'
[Tue, 23 Mar 2010 13:47:43 +0100] INFO: Updating template[/etc/resolv.conf] at /etc/resolv.conf
[Tue, 23 Mar 2010 13:47:43 +0100] INFO: Backing up template[/etc/resolv.conf] to /etc/resolv.conf.chef-20100323134743
[Tue, 23 Mar 2010 13:47:43 +0100] INFO: Chef Run complete in 5.588404 seconds&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Yeeehaa !&lt;/p&gt;
&lt;p&gt;Mon fonctionnement actuel m&amp;#8217;emp&amp;ecirc;che de m&amp;#8217;attacher &amp;agrave; un serveur central et ainsi fonctionner en client/serveur. Je pense que je vais donc commencer &amp;agrave; me faire des cookbooks et les utiliser &amp;#8220;b&amp;ecirc;tement&amp;#8221; via chef-solo, &amp;agrave; voir.&lt;/p&gt;
&lt;p&gt;Enfin pour l&amp;#8217;instant, c&amp;#8217;est juste &amp;eacute;norme.&lt;/p&gt;</description>
      <category domain="/archives/tags/chef">chef</category>
      <category domain="/archives/tags/ruby">ruby</category>
      <category domain="/archives/tags/tech">tech</category>
    </item>
    <item>
      <title>Schema-Free MySQL contre NoSQL</title>
      <link>/archives/2010/3/19/schemafree_mysql_contre_nosql/</link>
      <pubDate>Fri, 19 Mar 2010 18:00:00 GMT</pubDate>
      <guid>/archives/2010/3/19/schemafree_mysql_contre_nosql/</guid>
      <author>jeanbaptiste.barth@gmail.com (JB)</author>
      <description>&lt;p&gt;En ce moment il y a une vague d&amp;#8217;engouement pour les bases non-&lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;, comme les bases orient&amp;eacute;es document &lt;a href=&quot;http://couchdb.apache.org/&quot;&gt;CouchDB&lt;/a&gt; ou &lt;a href=&quot;http://www.mongodb.org/display/DOCS/Home&quot;&gt;MongoDB&lt;/a&gt;. J&amp;#8217;ai lu un article r&amp;eacute;cemment qui vaut le d&amp;eacute;tour : &lt;a href=&quot;http://www.igvita.com/2010/03/01/schema-free-mysql-vs-nosql/&quot;&gt;Schema Free Mysql VS NoSQL&lt;/a&gt; (&lt;a href=&quot;http://rubyflow.com/items/3537&quot;&gt;via&lt;/a&gt;). Ce genre de solution permettrait s&amp;ucirc;rement de faire passer la pillule plus doucement aux gens qui s&amp;#8217;accrochent encore au &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; pur &amp;agrave; l&amp;#8217;ancienne.&lt;/p&gt;
&lt;p&gt;Au passage, juste une citation qu&amp;#8217;on croirait destin&amp;eacute;e &amp;agrave; certains ayatollahs du boulot :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Open your mind. FriendFeed uses something very similiar to this to handle 250 million entries. Why is it no good for the theorists? Because they don&amp;#8217;t solve problems, they make them.&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category domain="/archives/tags/tech">tech</category>
    </item>
    <item>
      <title>.irbrc pour Rails 3</title>
      <link>/archives/2010/3/17/irbrc_pour_rails/</link>
      <pubDate>Wed, 17 Mar 2010 20:22:00 GMT</pubDate>
      <guid>/archives/2010/3/17/irbrc_pour_rails/</guid>
      <author>jeanbaptiste.barth@gmail.com (JB)</author>
      <description>&lt;p&gt;J&amp;#8217;utilise souvent &lt;a href=&quot;http://fr.wikipedia.org/wiki/Interactive_Ruby&quot;&gt;&lt;span class=&quot;caps&quot;&gt;IRB&lt;/span&gt;&lt;/a&gt;. Tr&amp;egrave;s souvent pour d&amp;#8217;autres choses que Rails (&lt;em&gt;&amp;agrave; la base&lt;/em&gt; on me paye pour &amp;ecirc;tre sysadmin, pas d&amp;eacute;veloppeur&amp;#8230;).&lt;/p&gt;
&lt;p&gt;L&amp;agrave; arrive Rails 3 beta :&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;qui s&amp;#8217;appuie sur &lt;span class=&quot;caps&quot;&gt;IRB&lt;/span&gt; pour sa console (&lt;code&gt;rails console&lt;/code&gt;)&lt;/li&gt;
	&lt;li&gt;qui g&amp;egrave;re ses d&amp;eacute;pendances via &lt;a href=&quot;http://github.com/carlhuda/bundler&quot;&gt;Bundler&lt;/a&gt;, ce qui ne permet plus par d&amp;eacute;faut de charger des Gems en dehors de son appli&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bah oui mais l&amp;agrave; &amp;ccedil;a coince. De b&amp;ecirc;tes &lt;code&gt;require&lt;/code&gt; dans mon .irbrc ne fonctionnent plus. Comme &lt;a href=&quot;http://groups.google.com/group/railsfrance/browse_thread/thread/d680e6708cd0db4b&quot;&gt;discut&amp;eacute; sur la liste rails france&lt;/a&gt;, je charge dans mon &lt;code&gt;.irbrc&lt;/code&gt; des choses dont j&amp;#8217;ai tr&amp;egrave;s souvent besoin, et qui n&amp;#8217;ont rien &amp;agrave; voir avec mes applis, m&amp;ecirc;me en Rails 3. Par exemple, il n&amp;#8217;y a &lt;strong&gt;aucune raison&lt;/strong&gt; qu&amp;#8217;une de mes applis d&amp;eacute;pende de &lt;a href=&quot;http://pablotron.org/software/wirble/&quot;&gt;Wirble&lt;/a&gt;, une lib pour am&amp;eacute;liorer &lt;span class=&quot;caps&quot;&gt;IRB&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Bref, faute de mieux pour le moment, voil&amp;agrave; le genre d&amp;#8217;horreur auquel Rails me pousse :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;basedirs = &lt;span class=&quot;co&quot;&gt;ENV&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;GEM_PATH&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;].to_s.split(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).map{|d|&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;d&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/gems/*/lib&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;}
&lt;span class=&quot;co&quot;&gt;Dir&lt;/span&gt;.glob(basedirs).each &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |dir|
  &lt;span class=&quot;gv&quot;&gt;$:&lt;/span&gt; &amp;lt;&amp;lt; dir &lt;span class=&quot;r&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;gv&quot;&gt;$:&lt;/span&gt;.include?(dir)
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Humpf.&lt;/p&gt;</description>
      <category domain="/archives/tags/irb">irb</category>
      <category domain="/archives/tags/rails3">rails3</category>
      <category domain="/archives/tags/ruby">ruby</category>
    </item>
    <item>
      <title>D&#233;placer une base Rails</title>
      <link>/archives/2010/3/17/dplacer_une_base_rails/</link>
      <pubDate>Wed, 17 Mar 2010 15:19:00 GMT</pubDate>
      <guid>/archives/2010/3/17/dplacer_une_base_rails/</guid>
      <author>jeanbaptiste.barth@gmail.com (JB)</author>
      <description>&lt;p&gt;Au boulot nous avons une instance &lt;a href=&quot;http://redmine.org/&quot;&gt;Redmine&lt;/a&gt; qui tourne avec une base Sqlite3 pour nos tickets internes. Pratique, mais nous avons aussi d&amp;eacute;velopp&amp;eacute; une offre d&amp;#8217;h&amp;eacute;bergement Redmine ouverte &amp;agrave; la demande sur l&amp;#8217;intranet, sous Mysql. D&amp;#8217;o&amp;ugrave; passage de l&amp;#8217;instance Sqlite sous Mysql.&lt;/p&gt;
&lt;p&gt;On ne peut bien s&amp;ucirc;r pas se contenter d&amp;#8217;un export &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; de Sqlite &amp;agrave; r&amp;eacute;importer sous Mysql : ces deux moteurs ne respectent pas exactement la m&amp;ecirc;me syntaxe &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;, et ne stockent pas leurs types primitifs de la m&amp;ecirc;me mani&amp;egrave;re (exemple: les bool&amp;eacute;ens, stock&amp;eacute;s en &amp;#8220;1/0&amp;#8221; sous Mysql, et en &amp;#8220;t/f&amp;#8221; sous Sqlite).&lt;/p&gt;
&lt;p&gt;C&amp;#8217;est l&amp;agrave; qu&amp;#8217;arrive &lt;a href=&quot;http://github.com/ludicast/yaml_db&quot;&gt;yaml_db&lt;/a&gt; , une biblitoth&amp;egrave;que &amp;agrave; installer comme une gem ou comme un plugin dans une appli Rails, qui permet de r&amp;eacute;aliser des exports ou imports de sa base sous un format neutre, &lt;a href=&quot;http://www.yaml.org&quot;&gt;&lt;span class=&quot;caps&quot;&gt;YAML&lt;/span&gt;&lt;/a&gt; (&lt;a href=&quot;http://fr.wikipedia.org/wiki/YAML&quot;&gt;wikipedia&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Pour une migration &lt;em&gt;&amp;#8220;one shot&amp;#8221;&lt;/em&gt;, le plus simple sera de cloner la lib dans le r&amp;eacute;pertoire plugins de vos applis et de suivre les instructions propos&amp;eacute;es dans le &lt;span class=&quot;caps&quot;&gt;README&lt;/span&gt; :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;cd /path/to/my/app
cd vendor/plugins
git clone http://github.com/ludicast/yaml_db.git
cd -
rake db:dump
#modifications &amp;eacute;ventuelles du fichier db/data.yml (chez nous l'appli change d'adresse, donc on a remplac&amp;eacute; toutes les anciennes URLs)
#changement de database.yml
rake db:load&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Un outil simple, comme on aime :)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;EDIT&lt;/span&gt;&lt;/strong&gt;: j&amp;#8217;ai titr&amp;eacute; &amp;#8220;d&amp;eacute;placer une base Rails&amp;#8221; car ce plugin fonctionne bien surtout avec une base ActiveRecord, &lt;span class=&quot;caps&quot;&gt;ORM&lt;/span&gt; de Rails par d&amp;eacute;faut. Pour une base quelconque rien de garanti :)&lt;/p&gt;</description>
      <category domain="/archives/tags/rails">rails</category>
      <category domain="/archives/tags/redmine">redmine</category>
      <category domain="/archives/tags/ruby">ruby</category>
    </item>
    <item>
      <title>Partie 1 : le retour de la vengeance</title>
      <link>/archives/2010/3/4/partie_le_retour_de_la/</link>
      <pubDate>Thu, 04 Mar 2010 11:20:00 GMT</pubDate>
      <guid>/archives/2010/3/4/partie_le_retour_de_la/</guid>
      <author>jeanbaptiste.barth@gmail.com (JB)</author>
      <description>&lt;p&gt;Que j&amp;#8217;aurais pu aussi sobrement appeler :&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;refaisons le match&lt;/li&gt;
	&lt;li&gt;massacre &amp;agrave; la tron&amp;ccedil;onneuse&lt;/li&gt;
	&lt;li&gt;f*ck&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yaml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;digest/md5&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;EvaFile&lt;/span&gt;
  attr_accessor &lt;span class=&quot;sy&quot;&gt;:path&lt;/span&gt;

  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;initialize&lt;/span&gt;(path)
    &lt;span class=&quot;iv&quot;&gt;@path&lt;/span&gt; = path
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;infos&lt;/span&gt;
    &lt;span class=&quot;iv&quot;&gt;@infos&lt;/span&gt; ||= {&lt;span class=&quot;sy&quot;&gt;:size&lt;/span&gt; =&amp;gt; &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.size(&lt;span class=&quot;iv&quot;&gt;@path&lt;/span&gt;).tap{|s| &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; s.to_s; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.dup&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; bytes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;; &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt; },
                &lt;span class=&quot;sy&quot;&gt;:last_modified&lt;/span&gt; =&amp;gt; &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.mtime(&lt;span class=&quot;iv&quot;&gt;@path&lt;/span&gt;),
                &lt;span class=&quot;sy&quot;&gt;:md5_sum&lt;/span&gt; =&amp;gt; &lt;span class=&quot;co&quot;&gt;Digest&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;MD5&lt;/span&gt;.hexdigest(&lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.read(&lt;span class=&quot;iv&quot;&gt;@path&lt;/span&gt;))}
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;EvaDir&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;initialize&lt;/span&gt;(subdir)
    raise &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Give me a (sub)directory !&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; subdir.nil? || !&lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.directory?(subdir)
    &lt;span class=&quot;iv&quot;&gt;@subdir&lt;/span&gt; = subdir
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;files&lt;/span&gt;
    &lt;span class=&quot;iv&quot;&gt;@files&lt;/span&gt; ||= &lt;span class=&quot;co&quot;&gt;Find&lt;/span&gt;.find(&lt;span class=&quot;iv&quot;&gt;@subdir&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |f|
                 &lt;span class=&quot;co&quot;&gt;Find&lt;/span&gt;.prune &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.directory?(f)
                 &lt;span class=&quot;co&quot;&gt;EvaFile&lt;/span&gt;.new(f) &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.file?(f)
               &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;.compact
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;write_info_file&lt;/span&gt;(filename)
    path = &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.join(&lt;span class=&quot;iv&quot;&gt;@subdir&lt;/span&gt;,filename)
    &lt;span class=&quot;r&quot;&gt;begin&lt;/span&gt;
      info = &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.open(path,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
    &lt;span class=&quot;r&quot;&gt;rescue&lt;/span&gt;
      &lt;span class=&quot;gv&quot;&gt;$stderr&lt;/span&gt;.puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Error opening file &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;path&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; for writing...&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
    info.write &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Size: &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;size&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; bytes&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    info.write &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Files: &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;nb_files&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    files_hash = {}
    files.each &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |file|
      files_hash.merge!(&lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.basename(file.path) =&amp;gt; file.infos)
    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
    info.write files_hash.to_yaml
    info.close_write
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;size&lt;/span&gt;
    &lt;span class=&quot;iv&quot;&gt;@size&lt;/span&gt; = files.inject(&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |memo, f|
              memo + f.infos[&lt;span class=&quot;sy&quot;&gt;:size&lt;/span&gt;]
            &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;nb_files&lt;/span&gt;
    files.length
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;EvaUtil&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;initialize&lt;/span&gt;(dir)
    raise &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Give me a directory !&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; dir.nil? || !&lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.directory?(dir)
    &lt;span class=&quot;iv&quot;&gt;@dir&lt;/span&gt; = dir
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;subdirs&lt;/span&gt;
    &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;iv&quot;&gt;@subdirs&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;iv&quot;&gt;@subdirs&lt;/span&gt;
    &lt;span class=&quot;iv&quot;&gt;@subdirs&lt;/span&gt; = [ &lt;span class=&quot;co&quot;&gt;EvaDir&lt;/span&gt;.new(&lt;span class=&quot;iv&quot;&gt;@dir&lt;/span&gt;) ]
    &lt;span class=&quot;iv&quot;&gt;@subdirs&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;co&quot;&gt;Find&lt;/span&gt;.find(&lt;span class=&quot;iv&quot;&gt;@dir&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |f|
                  &lt;span class=&quot;co&quot;&gt;EvaDir&lt;/span&gt;.new(f) &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.directory?(f)
                &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;iv&quot;&gt;@subdirs&lt;/span&gt; = &lt;span class=&quot;iv&quot;&gt;@subdirs&lt;/span&gt;.compact.uniq
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;generate_info_files&lt;/span&gt;(filename=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;infos.txt&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
    &lt;span class=&quot;iv&quot;&gt;@subdirs&lt;/span&gt;.each &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |s|
      s.write_info_file(filename)
    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;generate_meta_info_file&lt;/span&gt;(filename=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;metainfos.txt&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
    path = &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.join(&lt;span class=&quot;iv&quot;&gt;@dir&lt;/span&gt;,filename)
    &lt;span class=&quot;r&quot;&gt;begin&lt;/span&gt;
      meta = &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.open(path,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
    &lt;span class=&quot;r&quot;&gt;rescue&lt;/span&gt;
      &lt;span class=&quot;gv&quot;&gt;$stderr&lt;/span&gt;.puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Error opening file &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;path&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; for writing...&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
    meta.write &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Total size: &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;size&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; bytes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    meta.write &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Total number of files: &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;nb_files&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    meta.write &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Last modified (&amp;lt;24h) :&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;last_modified.join(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; last_modified.any?
    meta.close_write
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;last_modified&lt;/span&gt;
    &lt;span class=&quot;iv&quot;&gt;@subdirs&lt;/span&gt;.inject([]) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |memo, subdir|
      memo &amp;lt;&amp;lt; subdir.files.select{|f| &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.mtime(f) &amp;lt; &lt;span class=&quot;co&quot;&gt;Time&lt;/span&gt;.at(&lt;span class=&quot;co&quot;&gt;Time&lt;/span&gt;.now.to_i - &lt;span class=&quot;i&quot;&gt;86400&lt;/span&gt;)}.map(&amp;amp;&lt;span class=&quot;sy&quot;&gt;:path&lt;/span&gt;)
      memo.flatten
      memo
    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;

  private
  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;method_missing&lt;/span&gt;(symbol, *args)
    &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;%w(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;nb_files size&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;)&lt;/span&gt;&lt;/span&gt;.include?(symbol.to_s)
      &lt;span class=&quot;iv&quot;&gt;@subdirs&lt;/span&gt;.inject(&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |memo, subdir|
         memo + subdir.send(symbol)
      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;r&quot;&gt;super&lt;/span&gt;
    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;

e = &lt;span class=&quot;co&quot;&gt;EvaUtil&lt;/span&gt;.new(&lt;span class=&quot;pc&quot;&gt;ARGV&lt;/span&gt;[&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;])
e.generate_info_files
e.generate_meta_info_file&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Garanti 100% non test&amp;eacute;, 100% fait sans l&amp;#8217;API, &lt;strong&gt;et surtout 100% fait avec un &amp;eacute;diteur de texte&lt;/strong&gt;. C&amp;#8217;est s&amp;ucirc;rement bourr&amp;eacute; de conneries, mais au moins avec un truc comme &amp;ccedil;a j&amp;#8217;aurais pas eu honte. Cela dit vue la longueur, je commence &amp;agrave; me pardonner d&amp;#8217;avoir barbouill&amp;eacute; ma copie de blanco, c&amp;#8217;&amp;eacute;tait infaisable sans &amp;ccedil;a. Coder sur papier est d&amp;eacute;finitivement un cauchemard. On se la refait dans 2 ans ;-)&lt;/p&gt;</description>
      <category domain="/archives/tags/mylife">mylife</category>
      <category domain="/archives/tags/ruby">ruby</category>
      <category domain="/archives/tags/tech">tech</category>
      <category domain="/archives/tags/thoughts">thoughts</category>
    </item>
    <item>
      <title>Un shell en ruby ?</title>
      <link>/archives/2010/2/25/un_shell_en_ruby/</link>
      <pubDate>Thu, 25 Feb 2010 20:00:00 GMT</pubDate>
      <guid>/archives/2010/2/25/un_shell_en_ruby/</guid>
      <author>jeanbaptiste.barth@gmail.com (JB)</author>
      <description>&lt;p&gt;Dans 4 jours, je vais &lt;del&gt;me faire massacrer&lt;/del&gt; tenter un examen interne au boulot, cens&amp;eacute; valider mes aptitudes de &lt;em&gt;&amp;#8220;programmeur syst&amp;egrave;me&amp;#8221;&lt;/em&gt;. Cet examen comporte une &amp;eacute;preuve de d&amp;eacute;veloppement (sur papier, faut pas d&amp;eacute;conner), que la plupart des gens vont passer en Java ou C/C++. Mais tr&amp;egrave;s peu pour moi, j&amp;#8217;attaque en Ruby !&lt;/p&gt;
&lt;p&gt;Je lis donc des bouquins, qui pr&amp;eacute;sentent un squelette de shell en C. Et en Ruby ? Eh bien en fait, contre toute attente, c&amp;#8217;est super simple, voici un squelette fonctionnel :&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/ruby&lt;/span&gt;

require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;readline&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;open3&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Rshell&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;initialize&lt;/span&gt;
    loop &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;
      cmd = &lt;span class=&quot;co&quot;&gt;Readline&lt;/span&gt;.readline(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
      exit &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; cmd.nil? &lt;span class=&quot;r&quot;&gt;or&lt;/span&gt; cmd == &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;co&quot;&gt;Open3&lt;/span&gt;.popen3(cmd) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |stdin,stdout,stderr|
        &lt;span class=&quot;co&quot;&gt;STDOUT&lt;/span&gt;.print stdout.read
        &lt;span class=&quot;co&quot;&gt;STDERR&lt;/span&gt;.print stderr.read
      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;co&quot;&gt;Rshell&lt;/span&gt;.new&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Il ne faut pas s&amp;#8217;attendre &amp;agrave; des miracles, aucun builtin, pas de gestion du &lt;span class=&quot;caps&quot;&gt;PATH&lt;/span&gt;, mais on peut passer des commandes, diff&amp;eacute;rencier &amp;eacute;ventuellement &lt;span class=&quot;caps&quot;&gt;STDOUT&lt;/span&gt;/&lt;span class=&quot;caps&quot;&gt;STDERR&lt;/span&gt; pour le futur.&lt;/p&gt;
&lt;p&gt;Ca me donne l&amp;#8217;occasion de parler d&amp;#8217;un &lt;strong&gt;vrai&lt;/strong&gt; shell en Ruby, utilis&amp;eacute; chez Heroku, &lt;a href=&quot;http://adamblog.heroku.com/past/2008/2/19/rush_the_ruby_shell/&quot;&gt;Rush&lt;/a&gt;. J&amp;#8217;en reparlerai d&amp;egrave;s que j&amp;#8217;aurai test&amp;eacute; &amp;ccedil;a au quotidien au boulot :)&lt;/p&gt;</description>
      <category domain="/archives/tags/ruby">ruby</category>
      <category domain="/archives/tags/sysadmin">sysadmin</category>
      <category domain="/archives/tags/tech">tech</category>
    </item>
  </channel>
</rss>
