<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Shiny happy people coding]]></title>
  <link href="http://blog.shingara.fr/atom.xml" rel="self"/>
  <link href="http://blog.shingara.fr/"/>
  <updated>2013-04-07T10:16:49+02:00</updated>
  <id>http://blog.shingara.fr/</id>
  <author>
    <name><![CDATA[Cyril Mougel]]></name>
    <email><![CDATA[cyril.mougel@gmail.com]]></email>
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Release de public folder]]></title>
    <link href="http://blog.shingara.fr/release-public-folder.html"/>
    <updated>2013-04-06T09:49:00+02:00</updated>
    <id>http://blog.shingara.fr/release-public-folder</id>
    <content type="html"><![CDATA[<p>Depuis maintenant 1 semaine, je suis à la recherche d&#8217;un nouvel emploi.
Durant ma recherche d&#8217;emploi, on m&#8217;a fait une demande d&#8217;exercice en
Ruby. Étant un convaincu de l&#8217;open source et étant globalement fier de
ce que je peux produire, j&#8217;ai décidé de le sortir en open source.</p>

<p>Voici donc <a href="http://github.com/shingara/public_folder">Public Folder</a></p>

<p>Ce projet est extrêment simple, il s&#8217;agit d&#8217;une interface de gestion de
répertoires. À partir de la racine, on peut ainsi naviguer à travers une
arborescence que l&#8217;on peut créer soit même. On peut donc créer des
répertoires et uploader des fichiers directement dans l&#8217;application.</p>

<p>Le stockage des fichiers se fait directement sur disque dans la même
arborescence que celle définie dans l&#8217;application. Elle est juste comme
git, si vous créez un dossier dans l&#8217;application et qu&#8217;il ne contient
aucun fichier, le dossier ne sera pas créé sur le disque.</p>

<p>Au niveau de la navigation, l&#8217;url correspond à l&#8217;architecture du dossier
et on peut trier chaque liste par date/type/poids ou noms.</p>

<p>Pour réaliser cette application, la stack est full Rails, soit
ActionPack et ActiveRecord. J&#8217;ai juste utilisé <code>decent_exposure</code>,
<code>simple_form</code> et <code>draper</code> comme gems. Je ne peux plus du tout me passer
d&#8217;eux tellement ils sont devenu essentiel pour moi.</p>

<p>Ce projet est complétement testé. J&#8217;ai une couverture de
test de 99% selon
<a href="https://coveralls.io/r/shingara/public_folder">Coveralls</a>. Il a une note de 4
sur <a href="http://codeclimate.com/github/shingara/public_folder">CodeClimate</a>. Vous pouvez le voir aussi sur <a href="https://travis-ci.org/shingara/public_folder">Travis</a>.</p>

<p>Je ne compte pas continuer le développement de cette application. Je
n&#8217;en ai strictement aucun besoin. Par contre, je la laisse à la
postérité et aux lecteurs de code en tout genre.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[pourquoi j'ai arrêté decent_exposure]]></title>
    <link href="http://blog.shingara.fr/pourquoi-jai-arrete-decent-exposure.html"/>
    <updated>2012-07-04T09:49:00+02:00</updated>
    <id>http://blog.shingara.fr/pourquoi-jai-arrete-decent-exposure</id>
    <content type="html"><![CDATA[<p>A la sortie de
<a href="https://github.com/voxdolo/decent_exposure">decent_exposure</a>, j&#8217;ai été
très enthousiaste. J&#8217;utilisais avant
<a href="https://github.com/josevalim/inherited_resources/">inherited_ressources</a>, mais je
commençais à découvrir les problèmes de <code>inherited_resources</code>. La
personnalisation de son controller peut vite devenir compliqué et peux
lisible si on sort du cadre d&#8217;un controller qui soit plus qu&#8217;un CRUD
simple. On finissait par avoir un code moyennement
DRY et les test étaient loin d&#8217;être évident car impossible coté controller
( limitation indiqué dans le README lui-même ).</p>

<p>Le grand avantage que j&#8217;ai vu dans <code>decent_exposure</code> est la facilité
d&#8217;accès des variables dans les vues. Plus besoin de faire appel à des
instances. On appele simplement la méthode. Si celui-ci n&#8217;était pas
instancié alors <code>decent_exposure</code> le faisait pour nous. On obtenait ainsi un système beaucoup plus souple qui ne
chargeait les objets qu&#8217;au moment ou il était nécessaire. Un eager
loading intégré permettait d&#8217;éviter de rechercher en base plusieurs fois
le même objet. On pouvait aussi réutiliser plusieurs fois la même vue.
plus besoin de faire des assignations dans certaine action pour être sur
que l&#8217;objet existe. Il suffit juste d&#8217;exposer l&#8217;objet. Après on
l&#8217;utilise ou pas. De même l&#8217;utilisation des partials devient plus aisé
car, on peux surcharger facilement des variables par l&#8217;usage des
<code>locals</code>. J&#8217;y ai vu beaucoup d&#8217;intérêts.</p>

<p>Mais finalement cet intérêt n&#8217;existe que par l&#8217;usage de la méthode de
class d&#8217;un controller <code>helper_method</code>. Si on crée soit même sa propre
méthode avec son eager loading <code>decent_exposure</code> devient inutile.</p>

<p><code>decent_exposure</code> a été pour moi un révélateur de l&#8217;utilité de la
méthode <code>helper_method</code>. Mais à l&#8217;usage, je trouve qu&#8217;il fait
finalement trop de chose caché si on utilise la méthode d&#8217;appel <code>expose</code>
sans bloc. Je me suis ainsi retrouvé à faire des <code>update_attributes</code> 2
fois sur mon objet. Un dans le <code>decent_exposure</code> l&#8217;autre dans mon
action. Forcement ça posait quelques soucis. Quand on sait que cela peut
arriver, pas de soucis. Mais c&#8217;est toujours embêtant de perdre quelques
heures à débugger le problème quand on le voit. Sans compter les fois ou
on ne le voit pas.</p>

<p>Une des limitations de <code>decent_exposure</code> selon moi est l&#8217;override de
cette méthode. Parfois pour éviter les <code>if</code> infini dans cette méthode il
est plus judicieux de définir directement la valeur de retour de cette
méthode dans sa méthode d&#8217;action. Cela permet de savoir exactement ce
que retourne cette méthode, mais aussi d&#8217;éviter les conflits dans
d&#8217;autre action.</p>

<p>Pour réalisé cela ma méthode stocke en mémoisation la variable
d&#8217;instance égale au nom de la méthode. Ainsi ma méthode ressemble à ceci
:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">post</span>
</span><span class='line'>  <span class="vi">@post</span> <span class="o">||=</span> <span class="no">Post</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">params</span><span class="o">[</span><span class="ss">:id</span><span class="o">]</span><span class="p">)</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'><span class="n">helper_method</span> <span class="ss">:post</span>
</span></code></pre></td></tr></table></div></figure>


<p>Si je souhaite donc avoir un nouveau Post retourné par cette méthode
j&#8217;ai juste à faire :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">new</span>
</span><span class='line'>  <span class="vi">@post</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Je surcharge le retour de la méthode post par la valeur <code>Post.new</code>. Pour
faire cela avec <code>decent_exposure</code> il faut surchargé la variable
<code>@_resource[:post]</code>. Mais rien ne m&#8217;assure que ce nom de variable d&#8217;instance
soit conservé dans les futurs version de <code>decent_exposure</code>. Une solution serait peut-être de créer une
méthode <code>post=()</code> lors de l&#8217;exposition d&#8217;un <code>post</code>, mais cela devient
peut-être moins pratique.</p>

<p>Voilà donc les raisons de mon arrêt d&#8217;utilisation de <code>decent_exposure</code>.
Je peux très facilement émuler le comportement de <code>decent_exposure</code> et
tout ça sans aucune dépendance externe.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[tester ses vues rabl]]></title>
    <link href="http://blog.shingara.fr/tester-ses-vues-rabl.html"/>
    <updated>2012-06-28T09:40:00+02:00</updated>
    <id>http://blog.shingara.fr/tester-ses-vues-rabl</id>
    <content type="html"><![CDATA[<p>Personnelement, quand je fais des API, j&#8217;utilise le gem
<a href="https://github.com/nesquena/rabl">Rabl</a>. Je trouve ce gems vraiment
génial. Avant son utilisation, je faisais mes API json avec la méthode
<code>#to_json</code>. Mais pour ceux qui l&#8217;on utilisé, vous savez que c&#8217;est un
enfer à maintenir. Surtout si vous avez plusieurs type de représentation
de votre objet à différent endroit.</p>

<h1>Rabl la simplicité d&#8217;expression</h1>

<p>Pour gérer ses vues en JSON ou XML, les gems classique sont <code>JBuilder</code>
et <code>XmlBuilder</code>. Deux gems réalisées par DHH. Mais, personnelement, je
les trouves assez verbeuses comme vues. A contrario, Rabl a une syntaxe
trés simplifiée. On peux ausi avoir un système de partial qui permet une
réutilisation compléte. Petit bonus par rapport à JBuilder/XmlBuilder
est qu&#8217;il utilise la même vue pour générer du XML ou du JSON. Donc pas
besoin de faire plusieurs vues en fonction du format de sortie.</p>

<p>Voici un example de vue Rabl :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">object</span> <span class="vi">@post</span>
</span><span class='line'><span class="n">attribute</span> <span class="ss">:content</span>
</span><span class='line'><span class="n">child</span><span class="p">(</span><span class="ss">:author</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">attribute</span> <span class="ss">:firstname</span><span class="p">,</span> <span class="ss">:lastname</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<h1>Tester sa vue Rabl</h1>

<p>Pour tester le résultat de cette vue Rabl, deux possibilités s&#8217;offre à
nous. Un test de la génération de la vue par un test d&#8217;intégration
couplé avec le test du controller, soit un test de la vue. Finalement
tester une vue Rabl c&#8217;est ni plus ni moins que tester un retour de la
méthode <code>#to_json</code>. Donc si nous testons notre vue directement à partir
des données passées, c&#8217;est plus rapide et plus unitaire.</p>

<p>Depuis la version 0.6.0 de Rabl, une méthode permet de générer la vue
directement. C&#8217;est cela que nous allons utiliser pour faire notre test
de vue.</p>

<p>Voici donc un test de notre vue ( défini dans
<code>spec/views/posts/show_rabl_spec.rb</code> )</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s1">&#39;spec_helper&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="n">describe</span> <span class="s2">&quot;blogs/show.rabl&quot;</span> <span class="k">do</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">let</span><span class="p">(</span><span class="ss">:auhor</span><span class="p">)</span> <span class="p">{</span> <span class="no">Author</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="ss">:firstname</span> <span class="o">=&gt;</span> <span class="s1">&#39;Cyril&#39;</span><span class="p">,</span> <span class="ss">:lastname</span> <span class="o">=&gt;</span> <span class="s1">&#39;Mougel&#39;</span><span class="p">)</span> <span class="p">}</span>
</span><span class='line'>    <span class="n">let</span><span class="p">(</span><span class="ss">:blog</span><span class="p">)</span> <span class="p">{</span> <span class="no">Blog</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="ss">:content</span> <span class="o">=&gt;</span> <span class="s1">&#39;hello&#39;</span><span class="p">,</span> <span class="ss">:author</span> <span class="o">=&gt;</span> <span class="n">author</span><span class="p">)</span> <span class="p">}</span>
</span><span class='line'>    <span class="n">let</span><span class="p">(</span><span class="ss">:valid_json</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="p">{</span>
</span><span class='line'>        <span class="ss">:content</span> <span class="o">=&gt;</span> <span class="n">blog</span><span class="o">.</span><span class="n">content</span><span class="p">,</span>
</span><span class='line'>        <span class="ss">:author</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>          <span class="ss">:firstname</span> <span class="o">=&gt;</span> <span class="n">author</span><span class="o">.</span><span class="n">firstname</span><span class="p">,</span>
</span><span class='line'>          <span class="ss">:lastname</span> <span class="o">=&gt;</span> <span class="n">author</span><span class="o">.</span><span class="n">lastname</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>      <span class="p">}</span><span class="o">.</span><span class="n">to_json</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">let</span><span class="p">(</span><span class="ss">:render</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="no">Rabl</span><span class="o">.</span><span class="n">render</span><span class="p">(</span>
</span><span class='line'>        <span class="n">blog</span><span class="p">,</span>
</span><span class='line'>        <span class="s1">&#39;blog/show&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="ss">:view_path</span> <span class="o">=&gt;</span> <span class="s1">&#39;app/views&#39;</span>
</span><span class='line'>      <span class="p">)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">it</span> <span class="s1">&#39;should render valid_json&#39;</span> <span class="k">do</span>
</span><span class='line'>      <span class="n">render</span><span class="o">.</span><span class="n">should</span> <span class="n">eql</span><span class="p">(</span><span class="n">valid_json</span><span class="p">)</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>On obtient ainsi un test unitaire vraiment simple et une validation
compléte du json obtenu. Le test est vraiment très rapide et n&#8217;est pas
pollué par le test du controller.</p>

<p>J&#8217;ai par contre découvert des limitations à ce test car, on ne peux
passer à la méthode <code>#render</code> que les objects définis par <code>object</code> ou
<code>collection</code>. Si on veux tester une vue rabl qui utilise plusieurs
variables, la tâche devient très hardu. J&#8217;ai donc commencé à proposer un
<a href="https://github.com/nesquena/rabl/pull/269">Pull Request</a> pour passer directement des variables dans sa vue Rabl, de
la même méthode que les partials avec l&#8217;options <code>:locals</code>. Vous pouvez
la <a href="https://github.com/nesquena/rabl/pull/269">suivre sur github</a></p>

<p><a href="http://blog-en.shingara.fr/test-your-rabl-view.html">English translation</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[vundle ou le bundler de vim]]></title>
    <link href="http://blog.shingara.fr/vundle-ou-le-bundler-de-vim.html"/>
    <updated>2012-05-24T09:40:00+02:00</updated>
    <id>http://blog.shingara.fr/vundle-ou-le-bundler-de-vim</id>
    <content type="html"><![CDATA[<p>Personnellement, j&#8217;utilise vim comme éditeur de texte depuis mon
école. J&#8217;ai toujours apprécié vim et je ne compte toujours pas changer
d&#8217;éditeur.</p>

<h1>Mon évolution de la gestions des plugins vim.</h1>

<p>Vim a une très grande quantité de plugins disponibles et il est très
rapidement indispensable d&#8217;en utiliser plusieurs. La gestion des plugins
est donc très importante. Au fil des années, j&#8217;ai changé de technique en
fonction des possibilités apportées par vim ou par les développeurs.</p>

<h2>Gestion manuelle</h2>

<p>Au début, je gérais manuellement mes plugins en les ajoutant dans les
dossiers correspondant. Je versionnais mon dossier <code>.vim</code> et <code>.vimrc</code> et je pouvais le faire
évoluer globalement. Le soucis de cette technique est qu&#8217;il est pas
forcement évident de gérer les mises à jour des plugins et leur
installation n&#8217;est pas forcement simple car il faut mettre plusieurs
fichiers à plusieurs endroits.</p>

<h2>L&#8217;arrivée des vimballs</h2>

<p>Dans une évolution de vim, il y a eu la possibilité de gérer des
vimballs. L&#8217;avantage de cette technique est qu&#8217;on avait moins de
problème lors de l&#8217;installation et on pouvait gérer un peu plus
facilement les mises à jour car on savait rapidement quelle version on
utilisait. Mais la encore il fallait allez régulièrement sur
vimscript.org
pour voir si nos plugins avaient changé de version. Chose que finalement
on faisait très peu au final.</p>

<h2>Gestion par git-submodule</h2>

<p>Avec l&#8217;arrivée de github, les choses ont pu changer. Les plugins vim ont
commencé à avoir un dépôt centralisé, on pouvait suivre directement
l&#8217;évolution des scripts. Même vimscript a converti tous les plugins
qu&#8217;il hébergeait en repository git. Maintenant on peux gérer tous ses plugins
en faisant des mises à jour de repository git. J&#8217;ai ainsi commencé a gérer des
submodule et des liens symboliques vers ces submodules. La mise à jour
était automatique, mais l&#8217;installation devenait encore plus compliqué
qu&#8217;avant.</p>

<h2>Janus, la distribution vim</h2>

<p>C&#8217;est alors que Yehuda Katz et Carl Lerche ont commencé à créer
<a href="https://github.com/carlhuda/janus">janus</a>. Ce projet se veut comme une
distribution de gestion de plugins vim. Il contient un jeu de tâche rake
qui permette de mettre à jour facilement ses plugins. Un <code>.vimrc</code> est aussi
fourni pour utiliser les plugins par défaut et ajouter une configuration
minimal pratique. Ce projet est vraiment génial pour commencer à
pratiquer vim. On peux ainsi avoir un jeu de plugins pratique et
intéressant. Par contre, la gestion des versions de janus avec ses
propres usage peux vite devenir compliquée. En gros c&#8217;est bien si on ne veut
jamais modifier sa conf vim.</p>

<h2>Pathogen, le premier plugin vim de gestions de ses plugins</h2>

<p>Très peu de temps après <a href="https://github.com/tpope">Tim Pope</a> ( très prolifique développeur de plugins
vim ) a sorti <a href="https://github.com/tpope/vim-pathogen">Pathogen</a>. Ce
plugin permet de gérer directement la gestion de ses plugins dans son vimrc. J&#8217;avoue ne pas avoir
trop regardé comment fonctionne ce plugin. On m&#8217;en a toute fois dit du
bien. Il y a eu pas mal de projet pour que janus utilise pathogen
typiquement.</p>

<h2>Vundle, le bundler de vim.</h2>

<p>Mais c&#8217;est là qu&#8217;on m&#8217;a parlé du plugin qui me semble le meilleur
actuellement concernant la gestion de ses plugins vim,
<a href="https://github.com/gmarik/vundle">Vundle</a>. Comme pathogen, la gestion
des plugins est faite directement dans son vimrc. Son usage y est très
simplifié et pratique. Si vous connaissez
<a href="http://gembundler.org">Bundler</a> alors vous comprendrez facilement sont
usage car il en est très inspirés.</p>

<h1>Utilisation de Vundle</h1>

<h2>Installation de Vundle</h2>

<p>Pour installer vundle, un simple clone du repository du projet et 2
lignes dans votre <code>.vimrc</code> suffisent.</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='vim'><span class='line'><span class="k">set</span> <span class="nb">rtp</span><span class="p">+=~</span><span class="sr">/.vim/</span>bundle<span class="sr">/vundle/</span>
</span><span class='line'><span class="k">call</span> vundle#rc<span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Configuration de ses plugins</h2>

<p>Pour utiliser vundle une fois installé. C&#8217;est extrêmement simple. il
suffit d&#8217;utiliser la commande <code>Bundle</code> et le chemin de votre plugin.
Ainsi pour installer le plugin <code>vim-rails</code> il suffit juste de faire :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='vim'><span class='line'>Bundle <span class="s1">&#39;tpope/vim-rails.git&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Installation de ses plugins</h2>

<p>Ensuite, une fois votre vim lancé deux commandes vous suffisent.
<code>BundleInstall</code> qui permet d&#8217;installer tous les plugins que vous avez
définis et <code>BundleInstall!</code> qui permet de les mettre à jour.</p>

<p>Désormais ils ne vous reste plus qu&#8217;à trouver les plugins que vous
souhaitez et les utiliser.</p>

<h1>Mon vimrc</h1>

<p>Si vous souhaitez découvrir mon usage de vim, <a href="https://github.com/shingara/vim-conf">mon vimrc est ainsi
disponible sur github</a>. Grâce à
Vundle rien de plus simple que de le lire et découvrir rapidement les
plugins vim que j&#8217;utilise.</p>

<p><a href="http://blog-en.shingara.fr/vundle-the-bundler-of-vim.html">English Translation</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[dante pour mettre du daemon dans son code]]></title>
    <link href="http://blog.shingara.fr/dante-pour-mettre-du-daemon-dans-son-code.html"/>
    <updated>2012-05-09T09:43:00+02:00</updated>
    <id>http://blog.shingara.fr/dante-pour-mettre-du-daemon-dans-son-code</id>
    <content type="html"><![CDATA[<p>J&#8217;ai dernièrement eu besoin de convertir un petit script ruby en daemon.</p>

<p>J&#8217;utilise dans mes déploiements monitrc pour le monitoring de mes
scripts. Monit check un pidfile pour voir si le processus est actif ou
pas.</p>

<p>J&#8217;ai donc cherché en Ruby quel était la meilleure solution pour que mon
script soit un daemon et puisse générer lui-même son pidfile.</p>

<p>Le projet le plus connu est <a href="http://daemons.rubyforge.org/">daemons</a>.
J&#8217;ai déjà essayé de l&#8217;utiliser, mais je n&#8217;en ai jamais été un grand
convaincu. Je l&#8217;ai toujours trouvé compliqué. Il ne gére pas la
génération de pidfile. Il faut donc pratiquement tout gérer soit même.</p>

<p>Le deuxième projet le plus connu est une sur-couche de daemons c&#8217;est
<a href="https://github.com/kennethkalmer/daemon-kit">daemon-kit</a>. J&#8217;avais déjà
tenté de l&#8217;utiliser, mais je le trouve vraiment trop rigide pour un
simple script. C&#8217;est selon moi plus une massue qu&#8217;autre chose pour créer
un daemon.</p>

<p>C&#8217;est alors que je me suis rappelé avoir entendu parlé d&#8217;un nouveau gem
pour créer des daemons. J&#8217;ai cherché et j&#8217;ai ainsi pu découvrir
<a href="https://github.com/bazaarlabs/dante">dante</a>. Ce projet est exactement
ce que je cherchais. Il est simple et fait le boulot de créer un daemon.</p>

<p>Par défaut, il supporte quelques arguments à passer en ligne de
commande. Ces arguments font l&#8217;essentiel du travail d&#8217;un daemon.</p>

<p>Voici une liste des arguments par défaut disponible.</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>-p, --port PORT           Specify port
</span><span class='line'>                          (default: )
</span><span class='line'>-P, --pid FILE            save PID in FILE when using -d option.
</span><span class='line'>                          (default: /var/run/scheduler.pid)
</span><span class='line'>-d, --daemon              Daemonize mode
</span><span class='line'>-l, --log FILE            Logfile for output
</span><span class='line'>-k, --kill [PORT]         Kill specified running daemons - leave
</span><span class='line'>blank to kill all.
</span><span class='line'>-u, --user USER           User to run as
</span><span class='line'>-G, --group GROUP         Group to run as
</span><span class='line'>-?, --help                Display this usage information.</span></code></pre></td></tr></table></div></figure>


<p>On peux ainsi définir, le PID, le fichier de log, l&#8217;utilisateur et le
group lançant le daemon ( si lancé en root ). Seul petit argument qui ne
me semble pas essentiel, c&#8217;est l&#8217;argument du port. Mais l&#8217;usage initial
de dante est de lancé des applications rack. Voila pourquoi on
retrouve cet argument.</p>

<p>Une de ses autre fonctionnalités intéressantes est tout simplement le
fait que l&#8217;on peux ajouter des options. Il peux donc aussi servir de
gestion d&#8217;option pour son application.</p>

<p>Pour l&#8217;utiliser rien de plus simple. Il suffit de mettre votre script
dans un block <code>Dante.run</code></p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">Dante</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s1">&#39;myapp&#39;</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">opts</span><span class="o">|</span>
</span><span class='line'>  <span class="n">myapp</span><span class="o">.</span><span class="n">run</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Je suis vraiment impressionné par ce gem qui est issu de la société
<a href="http://gomiso.com">gomiso</a>. Merci à elle de nous permettre d&#8217;avoir
d&#8217;aussi bon gem.</p>

<p><a href="http://blog-en.shingara.fr/dante-lets-you-put-some-daemon-in-your-code.html">English Translation</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[moped le nouveau driver mongodb pour ruby]]></title>
    <link href="http://blog.shingara.fr/moped-le-nouveau-driver-mongodb-pour-ruby.html"/>
    <updated>2012-04-30T09:42:00+02:00</updated>
    <id>http://blog.shingara.fr/moped-le-nouveau-driver-mongodb-pour-ruby</id>
    <content type="html"><![CDATA[<p>Depuis décembre 2011, <a href="https://github.com/bernerdschaefer">Bernerd Schaefer</a> a commencé a créer un
driver MongoDB pour ruby. Ce nouveau driver MongoDB n&#8217;a pas été crée par
10Gen (créateur de MongoDB) contrairement au gem
<a href="https://github.com/mongodb/mongo-ruby-driver">mongo-ruby-driver</a>.</p>

<h1>Le but de ce gem</h1>

<p>Ce gem a été crée suite aux frustrations de l&#8217;équipe de développement de
Mongoid qui a fait plusieurs fois des propositions de changement de
design du driver officiel. Tous changement de design du driver a été
refusé.</p>

<h2>Thread-safe</h2>

<p>Un des buts de ce gem est de permettre d&#8217;avoir un gem qui est le plus
possible thread-safe. Le driver officiel mongoDB est parfois considéré
comme non thread-safe notament par <a href="https://github.com/mperham/sidekiq/wiki/Problems-and-Troubleshooting">Mike Perham</a>.
C&#8217;est un vrai problème alors que la communauté ruby
commence enfin à redécouvrir les threads. Cet état empêche par exemple
l&#8217;usage de <a href="http://mperham.github.com/sidekiq/">sidekiq</a> avec MongoDB.</p>

<h2>Suppression de l&#8217;extension</h2>

<p>Avec le driver MongoDB officiel, il est très fortement conseillé
d&#8217;installer le gem <a href="http://rubygems.org/gems/bson_ext">bson_ext</a> sans
celui-ci les performances sont beaucoup moins bonnes. Par contre cette
extension étant écrite en C, elle est incompatible avec JRuby. Il a
fallu créer une version JRuby du gem bson. Ça rend la maintenabilité
plus complexe.</p>

<p>Dans le cas de moped, aucune extension C n&#8217;est à prévoir.
Il est naturellement plus performant. Il arriverait même à être plus
performant que l&#8217;extension C selon
les benchmarks réalisés pour le projet.</p>

<p>Seul ombre au tableau, la génération d&#8217;un ObjectId est plus lente avec
moped qu&#8217;avec le gem officiel bson selon un <a href="https://groups.google.com/d/topic/mongoid/87IdIKO8-VM/discussion">thread de la mailing-list de Mongoid</a>.
Mais cela pourra être améliorer par la suite, je n&#8217;en doute pas.</p>

<h2>Une API plus simple</h2>

<p>L&#8217;API de moped est vraiment plus belle que celle du gem mongo. Ce
changement est bien sûr subjectif. Elle est beaucoup plus orienté ruby.
Elle permet aussi la combinaison de recherche/mise à jour.</p>

<h2>Meilleure gestion du replicat Set</h2>

<p>Une des fonctionnalités principale de MongoDB est la gestion du
replicatSet. Avec Moped, cette gestion devient vraiment plus souple et
surtout ne lève plus d&#8217;exception la première fois que le node maître est
down. Cette fois ci le basculement se fait automatiquement.</p>

<p>Plus besoin de passer la liste de vos nodes en configuration. Moped
utilise directement les mécanismes de MongoDB pour découvrir les
nouveaux nodes et ainsi les utiliser.</p>

<h1>Les limitations</h1>

<p>Par contre, moped a certaine limitation.</p>

<h2>Ruby 1.9 uniquement</h2>

<p>Moped n&#8217;est pas compatible avec Ruby &lt; 1.9. Le choix de l&#8217;implémentation
a été fait de ne pas être compatible avec les plus anciennes version de
ruby.</p>

<p>Personnellement, je suis d&#8217;accord avec ce choix, car l&#8217;usage de ruby 1.8
doit disparaitre.</p>

<h2>Pas de support de GridFS</h2>

<p>GridFS n&#8217;est pas supporté nativement dans moped. Ce choix a été fait
pour limiter le core du gem. Bien sûr rien n&#8217;empêche de créer une
extension de moped gérant GridFS.</p>

<h1>Intégration dans Mongoid 3</h1>

<p>Mongoid 3.x utilisera désormais moped à la place du driver mongodb de
10Gen. Si vous souhaitez donc commencer un peu à l&#8217;utiliser essayer
cette nouvelle version majeur de Mongoid.</p>

<p>Attention, Mongoid 3 n&#8217;est actuellement pas release. Si vous souhaitez
l&#8217;utiliser il faudra utiliser la branche master de Mongoid. Le
dévelopment y est toujours actif.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">gem</span> <span class="s1">&#39;mongoid&#39;</span><span class="p">,</span> <span class="ss">:git</span> <span class="o">=&gt;</span> <span class="s1">&#39;git://github.com/mongoid/mongoid&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<p><a href="http://blog-en.shingara.fr/moped-the-new-mongodb-ruby-driver.html">English Translation</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Quiet Assets le gem qui limite les logs]]></title>
    <link href="http://blog.shingara.fr/quiet-assets-le-limiteur-de-log.html"/>
    <updated>2012-04-25T09:42:00+02:00</updated>
    <id>http://blog.shingara.fr/quiet-assets-le-limiteur-de-log</id>
    <content type="html"><![CDATA[<p>Voici une semaine, j&#8217;ai découvert un gem vraiment pratique.
<a href="https://github.com/evrone/quiet_assets">quiet_assets</a>.</p>

<p>Ce gems ne fait pas grand chose, mais a de grand avantage quand on
développe une application Rails (> 3.1) avec des assets en utilisant la
technologie &#8216;asset_pipeline&#8217;.</p>

<p>Si c&#8217;est votre cas, vous vous êtes déjà rendu compte que chaques requêtes faites
à votre application pour obtenir vos assets est logués dans votre
fichier de log ( development.log en environement de dévelopment ). Des
requêtes comme celle-ci :</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>Started GET "/assets/application.js?body=1" for 127.0.0.1 at 2012-02-13 13:24:04 +0400
</span><span class='line'>Served asset /application.js - 304 Not Modified (8ms)</span></code></pre></td></tr></table></div></figure>


<p>On se retrouve ainsi à devoir remonter dans son fichier de logs pour
obtenir les logs qui nous interresse vraiment ( les log de la requête
courante ). Notre fichier de log est
vraiment pollué par ces assets si vous en avez comme moi beaucoup.</p>

<p>C&#8217;est là que <a href="https://github.com/evrone/quiet_assets">quiet_assets</a>
devient vraiment interressant et pratique. Vous ajoutez ce gem dans
votre Gemfile au niveau du groupe &#8216;development&#8217; et tous vos logs d&#8217;assets
disparaissent. Ils ne sont tous simplement plus logguées dans votre fichier
de log. On retrouve ainsi un fichier de log rapide a consulter et moins
pollué par des informations inutiles.</p>

<p>Comme quoi de tout petits gems peuvent nous rendre de grand service.</p>

<p><em>Edit du 27 Avril 2012</em></p>

<p>On pourrait se dire que cela pourrait être directement integré à Rails.
Hélas cela à été fait en partie, mais pas complétement.</p>

<p>Depuis la version 3.2.x et l&#8217;<a href="https://github.com/rails/rails/issues/2639">issue 2639</a>
nous pouvons configurer le logger de Sprockets. Mais il n&#8217;est pas seul à
afficher les informations. Actionpack log toujours les requêtes faites
pour obtenir ces assets. Vous ne pourrez donc pas avoir un fichier de
log complétement épuré.</p>

<p><a href="http://blog-en.shingara.fr/quiet-assets-help-you-to-have-little-log.html">English translation</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Récupération de ses fichiers sur basecamp]]></title>
    <link href="http://blog.shingara.fr/telecharger-fichier-de-basecamp.html"/>
    <updated>2012-04-20T09:38:00+02:00</updated>
    <id>http://blog.shingara.fr/telecharger-fichier-de-basecamp</id>
    <content type="html"><![CDATA[<p>Au niveau de mon travail actuel chez <a href="http://bemyboat.com">Be My Boat</a>,
nous sommes actuellement en train de migrer de
<a href="http://basecamphq.com">Basecamp</a> vers
<a href="http://trello.com">Trello</a>.</p>

<p>Pour éviter de perdre toutes les informations qui ont été mis dans
basecamp, nous avons réalisé un import complet. Par contre, l&#8217;import ne
comprend pas les fichiers qui ont pu être ajouté dans basecamp.</p>

<p>Pour ne pas perdre ces fichiers qui font parti du patrimoine de
l&#8217;entreprise, j&#8217;ai créé un petit script pour télécharger tous ces
fichiers.</p>

<p>Je vous le partage si vous en avez besoin un jour.</p>

<div><script src='https://gist.github.com/2420838.js?file='></script>
<noscript><pre><code></code></pre></noscript></div>


<p>Dans ce script j&#8217;utilise
<a href="https://github.com/technoweenie/faraday">Faraday</a> pour faire le requêtage avec l&#8217;API et
aussi télécharger les fichiers. Je suis personnellement un grand fan de
Faraday. C&#8217;est selon moi la meilleure librairie de requêtage HTTP
actuelle du monde Ruby. Utilisez la dès que vous avez besoin de faire du
requêtage HTTP.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Localize avec mongoid]]></title>
    <link href="http://blog.shingara.fr/translate-on-mongoid.html"/>
    <updated>2012-02-06T22:02:00+01:00</updated>
    <id>http://blog.shingara.fr/translate-on-mongoid</id>
    <content type="html"><![CDATA[<p>Depuis la version 2.4.0 de <a href="http://mongoid.org">Mongoid</a>, une nouvelle
fonctionnalité à été ajoutée très discrétement. C&#8217;est tout simplement la
gestion native des traductions en base.</p>

<p>La <a href="http://mongoid.org/docs/documents/localized.html">documentation compléte</a> de cette fonctionnalité est sur le site de
<a href="http://mongoid.org">mongoid</a>.</p>

<p>Grâce à cette fonctionnalité, on peut définir tout simplement qu&#8217;un
champs de Mongoid est localizable. La gestion de la locale est faite de
manière très intelligente et surtout en complète coordination avec
MongoDB.</p>

<p>Contrairement à une gestion de traduction dans une Base de donnée
relationnelle, qui créé une table de liaison, Mongoid stocke un hash
avec la locale comme clé et la traduction comme valeur.</p>

<p>Mongoid n&#8217;a plus qu&#8217;à faire la glue entre le système pour que les accès
en lecture/écriture en fonction de la locale et la recherche</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Mailtrap l'aide au staging]]></title>
    <link href="http://blog.shingara.fr/mailtrap-l-aide-au-staging.html"/>
    <updated>2012-01-24T22:17:00+01:00</updated>
    <id>http://blog.shingara.fr/mailtrap-l-aide-au-staging</id>
    <content type="html"><![CDATA[<p>Avant chaque mise en production d&#8217;un projet, il faut le test dans un
environement de staging. Pour avoir un environement le plus proche de
notre environement de production, une pratique courante est d&#8217;éffectuer
un dump de la base de production pour avoir un jeu de donnée complet et
valide. Ça nous permet aussi de vérifier que nos migrations ne posent
pas de problème, tester quelques pages au niveau de leur performance.</p>

<p>En gros faire plein de test comme si on jouait avec la prod mais sans
toucher au donnée de production.</p>

<p>Le plus gros soucis que l&#8217;on rencontre et beaucoup d&#8217;entre nous l&#8217;ont
rencontré, c&#8217;est l&#8217;envoi d&#8217;email. Tous les emails copié de la production
sont valide et posséde un utilisateur au bout. Si nous envoyons un email
réellement cela peut vite être problèmatique. Les solutions utilisées
généralement sont les suivantes.</p>

<h2>Remplacement de tous les emails de la base de donnée.</h2>

<p>Une pratique simple est courant est la tâche qui remplace tous les
emails de la base de donnée par des emails possédés par la société.
Cette technique marche parfaitement, mais pose quelques problèmes :</p>

<ul>
<li>Il faut penser a toujours faire la modification après chaque copie de
la base de production.</li>
<li>Il faut mettre à jour son script pour remplacer tous les nouveaux
champs qui posséde des emails si on en ajoute</li>
<li>Il devient difficile de savoir à qui était réelement destiné l&#8217;email
initial. On peux ainsi passer à coté de quelques bugs.</li>
</ul>


<h2>Ne plus contacter de serveur SMTP et créer un fichier par email</h2>

<p>Avec le framework Ruby on Rails, il est possible de définir que tous les
emails envoyés sont mis dans un fichier plutôt qu&#8217;envoyer par SMTP. Il
suffit de définir un nouveau smtp_delivery</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">ActionMailer</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">delivery_methods</span> <span class="o">=</span> <span class="ss">:file</span>
</span></code></pre></td></tr></table></div></figure>


<p>Cette technique permet d&#8217;être sûr qu&#8217;aucun email n&#8217;est envoyé au client
finaux. L&#8217;inconvénient de cette technique est le stockage et la lecture
des emails. Tous les emails sont stocké sous forme de fichier
directement sur le serveur. Il peux donc être fastidieux de connaitre
les nouveaux emails envoyés, car ils sont classé par destinataire. On
peux ainsi ne pas constater qu&#8217;un email est envoyé sous certaine
conditions. De même, si votre application est utilisé par des personnes
n&#8217;ayant pas un accès shell à votre serveur, ils ne pourront pas lire les
mails envoyés.</p>

<h2>Le mock SMTP</h2>

<p>Cette technique est selon moi la meilleure actuellement. Elle consiste
tout simplement à emuler un vrai serveur SMTP. Par contre, ce serveur ne
transmet pas les emails qu&#8217;il reçoit. Il les stocke et vous permet de
les consulter dans un client mail classique. Ils sont conservé
entièrement.</p>

<p>L&#8217;avantage est que n&#8217;importe qui peux consulter les emails générés, sans
aucune connaissance technique évolués et ils sont conservé entièrement.</p>

<p>A ma connaissance, il existe 3 produits qui permettent cela.</p>

<ul>
<li><a href="http://mailcatcher.me/">Mailcatcher</a></li>
<li><a href="http://mailtrap.io/">Mailtrap.io</a></li>
<li><a href="http://mocksmtpapp.com/">MockSMTP.app</a></li>
</ul>


<h3>Mailcatcher</h3>

<p>C&#8217;est un produit open source tres simple d&#8217;utilisation. Vous télécharger
le gem, vous lancer la commande <code>mailcatcher</code> et c&#8217;est fini. Vous avez
ainsi un serveur SMTP sur le port 1025 et un client mail sur le port
1080.</p>

<p>Je vous le conseille dans un environement de développement. Il a en plus
quelques petits addons comme la notification growl.</p>

<p>Le seul soucis que j&#8217;ai rencontré avec est le deployement dans un
environement de staging. la commande <code>mailcatcher</code> ne permet pas
d&#8217;écouter sur toutes les interfaces. Il faut donc mettre un proxy devant
pour le rendre accessible à tout le monde. On doit donc le maintenir et
le gérer. Cela peux être un peu compliqué juste pour un simple mock.
Bien sûr rien ne vous empêche de le faire.</p>

<h3>Mailtrap.io</h3>

<p>Voici un projet que j&#8217;ai découvert que très récement. Le concept est
exactement le même que celui de mailcatcher, sauf que vous n&#8217;avez plus à
gérer l&#8217;hébergement vous même. Tout est géré par
<a href="http://railsware.com/">railsware</a>, l&#8217;éditeur de ce service.</p>

<p>Vous créer un compte sur leur site, vous créer un serveur SMTP fictif et
c&#8217;est fini.</p>

<p>Vous obtenez les informations de connection à ce SMTP. Une fois que vous
définissez ces paramètres dans votre application, tous les emails seront
envoyé directement à Mailtrap.</p>

<p>Une gestion de collaboration sur les mailbox vous permet d&#8217;ajouter vos
collaborateur à cette mailbox pour qu&#8217;ils puissent voir les emails.</p>

<p>Cette solution est vraiment simple a mettre en oeuvre et très pratique.
Petit plus, c&#8217;est encore gratuit actuellement. Donc profitez en.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Une journée dédiée à MongoDB]]></title>
    <link href="http://blog.shingara.fr/une-journee-dediee-i-mongodb.html"/>
    <updated>2010-05-19T00:00:00+02:00</updated>
    <id>http://blog.shingara.fr/une-journee-dediee-i-mongodb</id>
    <content type="html"><![CDATA[<p><img src="http://blog.shingara.fr/files/badge-mongofr-large.png" alt="mongoFR badges"/></p>

<p>Le 21 Juin se tiendra à Paris un événement auquel je vous invite à venir. Cet événement sera dédié à <a href="http://mongodb.com">MongoDB</a>, le <a href="http://www.10gen.com/conferences/event_mongofr_21june10">MongoFR</a>.</p>

<p>J&#8217;ai la chance de pouvoir proposer une petite conférence sur un retour d&#8217;expérience : ma migration de SQL à MongoDB sur <a href="http://oupsnow.rubyforge.org">Oupsnow</a>.
Hormis les développeurs de <a href="http://10gen.com">10Gen</a>, il n&#8217;y aura que des Rubyists.</p>

<p>Selon moi, cette nouvelle technologie qu&#8217;est MongoDB est assez prometteuse.</p>

<p>Pour découvrir MongoDB, venez nombreux <a href="http://www.10gen.com/conferences/event_mongofr_21june10">le 21 Juin</a> !</p>

<p><a href="http://blog-en.shingara.fr/one-day-dedicated-to-mongodb.html">English translation</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[PeriodicTimer de EventMachine, le cron simplifié]]></title>
    <link href="http://blog.shingara.fr/periodictimer-de-eventmachine-le-cron-simplifie.html"/>
    <updated>2010-03-27T00:00:00+01:00</updated>
    <id>http://blog.shingara.fr/periodictimer-de-eventmachine-le-cron-simplifie</id>
    <content type="html"><![CDATA[<p><a href="http://rubyeventmachine.com/">EventMachine</a> est une des meilleures librairies Ruby,
tout en étant une des plus sous-estimées et mal connues.</p>

<p>J&#8217;ai donc commencé à regarder un peu dans quels cas utiliser EventMachine.
La première application que j&#8217;en ai trouvé c&#8217;est tout simplement le <a href="http://eventmachine.rubyforge.org/EventMachine/PeriodicTimer.html">PeriodicTimer</a>.</p>

<p>Son utilisation la plus simple est le remplacement d&#8217;une cronjob.</p>

<p>Je m&#8217;explique : une cronjob est vraiment une très bonne chose. On peut définir très précisément l&#8217;heure à laquelle on souhaite qu&#8217;une tâche s&#8217;exécute. Celle-ci s&#8217;exécute alors à ce moment précis. Cron est vraiment un outil magnifique. Cependant, dans
le cas d&#8217;une tâche récurrente qui doit être effectuée régulièrement, l&#8217;utilisation d&#8217;un cronjob peut avoir un gros inconvénient.</p>

<p>Cron n&#8217;a aucune gestion de queue. Ainsi on peut se retrouver très simplement avec une quantité astronomique de tâches essayant de s&#8217;exécuter en même temps. Votre « load » explose et il faut redémarrer votre serveur. Bien sûr cela n&#8217;arrive que si vous lancez une tâche plus fréquemment que son temps d&#8217;exécution.</p>

<p>La seule solution serait d&#8217;avoir une petite application - comme : <a href="http://forge.bearstech.com/trac/wiki/JobQueue">jobq</a> - qui gére pour vous un système de queue. Bien sûr, si le fait d&#8217;avoir une queue ne sert strictement à rien, cette solution peut être un peu overkill.</p>

<p>L&#8217;avantage de PeriodicTimer est que les tâches sont exécutées après un temps défini. Il n&#8217;y a aucune gestion d&#8217;heure de lancement. Il y a juste un lancement de la tâche après X secondes une fois que la précédente tâche est finie et qu&#8217;aucune autre tâche ne soit en cours d&#8217;exécution. Cela entraîne effectivement un glissement progressif de l&#8217;heure de lancement. Mais globalement, ça ne pose aucun problème. L&#8217;important est que la tâche soit exécutée régulièrement. C&#8217;est le cas, par exemple dans le cas de récupération de statistique.</p>

<p>Voici <a href="http://gist.github.com/345000">un exemple de code</a> qui utilise
PeriodicTimer</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s1">&#39;eventmachine&#39;</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;timeout&#39;</span>
</span><span class='line'><span class="no">EventMachine</span><span class="o">.</span><span class="n">run</span> <span class="p">{</span>
</span><span class='line'> <span class="no">EventMachine</span><span class="o">::</span><span class="no">PeriodicTimer</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>   <span class="nb">puts</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="no">Time</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2"> : I am 10&quot;</span>
</span><span class='line'>   <span class="nb">sleep</span> <span class="mi">10</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="no">EventMachine</span><span class="o">::</span><span class="no">PeriodicTimer</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>   <span class="nb">puts</span> <span class="no">Time</span><span class="o">.</span><span class="n">now</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Voici la sortie qui est effectuée si on lance l&#8217;application pendant 50s.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="err">$</span> <span class="n">ruby</span> <span class="n">em_periodic</span><span class="o">.</span><span class="n">rb</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">:</span><span class="mi">39</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">:</span><span class="mi">40</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">:</span><span class="mi">41</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">:</span><span class="mi">42</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">:</span><span class="mi">43</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">:</span><span class="mi">44</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">:</span><span class="mi">45</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">:</span><span class="mi">46</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">:</span><span class="mi">47</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">:</span><span class="mi">48</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span> <span class="p">:</span> <span class="n">I</span> <span class="n">am</span> <span class="mi">10</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">:</span><span class="mi">58</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">:</span><span class="mi">59</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mo">00</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mo">01</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mo">02</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mo">03</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mo">04</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mo">05</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mo">06</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">08</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">08</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span> <span class="p">:</span> <span class="n">I</span> <span class="n">am</span> <span class="mi">10</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">18</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">19</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">20</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">21</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">22</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">23</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">25</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">26</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">27</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">28</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span>
</span><span class='line'><span class="no">Fri</span> <span class="no">Mar</span> <span class="mi">26</span> <span class="mi">16</span><span class="p">:</span><span class="mi">08</span><span class="p">:</span><span class="mi">28</span> <span class="o">+</span><span class="mo">0100</span> <span class="mi">2010</span> <span class="p">:</span> <span class="n">I</span> <span class="n">am</span> <span class="mi">10</span>
</span></code></pre></td></tr></table></div></figure>


<p>On peut constater que la tâche qui doit s&#8217;exécuter toutes les
secondes le fait bien. Par contre la tâche qui s&#8217;exécute au bout de 10
secondes effectue un lock sur le thread. Ainsi la tâche qui s&#8217;exécute toutes
les secondes attend que le lock soit libéré. Une fois terminée,
l&#8217;exécution de la tâche toutes les secondes recommence. La tache qui doit s&#8217;exécuter toutes les 10
secondes attendra, quand à elle, 10 nouvelles secondes après avoir été terminée.</p>

<p>C&#8217;est là une grande puissance de PeriodicTimer. On a facilement une succession
de tâche qui ne se marchent jamais sur les pieds. Désormais,  je n&#8217;utilise plus que</p>

<p>cette solution pour créer des scripts de récupération de données.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Oupsnow 0.5.0 est sortie]]></title>
    <link href="http://blog.shingara.fr/oupsnow-0-5-0-est-sortie.html"/>
    <updated>2010-03-15T00:00:00+01:00</updated>
    <id>http://blog.shingara.fr/oupsnow-0-5-0-est-sortie</id>
    <content type="html"><![CDATA[<p>Ca y est, j&#8217;ai presque pris un cycle de release pas trop mauvais. Ainsi après seulement un mois après la version 0.4.1 de <a href="http://oupsnow.rubyforge.org">Oupsnow</a>, voici la version 0.5.0. Cette version apporte quelque feature, mais marque surtout un moment de stabilité dans le code.</p>

<h2>Les nouveautés</h2>

<ul>
<li>Ajout d&#8217;un filtre sur la recherche des tickets pour ne voir que les tickets fermé ou non</li>
<li>Possibilité d&#8217;éditer une milestone pour les admin d&#8217;un projet</li>
<li>Possibilité de définir une milestone comme actuelle. Par défaut, c&#8217;est la première milestone créée</li>
<li>Possibilité de récupérer son password par email</li>
<li>Possibilité de rester connecter avec un remember_me</li>
<li>Ajout d&#8217;information concernant le nombre de tickets filtrés ou vues</li>
<li>Possibilité pour chaque utilisateur loggé de suivre un ticket. Un utilisateur qui suit un ticket recevra ainsi à chaque mise à jour de ce ticket un email concernant cette modification.</li>
<li>Les utilisateurs ne peuvent plus changer leur email.</li>
</ul>


<p>Enfin comme d&#8217;habitude voici mon fichier capistrano de déployement pour faciliter celui-ci.</p>

<h2>Ficher de déployement capistrano</h2>

<p>&lt;typo:code lang=&#8221;ruby&#8221;>
set :application, &#8220;oupsnow&#8221;
set :repository,  &#8220;git://github.com/shingara/oupsnow.git&#8221;
set :domain, &#8220;dev.shingara.fr&#8221;</p>

<h1>If you aren&#8217;t deploying to /u/apps/#{application} on the target</h1>

<h1>servers (which is the default), you can specify the actual location</h1>

<h1>via the :deploy_to variable:</h1>

<p>set :deploy_to, &#8220;XXXXXXXXX&#8221;</p>

<h1>If you aren&#8217;t using Subversion to manage your source code, specify</h1>

<h1>your SCM below:</h1>

<h1>set :scm, :subversion</h1>

<p>set :scm, :git
set :git_enable_submodules, 1</p>

<p>set :runner, &#8220;xxxx&#8221;
set :user, &#8220;xxxx&#8221;
set :use_sudo, false</p>

<p>set :thin_conf, &#8220;/etc/thin/#{domain}.yml&#8221;</p>

<p>set :rails_env, &#8220;production&#8221;</p>

<p>role :app, domain
role :web, domain
role :db,  domain, :primary => true</p>

<p>task :update_config, :roles => [:app] do
  run &#8220;ln -s #{shared_path}/config/database.yml #{release_path}/config/database.yml&#8221;
  run &#8220;ln -s #{shared_path}/config/email.yml #{release_path}/config/email.yml&#8221;
  run &#8220;ln -s #{shared_path}/config/initializers/errornot.rb #{release_path}/config/initializers/errornot.rb&#8221;
  run &#8220;cd #{release_path} &amp;&amp; echo &#8216;GOOGLE_ANALYTICS=&#34;XXXXXXXX&#34;&#8217; >> config/environment.rb&#8221;
end</p>

<p>namespace :deploy do
  task :start, :roles => [:app] do</p>

<pre><code>run "thin -C #{thin_conf} start"
</code></pre>

<p>  end</p>

<p>  task :stop, :roles => [:app] do</p>

<pre><code>run "thin -C #{thin_conf} stop"
</code></pre>

<p>  end</p>

<p>  task :restart, :roles => [:app] do</p>

<pre><code>run "thin -C #{thin_conf} restart"
</code></pre>

<p>  end
end</p>

<p>task :update_db do
  run &#8220;cd #{current_path} &amp;&amp; RAILS_ENV=#{rails_env} rake db:update&#8221;
end</p>

<p>after &#8220;deploy:update_code&#8221;, :update_config
after &#8220;deploy:symlink&#8221;, :update_db
&lt;/typo:code></p>

<p><a href="http://blog.shingara.fr/en/2010-03-13-oupsnow-0-5-0-released.html">English translation</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Pourquoi Ruby et Ruby On Rails dans le développement d'application web ?]]></title>
    <link href="http://blog.shingara.fr/pourquoi-ruby-et-ruby-on-rails-dans-le-developpement-dapplication-web.html"/>
    <updated>2010-01-27T00:00:00+01:00</updated>
    <id>http://blog.shingara.fr/pourquoi-ruby-et-ruby-on-rails-dans-le-developpement-dapplication-web</id>
    <content type="html"><![CDATA[<p>Cette question a été posée dernièrement sur la Mailling List de RailsFrance. Effectivement, si on veut promouvoir Ruby dans le monde informatique français, il faut pouvoir argumenter pourquoi on trouve que c&#8217;est une bonne idée.
</p>

<p>
Tout le monde est en droit de se poser la question. Voici donc, pour moi, l&#8217;avantage de Ruby par rapport aux autres technologies à l&#8217;heure actuelle.
</p>

<h4>Ruby c&#8217;est fun</h4>

<p>
Matz, quand il a créé Ruby, a voulu faire un langage fun avec lequel il pourrait s&#8217;amuser à coder. Aujourd&#8217;hui tous les développeurs Ruby diront à peu près la même chose. Coder en Ruby est plaisant. L&#8217;avantage de ce point est qu&#8217;un développeur Ruby est plus détendu. Un développeur détendu est un développeur plus heureux. Un développeur plus heureux est motivant pour une équipe. Un développeur heureux essayera de faire son travail proprement. L&#8217;ambiance d&#8217;une équipe de développeur Ruby peut ainsi être agréable. Moins de stress sur un projet, c&#8217;est un projet qui part avec un peu plus de chances de réussir.
</p>

<h4>Ruby aime les tests</h4>

<p>
La communauté Ruby actuelle est convaincue de l&#8217;utilité des tests unitaires. Ainsi, chaque librairie est poussée par la communauté à avoir des tests. Beaucoup de développeurs, moi y compris, privilégierons une librairie avec des tests unitaires plutôt qu&#8217;une sans aucun tests.
</p>
<p>
Cette philosophie permet d&#8217;avoir un environnement de développement de test simplifié directement dans Rails. Pas besoin de se prendre la tête pour faire des tests. Si vous ne faites pas de tests de base : soit vous ne voulez pas en faire, ce que je ne recommande pas, soit vous le faites exprès.
</p>


<h4>Ruby aime le cloud</h4>

<p>
En ce moment, l&#8217;évolution logique du net est le Cloud Computing. L&#8217;idée du Cloud Computing est simple. Nos sites internet ne sont plus hébergés sur une seule machine. Les services sont séparés pour améliorer la scallabilité. Au sein de la communauté Ruby, les développeurs sont très attachés à cette idée. Ainsi beaucoup d&#8217;utilitaires pour gérer et utiliser son cloud commencent à voir le jour comme Chef. L&#8217;architecture même de Rails permet de facilement sortir de Ruby On Rails pour ainsi utiliser son Cloud. ActiveRessource en est la preuve.
</p>
<p>
Mais coder dans un Cloud implique de coder plusieurs briques. Le Ruby a des bindings pour tous ces utilitaires, comme les systèmes de queues ou les bases de Données Non-Relationnelle. Je ne dis pas que les autres ne peuvent pas le faire. Mais là encore c&#8217;est un effet de groupe. Chaque développeur ruby a envie de jouer avec un Cloud. On pense de plus en plus en cloud.
</p>
<h4>Les plugins de Rails</h4>
<p>
Ruby On Rails possède une très grande quantité de plugins. On peut ainsi facilement trouver la petite brique que l&#8217;on cherche pour sa propre utilisation. C&#8217;est plus que l&#8217;utilisation d&#8217;un module Drupal. Car là nous sommes dans un environement facilement modifiable et sans aucune limitation. Chose que Drupal peut vite avoir.
</p>

<h4>Les Ressources</h4>
<p>
Le plus grand reproche que l&#8217;on fait actuellement au choix de Ruby On Rails, c&#8217;est le manque de ressources. Effectivement, les ressources de développeurs Ruby sont plus faibles que pour d&#8217;autres langages. Mais ceci est selon moi un faux problème. L&#8217;apprentissage de Ruby et Ruby On Rails est assez simple si on connait la logique Objet. Ainsi, n&#8217;importe quel développeur Java peut tout à fait se mettre à Ruby et Ruby On Rails. Donc avec un expert Ruby/Rails, on peut former facilement une équipe complète et compétente.
</p>

<p>Cet argumentaire n&#8217;engage bien sûr que moi et peut donc être sujet à caution.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Que cherche un développeur dans une offre d'emploi ?]]></title>
    <link href="http://blog.shingara.fr/que-cherche-un-developpeur-dans-une-offre-demploi.html"/>
    <updated>2010-01-23T00:00:00+01:00</updated>
    <id>http://blog.shingara.fr/que-cherche-un-developpeur-dans-une-offre-demploi</id>
    <content type="html"><![CDATA[<p>On m&#8217;a posé dernièrement cette question. Ça peut sembler bête au premier abord, mais après quelques secondes de réflexion on se rappelle que toutes les offres d&#8217;emplois sont pleines d&#8217;interrogation.</p>

<h4>Donc qu&#8217;est ce que j&#8217;attends dans une offre d&#8217;emploi ?</h4>

<ul>

<li>Le nom de l&#8217;entreprise :<br/>
<p>Le nom de l&#8217;entreprise est toujours pratique ne serait-ce que pour zapper l&#8217;annonce si on aime pas cette entreprise. Ou alors rigoler encore plus en lisant l&#8217;offre d&#8217;emploi.</p>
</li>

<li>Le cœur de métier de l&#8217;entreprise :<br/>
<p>C&#8217;est toujours agréable de savoir si on va travailler pour une entreprise qui fait du beurre ou des sites Web. On peut ainsi éviter certains entretiens inutiles.</p>
</li>

<li>Le nombre de développeurs dans l&#8217;entreprise :<br />
<p>C&#8217;est une question plutôt inhabituelle pour un recruteur, mais avoir cette information permet de savoir tout de suite si on sera le geek dans son coin qui sera interrompu pour faire de l&#8217;assistance Words alors qu&#8217;il n&#8217;a plus touché à un windows depuis 3 ans. Au contraire, si on voit qu&#8217;il y a une majorité de développeurs, on pourra se dire que ça sera la fête aux trolls. Un développeur aime les Trolls \o/.</p>
</li>

<li>Les personnes connues :<br />
<p>Comme dans tous métiers, on connaît certaines personnes de réputation. Cela peut facilement aider un développeur à choisir cette offre d&#8217;emploi si une personne connue y est. En revanche, c&#8217;est aussi à double tranchant. Certains feront l&#8217;entretien juste pour voir cette personne. D&#8217;autres zapperont encore plus l&#8217;offre d&#8217;emploi à cause de cette même personne.</p>
</li>

<li>L&#8217;environnement de travail :<br />
<p>L&#8217;OS utilisé en majorité par les développeurs de la société peut être un très bon indicateur parfois. Typiquement chez AF83 où je travaille encore en ce moment, tous les développeurs sont sous UNIX, soit GNU/Linux, soit MacOSX. Pour beaucoup, cela prouve la qualité des développeurs. Et là encore la guerre aux trolls pourra facilement être ouverte.</p>
</li>

<li>La contribution Open source possible et faite par l&#8217;entreprise :<br />
<p>Avoir du temps pour faire de l&#8217;Open Source selon notre désir est un plus non négligeable selon moi. J&#8217;ai énormément de projets open source en cours que je fais en parallèle de mon emploi, mais si je pouvais les faire aussi durant une partie de celui-ci, je serais vraiment heureux. Ensuite le fait que la société produise du code Open Source, peut facilement permettre au développeur de jauger de la qualité du code de cette société. En effet, pourquoi est-ce toujours la société qui doit vérifier le code de ses futurs employés ?</p>
</li>
</ul>

<p>Selon, moi ces 6 points ne sont hélas pas toujours renseignés dans une offre d&#8217;emploi et cela serait un plus non négligeable.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Sortie de Typo 5.4.0]]></title>
    <link href="http://blog.shingara.fr/sortie-de-typo-5-4-0.html"/>
    <updated>2009-12-21T00:00:00+01:00</updated>
    <id>http://blog.shingara.fr/sortie-de-typo-5-4-0</id>
    <content type="html"><![CDATA[<p>Ça y est, une nouvelle version de <a href="http://typosphere.org">Typo</a> est lancée dans la nature. Je n&#8217;ai
hélas que très peu participé à cette nouvelle version faute de
motivation/temps. Mais je suis toujours très content de voir une nouvelle
version de ce blog sortir.</p>

<p>A chaque release, une nouvelle admin fait son apparition, mais à chaque
fois elle est meilleure que la précédente, donc c&#8217;est une excellente chose.</p>

<p>J&#8217;ai bien-sûr mis à jour ce blog et j&#8217;ai aussi switché sur le nouveau thème
par défaut. Je suis toujours aussi nul en design.</p>

<p>En petit cadeau, voici mon fichier <a href="http://capify.org/">capistrano</a> que j&#8217;utilise pour déployer
ce blog. Ça peux toujours vous servir. On ne sait jamais.</p>

<typo:code lang="ruby">
set :application, &#8220;typo&#8221;
set :repository,  &#8220;git://github.com/fdv/typo.git&#8221;
set :domain, &#8220;blog.shingara.fr&#8221;

# If you aren&#8217;t deploying to /u/apps/#{application} on the target
# # servers (which is the default), you can specify the actual location
# # via the :deploy_to variable:
set :deploy_to, &#8220;/var/rails/blog-typo&#8221;
#
# # If you aren&#8217;t using Subversion to manage your source code, specify
# # your SCM below:
set :scm, :git

set :runner, &#8220;rails&#8221;
set :user, &#8220;rails&#8221;
set :use_sudo, false

set :thin_conf, &#8220;/etc/thin/#{domain}.yml&#8221;

role :app, domain
role :web, domain
role :db,  domain, :primary => true

task :update_config, :roles => [:app] do
  run &#8220;cp -Rf #{shared_path}/config/* #{release_path}/config/&#8221;
  run &#8220;ln -s #{shared_path}/files #{release_path}/public/files&#8221;
end

task :update_gems, :roles => [:app] do
  run &#8220;cd #{release_path} && RAILS_ENV=production rake gems:install&#8221;
end


after &#8220;deploy:update_code&#8221;, :update_config
after &#8220;deploy:update_code&#8221;, :update_gems


namespace :deploy do
  task :start, :roles => [:app] do
    run &#8220;thin -C #{thin_conf} start&#8221;
  end

  task :stop, :roles => [:app] do
    run &#8220;thin -C #{thin_conf} stop&#8221;
  end

  task :restart, :roles => [:app] do
    run &#8220;thin -C #{thin_conf} restart&#8221;
  end
end

task :clear_cache, :roles => [:app] do
  run &#8220;cd #{current_path} && RAILS_ENV=production rake sweep_cache&#8221;
  run &#8220;cd #{current_path} && RAILS_ENV=production rake tmp:cache:clear&#8221;
end

after &#8220;deploy:restart&#8221;, :clear_cache
after &#8220;deploy:start&#8221;, :clear_cache
</typo:code>

<p><a href="http://blog.shingara.fr/en/2009-12-21-typo-5-4-0-released.html">English Translation</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Sortie de Oupsnow 0.4.0]]></title>
    <link href="http://blog.shingara.fr/sortie-de-oupsnow-0-4-0.html"/>
    <updated>2009-12-01T00:00:00+01:00</updated>
    <id>http://blog.shingara.fr/sortie-de-oupsnow-0-4-0</id>
    <content type="html"><![CDATA[<p>Ca y est, Oupsnow 0.4.0 est enfin sorti. Cette version est un refactoring quasiment complet. Après avoir eu une version 0.3.0 en Merb/DataMapper, cette version est désormais en Rails/MongoDB. Le back-end et le serveur ont changé.</p>

<p>Cette nouvelle version, outre son refactoring comprend aussi l&#8217;ajout de quelques nouvelles fonctionnalités.</p>

<ul>
<li>Ajout d&#8217;un filtre par Status dans la recherche de ticket</li>
<li>Ajout de la possibilité de changer la fonction de tous les membres d&#8217;un project</li>
<li>Ajout de la preview des tickets et commentaires sur les tickets</li>
<li>Ajout de la visualisation de la milestone courante dans la visualisation d&#8217;un ticket</li>
<li>Possibilité d&#8217;ordonner tous les champs de recherche dans la vue des tickets</li>
<li>Login par l&#8217;email et plus par le pseudo</li>
</ul>

<p>Vous pouvez télécharger cette version sur <a href="http://rubyforge.org/frs/?group_id=7685">rubyforge</a></p>

<p>Si vous souhaitez tester cette version, une <a href="http://oupsnow.shingara.fr/">version de demo de oupsnow</a> est en ligne. Les login/mdp sont : admin@admin.com/oupsnow. Amusez vous bien.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Comment tester devise ? réélement ?]]></title>
    <link href="http://blog.shingara.fr/comment-tester-devise-reelement.html"/>
    <updated>2009-11-30T00:00:00+01:00</updated>
    <id>http://blog.shingara.fr/comment-tester-devise-reelement</id>
    <content type="html"><![CDATA[<p>Alors que j&#8217;ai cherché comment tester facilement <a href="http://github.com/plataformatec/devise">Devise</a>. J&#8217;ai indiqué une technique dans <a href="http://blog.shingara.fr/devise-cest-bien-mais-il-faut-le-tester.html">mon précédent post</a>. Mais cette technique est loin d&#8217;être la meilleure. Voici donc la nouvelle solution, la solution officielle.</p>

<p>Il suffit d&#8217;inclure <code>Devise::TestHelpers</code>. Ensuite pour se logger avec un utilisateur, on utilise la méthode <code>sign_in</code>. La méthode <code>sign_out</code> existe aussi.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Devise ? c'est bien, mais il faut le tester.]]></title>
    <link href="http://blog.shingara.fr/devise-cest-bien-mais-il-faut-le-tester.html"/>
    <updated>2009-11-19T00:00:00+01:00</updated>
    <id>http://blog.shingara.fr/devise-cest-bien-mais-il-faut-le-tester</id>
    <content type="html"><![CDATA[<p>Alors que j&#8217;ai évoqué ma <a href="http://blog.shingara.fr/oupsnow-de-merb-i-rails.html">migration de Merb à Rails pour
Oupsnow</a>, il a
fallu trouver un système d&#8217;authentification ORM Agnostique.</p>

<p>Le plugin d&#8217;authentification le plus connu à l&#8217;heure actuel est <a
href="http://rdoc.info/projects/binarylogic/authlogic">Authlogic</a>.
Ce plugin est vraiment très performant, mais tous les essais de le rendre ORM
Agnostique ont été vain. C&#8217;est alors qu&#8217;au même moment, durant le <a
href="http://www.railssummit.com.br/">Rails Summit 2009</a>,
George Guimarães et Carlos Antonio annoncent la sortie de <a
href="http://github.com/plataformatec/devise">Devise</a>, un plugin Rails au
dessus de <a href="http://github.com/hassox/warden">Warden</a> (
Rack middleware d&#8217;authentification). C&#8217;est exactement, ce qu&#8217;il me faut, un
nouveau système d&#8217;authentification a tester et peut-être une possibilité
d&#8217;ajouter une couche d&#8217;ORM Agnostique dedans. En plus Warden étant un
RackMiddleware, je pourrais un peu tester ce que ça donne.</p>

<p>J&#8217;installe donc Devise et commence à l&#8217;utiliser dans Oupsnow. Tout se passe
à merveille, jusqu&#8217;au moment où il faut faire les tests. Tout de suite le bât
blesse. Les tests controlleurs de Rails ne communiquent pas avec la couche Rack
qui n&#8217;est pas initialisée. On se retrouve donc avec une impossibilité de
définir si un utilisateur est loggé ou non et si oui, qui est cet
utilisateur.</p>

<p>Après de nombreux tests et essais. J&#8217;ai fini par trouver comment faire.
Warden ajoute à la requête une variable d&#8217;environment dans la requête. On peux
y accéder par
<code>request.env['warden']</code>. Il suffit donc de remplir cette
variable.</p>

<p>Pour avoir un utilisateur non loggé, il faut faire :</p>

<typo:code lang="ruby">
def unlogged
  request.env[&#8216;warden&#8217;] = Warden::Proxy.new(request.env, {:default_strategies => [:rememberable, :authenticable],:silence_missing_strategies => true})
end
</typo:code>

<p>Pour se logger avec un utilisateur en particulier il faut faire :</p>

<typo:code lang="ruby">
def logged_as(user)
  proxy = Warden::Proxy.new(request.env, {:default_strategies => [:rememberable, :authenticable], :silence_missing_strategies => true})
  proxy.set_user(user, :store => true, :scope => :user)
  request.env[&#8216;warden&#8217;] = proxy
end
</typo:code>

<p>Personnellement, j&#8217;aime beaucoup <a href="http://github.com/plataformatec/devise">devise</a>. A tel point que j&#8217;ai permis de le
rendre ORM Agnostique et compatible avec <a href="http://github.com/jnunemaker/mongomapper/">MongoMapper</a>.</p>

<p>EDIT du 30 Novembre 2009: la technique indiquée ici n&#8217;est pas optimum et ne marche pas avec les dernières versions de Devise. utilisez plutôt la technique décrite dans mon ticket <a href="http://blog.shingara.fr/comment-tester-devise-reelement.html">Comment tester devise ? réélement ?</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Oupsnow de Merb à Rails]]></title>
    <link href="http://blog.shingara.fr/oupsnow-de-merb-i-rails.html"/>
    <updated>2009-11-18T00:00:00+01:00</updated>
    <id>http://blog.shingara.fr/oupsnow-de-merb-i-rails</id>
    <content type="html"><![CDATA[<p>Dernièrement, j&#8217;ai fini par me décider de migrer <a
href="http://oupsnow.rubyforge.org">Oupsnow</a>, de Merb à Rails.</p>

<p>Alors que je
finissais une migration de SQL à MongoDB, j&#8217;en entame une nouvelle. Celle-ci
beaucoup plus profonde.</p>

<p>La raison de ma migration ?</p>

<p>Rails 3. En
effet, depuis Décembre 2008, soit presque un an, Merb s&#8217;est figé.
Certain me diront que la communauté Merb est en train de revivre et c&#8217;est tout
à fait vrai. J&#8217;en suis même ravi. Mais Merb a pris un immense retard en
presque un an. Même si Rails n&#8217;a pas vraiment avancé dans sa version stable,
sa version Edge a elle énormément avancée.</p>

<p>Voulant toujours tester les
nouvelles technologies en Ruby, je voudrais tester Rails 3. Mais aucun système
n&#8217;existe pour passer de Merb à Rails 3. Un rapide test m&#8217;a montré que la
différence était par contre minime entre Rails 2.3.x et Rails 3. La
migration de Rails 2.3.x à Rails 3 en sera donc d&#8217;autant plus simple.</p>

<p>Voulant vraiment sortir une version stable le plus vite possible, j&#8217;ai
donc pris la décision de migrer Oupsnow vers Rails 2.3.x pour ensuite migrer
sur Rails 3 pour cette fois sortir une version de Oupsnow compatible Rails 3.</p>

<p>Oupsnow devient donc un projet Rails/MongoMapper et non plus
Merb/DataMapper comme sa dernière version. Toute aide est bien-sûr la
bienvenue.</p>

<p><a href="http://blog.shingara.fr/en/2009-11-19-oupsnow-from-merb-to-rails.html">English translation</a></p>
]]></content>
  </entry>
  
</feed>
