<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>tutoriaux rails</title>
 <link href="http://www.tutoriaux-rails.com/atom.xml" rel="self"/>
 <link href="http://www.tutoriaux-rails.com/"/>
 <icon>/favicon.ico</icon>
 <updated>2010-09-01T12:00:34+02:00</updated>
 <id>http://www.tutoriaux-rails.com/</id>
 <author>
   <name>Matthieu Sadouni</name>
   <email>mathieusadouni@gmail.com</email>
 </author>
 
 
 <entry>
   <title>Créer et envoyer un email</title>
   <link href="http://www.tutoriaux-rails.com/articles/creer-et-envoyer-un-email"/>
   <updated>2010-08-16T00:00:00+02:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/creer-et-envoyer-un-email</id>
   <content type="html">&lt;h2 id='principe'&gt;Principe&lt;/h2&gt;

&lt;p&gt;Le framework Ruby on Rails est construit sur le principe &lt;a href='http://fr.wikipedia.org/wiki/Modèle-Vue-Contrôleur'&gt;MVC&lt;/a&gt;, et les emails n&amp;#8217;échappent pas à cette règle. Ils sont gérés par des modèles un peu particuliers qui héritent de &lt;code&gt;ActionMailer::Base&lt;/code&gt;, les &lt;code&gt;Mailer&lt;/code&gt;. Chaque &lt;code&gt;Mailer&lt;/code&gt; concerne une partie de l&amp;#8217;application, par exemple :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;UserMailer&lt;/code&gt; pour les emails en rapport avec l&amp;#8217;inscription et l&amp;#8217;activation de compte&lt;/li&gt;

&lt;li&gt;&lt;code&gt;PostMailer&lt;/code&gt; pour les emails de notification d&amp;#8217;un nouvel article aux abonnés&lt;/li&gt;

&lt;li&gt;&lt;code&gt;OrderMailer&lt;/code&gt; pour les emails de notification des différentes étapes d&amp;#8217;avancement d&amp;#8217;une commande&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dans chaque &lt;code&gt;Mailer&lt;/code&gt;, une méthode de classe est définie pour chaque email. Y sont définis le destinataire, le sujet, les variables utilisées dans le corps du message, etc. Le message final est compilé à partir d&amp;#8217;une vue, comme n&amp;#8217;importe quelle action de contrôleur dans l&amp;#8217;application.&lt;/p&gt;

&lt;h2 id='cration_dun_mailer'&gt;Création d&amp;#8217;un Mailer&lt;/h2&gt;

&lt;p&gt;Un script fourni avec Ruby on Rails permet de générer les fichiers nécessaires :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;script/generate mailer user_mailer
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Intéressons-nous tout d&amp;#8217;abord au fichier &lt;code&gt;models/user_mailer.rb&lt;/code&gt;, auquel nous ajoutons une méthode représentant un email de bienvenue après l&amp;#8217;inscription :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user_mailer.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UserMailer&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActionMailer&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;bienvenue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;recipients&lt;/span&gt; &lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;email&lt;/span&gt;
        &lt;span class='n'&gt;from&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Example.com&amp;lt;no-reply@example.com&amp;gt;&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;subject&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Bienvenue !&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='ss'&gt;:user&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:account_url&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;edit_user_url&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;recipients&lt;/code&gt; définit le destinataire à partir d&amp;#8217;une chaîne contenant une adresse email, ou un tableau de chaînes (sous forme &lt;code&gt;[&amp;#39;email1@example.com&amp;#39;, &amp;#39;John&amp;lt;john@example.com&amp;gt;]&lt;/code&gt;)&lt;/li&gt;

&lt;li&gt;&lt;code&gt;from&lt;/code&gt; définit l&amp;#8217;adresse de l&amp;#8217;expéditeur&lt;/li&gt;

&lt;li&gt;&lt;code&gt;subject&lt;/code&gt; définit, sans surprise, le sujet&lt;/li&gt;

&lt;li&gt;&lt;code&gt;body&lt;/code&gt; permet de définir des variables accessibles dans la vue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La liste complète des attributs est disponible &lt;a href='http://guides.rubyonrails.org/action_mailer_basics.html'&gt;dans le chapitre 2.3 du guide ActionMailer (en anglais)&lt;/a&gt;. Les plus utilisés, à part ceux présentés ici, sont probablement &lt;code&gt;bcc&lt;/code&gt; et &lt;code&gt;reply-to&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nous voyons ici que l&amp;#8217;une des variables accessibles dans la vue, &lt;code&gt;account_url&lt;/code&gt;, contient l&amp;#8217;url du compte de l&amp;#8217;utilisateur. Les &lt;code&gt;Mailers&lt;/code&gt; n&amp;#8217;ayant pas accès au contexte de la requête, il faut paramétrer l&amp;#8217;URL de base de l&amp;#8217;application pour que le lien complet puisse être construit. Nous ajoutons pour cela une ligne au fichier de l&amp;#8217;environnement concerné :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/environments/&amp;lt;environment&amp;gt;.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;action_mailer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;default_url_options&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='ss'&gt;:host&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;example.com&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Avec pour &lt;code&gt;:host&lt;/code&gt; le nom du domaine sur lequel est hébergé l&amp;#8217;application. En développement, ce sera par exemple &lt;code&gt;localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Il ne nous reste plus qu&amp;#8217;à créer la vue correspondante :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/user_mailer/bienvenue.text.plain.erb&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    Bienvenue &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x'&gt; !&lt;/span&gt;
&lt;span class='x'&gt;    Votre compte : &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='vi'&gt;@account_url&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;Notons que le nom du fichier mentionne le type de format utilisé (&lt;code&gt;text.plain&lt;/code&gt;). Nous y reviendrons juste après le chapitre suivant.&lt;/p&gt;

&lt;h2 id='envoi_dun_email'&gt;Envoi d&amp;#8217;un email&lt;/h2&gt;

&lt;p&gt;Une fois l&amp;#8217;email créé, le plus simple pour l&amp;#8217;envoyer est d&amp;#8217;appeler la méthode correspondante dans un contrôleur :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/users_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UsersController&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ApplicationController&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create&lt;/span&gt;
        &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:user&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;save&lt;/span&gt;
          &lt;span class='no'&gt;UserMailer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;deliver_bienvenue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
          &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;root_path&lt;/span&gt; &lt;span class='ow'&gt;and&lt;/span&gt; &lt;span class='k'&gt;return&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous remarquons que la méthode appelée est &lt;code&gt;deliver_bienvenue&lt;/code&gt; et non &lt;code&gt;bienvenue&lt;/code&gt;. ActionMailer utilise &lt;code&gt;method_missing&lt;/code&gt; &lt;a href='http://weblog.jamisbuck.org/2006/12/1/under-the-hood-activerecord-base-find-part-3'&gt;(en savoir plus sur &lt;code&gt;method_missing&lt;/code&gt; - en anglais)&lt;/a&gt; pour retrouver la méthode demandée &lt;code&gt;bienvenue&lt;/code&gt; et envoyer l&amp;#8217;email. Il est ainsi également possible de créer notre email sans l&amp;#8217;envoyer, via &lt;code&gt;create_bienvenue&lt;/code&gt;. Ceci permet de n&amp;#8217;écrire qu&amp;#8217;une seule méthode pour définir un email, et de l&amp;#8217;envoyer en une seule ligne de code. De plus, le code dans le contrôleur est plus lisible car l&amp;#8217;intention est claire :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='no'&gt;UserMailer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;deliver_bienvenue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='c1'&gt;# est plus explicite que&lt;/span&gt;
    &lt;span class='no'&gt;UserMailer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;bienvenue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Il existe deux autres manières d&amp;#8217;envoyer un email. La première, depuis un modèle, par exemple ici dans la méthode &lt;code&gt;after_create&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;User&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
      &lt;span class='n'&gt;after_create&lt;/span&gt; &lt;span class='ss'&gt;:notify_by_email&lt;/span&gt;

      &lt;span class='kp'&gt;private&lt;/span&gt;
        &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;notify_by_email&lt;/span&gt;
          &lt;span class='no'&gt;UserMailer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;deliver_bienvenue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Le souci avec cette approche est que du code sans rapport avec la responsabilité première du modèle lui est rajouté. Pour éviter cela, nous pouvons utiliser un &lt;code&gt;Observer&lt;/code&gt;. Comme son nom l&amp;#8217;indique, un &lt;code&gt;Observer&lt;/code&gt; &amp;#8220;observe&amp;#8221; une classe et répond aux méthodes de rappel (callbacks) comme &lt;code&gt;after_create&lt;/code&gt;, &lt;code&gt;before_save&lt;/code&gt; etc. Pour mettre en place ce fonctionnement, nous commençons par créer un fichier &lt;code&gt;app/models/user_observer.rb&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user_observer.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UserObserver&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Observer&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;after_save&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='no'&gt;UserMailer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;deliver_bienvenue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Pour que l&amp;#8217;&lt;code&gt;Observer&lt;/code&gt; soit chargé automatiquement au lancement de l&amp;#8217;application, il faut le spécifier dans &lt;code&gt;config/environment.rb&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/environment.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='no'&gt;Rails&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Initializer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
      &lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;.&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;
      &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;active_record&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;observers&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='ss'&gt;:user_observer&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Il ne reste plus ensuite qu&amp;#8217;à supprimer de &lt;code&gt;UsersController&lt;/code&gt; la ligne concernant l&amp;#8217;envoi de l&amp;#8217;email, celui-ci étant envoyé automatiquement par l&amp;#8217;&lt;code&gt;Observer&lt;/code&gt; après la création de l&amp;#8217;utilisateur :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/users_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UsersController&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ApplicationController&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create&lt;/span&gt;
        &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:user&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;save&lt;/span&gt;
          &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;root_path&lt;/span&gt; &lt;span class='ow'&gt;and&lt;/span&gt; &lt;span class='k'&gt;return&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Chaque méthode a ses avantages et ses inconvénients. Un &lt;code&gt;Observer&lt;/code&gt; permet de garder le code du modèle et du contrôleur le plus simple possible, et de s&amp;#8217;assurer que l&amp;#8217;email est envoyé à chaque fois qu&amp;#8217;un utilisateur est créé, même sans passer par le contrôleur (en console par exemple). Par contre, si l&amp;#8217;application grossit et compte plusieurs observers réalisant chacun plusieurs tâches, il peut être difficile de bien voir tout ce qu&amp;#8217;il se passe sur une action donnée.&lt;/p&gt;

&lt;p&gt;L&amp;#8217;envoi depuis le contrôleur ou un modèle permet quant à lui de garder un code plus clair, car chaque action effectuée est directement visible, en contrepartie de la possibilité d&amp;#8217;une duplication de code. C&amp;#8217;est à chacun de choisir la méthode appropriée selon ses besoins, en gardant à l&amp;#8217;esprit que les deux approches sont compatibles.&lt;/p&gt;

&lt;h2 id='envoi_au_format_html'&gt;Envoi au format HTML&lt;/h2&gt;

&lt;p&gt;L&amp;#8217;envoi au format HTML est très simple : il suffit d&amp;#8217;avoir deux vues du même nom que l&amp;#8217;email, une pour la version texte et une pour la version HTML :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/user_mailer/bienvenue.text.plain.erb&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    Bienvenue &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x'&gt; !&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;span class='x'&gt;    Votre compte : &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='vi'&gt;@account_url&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/user_mailer/bienvenue.text.html.erb&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &amp;lt;h1&amp;gt;Bienvenue &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x'&gt; !&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;span class='x'&gt;    &amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;&lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='vi'&gt;@account_url&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x'&gt;&amp;quot;&amp;gt;Votre compte&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;Rails va alors automatiquement construire un email au format multipart, sans aucune autre action nécessaire de notre part.&lt;/p&gt;

&lt;h2 id='utiliser_un_layout'&gt;Utiliser un layout&lt;/h2&gt;

&lt;p&gt;Comme un contrôleur, un &lt;code&gt;Mailer&lt;/code&gt; peut également utiliser un layout pour ses vues. Il suffit pour cela de créer un fichier dont le nom se termine par &lt;code&gt;_mailer&lt;/code&gt; et nommé comme le &lt;code&gt;Mailer&lt;/code&gt;. Pour &lt;code&gt;UserMailer&lt;/code&gt;, les layouts &lt;code&gt;app/views/layouts/user_mailer.text.plain.erb&lt;/code&gt; et &lt;code&gt;app/views/layouts/user_mailer.text.html.erb&lt;/code&gt; seront automatiquement utilisés. Pour spécifier un autre fichier, il faut utiliser la méthode &lt;code&gt;layout&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user_mailer.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UserMailer&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActionMailer&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
      &lt;span class='n'&gt;layout&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;application_mailer&amp;#39;&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;# app/views/layouts/application_mailer.text.plain.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    --&lt;/span&gt;
&lt;span class='x'&gt;    À bientôt sur notre site&lt;/span&gt;
&lt;span class='x'&gt;    Toute l&amp;#39;équipe de http://www.example.com&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Le layout HTML, nécessaire si une vue existe au format HTML, serait quant à lui nommé &lt;code&gt;application_mailer.text.html.erb&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='optimiser_ses_mailers'&gt;Optimiser ses Mailers&lt;/h2&gt;

&lt;p&gt;À partir du moment où l&amp;#8217;application utilise plusieurs &lt;code&gt;Mailers&lt;/code&gt;, du code se retrouve dupliqué lors du paramétrage des emails :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;les attributs &lt;code&gt;from&lt;/code&gt; et &lt;code&gt;sent_on&lt;/code&gt; sont quasiment toujours identiques&lt;/li&gt;

&lt;li&gt;si un seul layout est utilisé pour tous les &lt;code&gt;Mailers&lt;/code&gt;, il est nécessaire de le définir dans chacun puisque le fonctionnement automatique en fonction du nom du &lt;code&gt;Mailer&lt;/code&gt; n&amp;#8217;est plus possible&lt;/li&gt;

&lt;li&gt;si nous souhaitons ajouter le nom de l&amp;#8217;application entre crochets devant le sujet de chaque message pour faciliter le filtrage des emails, il faudrait le répéter dans chaque méthode de nos &lt;code&gt;Mailers&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour remédier à cela, nous créons une classe &lt;code&gt;ApplicationMailer&lt;/code&gt; dont héritent les &lt;code&gt;Mailers&lt;/code&gt; de l&amp;#8217;application. Nous y centralisons le code commun dans une méthode &lt;code&gt;setup&lt;/code&gt; et allégeons ainsi nos &lt;code&gt;Mailers&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/application_mailer.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;ApplicationMailer&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActionMailer&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
      &lt;span class='n'&gt;layout&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;application_mailer&amp;#39;&lt;/span&gt;

      &lt;span class='kp'&gt;protected&lt;/span&gt;
        &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;setup&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;args&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
          &lt;span class='n'&gt;from&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Example.com&amp;lt;no-reply@example.com&amp;gt;&amp;quot;&lt;/span&gt;
          &lt;span class='n'&gt;subject&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;[Example.com] &amp;quot;&lt;/span&gt;
          &lt;span class='n'&gt;sent_on&lt;/span&gt; &lt;span class='no'&gt;Time&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;now&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Il nous suffit ensuite de faire hériter &lt;code&gt;UserMailer&lt;/code&gt; de &lt;code&gt;ApplicationMailer&lt;/code&gt; et d&amp;#8217;appeler la méthode &lt;code&gt;setup&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user_mailer.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UserMailer&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ApplicationMailer&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;bienvenue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;setup&lt;/span&gt;
        &lt;span class='n'&gt;recipients&lt;/span&gt; &lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;email&lt;/span&gt;
        &lt;span class='vi'&gt;@subject&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Bienvenue !&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='ss'&gt;:user&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:account_url&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;edit_user_url&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Notons l&amp;#8217;utilisation de &lt;code&gt;@subject&lt;/code&gt; pour ajouter au sujet prédéfini dans &lt;code&gt;setup&lt;/code&gt; le sujet de l&amp;#8217;email.&lt;/p&gt;

&lt;p&gt;Une autre forme de duplication apparaît également dans chaque &lt;code&gt;Mailer&lt;/code&gt;, selon sa responsabilité. Par exemple, les emails de notre &lt;code&gt;UserMailer&lt;/code&gt; sont presque toujours envoyé à un utilisateur passé en paramètre. Celui-ci est également passé à leur vue respective pour y afficher son nom, etc. Pour centraliser cela, nous surchargeons la méthode &lt;code&gt;setup&lt;/code&gt; dans chaque Mailer concerné :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user_mailer.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UserMailer&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ApplicationMailer&lt;/span&gt;
      &lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;.&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;bienvenue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;setup&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='vi'&gt;@subject&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Bienvenue !&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;body&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:account_url&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;edit_user_url&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;anniversaire&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;setup&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='vi'&gt;@subject&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Joyeux anniversaire !&amp;quot;&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;anonyme&lt;/span&gt;
        &lt;span class='n'&gt;setup&lt;/span&gt;
        &lt;span class='n'&gt;recipients&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;test@example.com&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;test2@example.com&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
        &lt;span class='vi'&gt;@subject&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Un simple exemple n&amp;#39;utilisant pas user&amp;quot;&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='kp'&gt;protected&lt;/span&gt;
        &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;setup&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kp'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
          &lt;span class='k'&gt;super&lt;/span&gt;
          &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;user&lt;/span&gt;
            &lt;span class='n'&gt;recipients&lt;/span&gt; &lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;email&lt;/span&gt;
            &lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='ss'&gt;:user&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;user&lt;/span&gt;
          &lt;span class='k'&gt;end&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Notons l&amp;#8217;utilisation de &lt;code&gt;body[:account_url]&lt;/code&gt; pour ajouter une variable disponible dans la vue.&lt;/p&gt;

&lt;p&gt;Nous venons de voir les bases de l&amp;#8217;utilisation d&amp;#8217;ActionMailer, couvrant les principaux besoins d&amp;#8217;une application web en terme de création et d&amp;#8217;envoi d&amp;#8217;emails. ActionMailer propose également d&amp;#8217;autres fonctionnalités comme la réception d&amp;#8217;emails ou l&amp;#8217;attachement de pièces jointes sur lesquelles nous reviendrons dans un prochain article.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Annuler la suppression d'un enregistrement avec ActsAsArchive</title>
   <link href="http://www.tutoriaux-rails.com/articles/annuler-la-suppression-d-un-enregistrement-avec-acts-as-archive"/>
   <updated>2010-06-25T00:00:00+02:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/annuler-la-suppression-d-un-enregistrement-avec-acts-as-archive</id>
   <content type="html">&lt;h2 id='raison_et_principe'&gt;Raison et principe&lt;/h2&gt;

&lt;p&gt;&lt;a href='http://www.alistapart.com/articles/neveruseawarning/'&gt;Cet excellent article du site A List Apart&lt;/a&gt; (en anglais) explique en détail pourquoi il est plus judicieux de proposer l&amp;#8217;annulation d&amp;#8217;une action plutôt que d&amp;#8217;en demander confirmation. Pour résumer, à force d&amp;#8217;habitude nous ne lisons plus les messages de confirmation et cliquons machinalement sur &amp;#8220;Ok&amp;#8221;. Une solution est alors d&amp;#8217;accepter directement l&amp;#8217;action effectuée par l&amp;#8217;utilisateur et de lui proposer la possibilité de l&amp;#8217;annuler en cas d&amp;#8217;erreur, comme lors de la suppression d&amp;#8217;un email sur Gmail.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://github.com/winton/acts_as_archive'&gt;ActsAsArchive&lt;/a&gt; permet de déplacer les enregistrements supprimés de la table d&amp;#8217;origine dans une table à part. Si la structure de la table d&amp;#8217;origine est modifiée dans une migration, celle de la table d&amp;#8217;archivage l&amp;#8217;est également. Il offre également la possibilité de restaurer un enregistrement.&lt;/p&gt;

&lt;h2 id='installation'&gt;Installation&lt;/h2&gt;

&lt;p&gt;Nous ajoutons au fichier &lt;code&gt;config/environment.rb&lt;/code&gt; la gem ActsAsArchive, dépaquetons le code et versionnons le tout :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/environnement.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;gem&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;acts_as_archive&amp;#39;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;sudo rake gems:install
    &lt;span class='nv'&gt;$ &lt;/span&gt;rake gems:unpack:dependencies
    &lt;span class='nv'&gt;$ &lt;/span&gt;git add .
    &lt;span class='nv'&gt;$ &lt;/span&gt;git commit -am &lt;span class='s2'&gt;&amp;quot;ActsAsArchive&amp;quot;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='archivage_dun_enregistrement'&gt;Archivage d&amp;#8217;un enregistrement&lt;/h2&gt;

&lt;p&gt;Nous commençons par indiquer au modèle que les suppressions sont gérées par ActsAsArchive :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/post.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Post&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
      &lt;span class='n'&gt;acts_as_archive&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis nous générons un fichier de migration pour créer la table d&amp;#8217;archivage :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    script/generate migration add_acts_as_archive_to_posts
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;# db/migrate/xxxx_add_acts_as_archive_to_posts.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;AddActsAsArchiveToPosts&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Migration&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nc'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nf'&gt;up&lt;/span&gt;
        &lt;span class='no'&gt;ActsAsArchive&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;update&lt;/span&gt; &lt;span class='no'&gt;Post&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nc'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nf'&gt;down&lt;/span&gt;
        &lt;span class='n'&gt;drop_table&lt;/span&gt; &lt;span class='ss'&gt;:archived_posts&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    rake db:migrate
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;La table &lt;code&gt;archived_posts&lt;/code&gt; est créée, elle possède la même structure que &lt;code&gt;posts&lt;/code&gt; et sera mise à jour automatique si la structure de &lt;code&gt;posts&lt;/code&gt; est modifiée dans une future migration.&lt;/p&gt;

&lt;p&gt;À partir de maintenant, tout appel à &lt;code&gt;delete&lt;/code&gt;, &lt;code&gt;destroy&lt;/code&gt; ou &lt;code&gt;delete_all&lt;/code&gt; sur une instance de &lt;code&gt;Post&lt;/code&gt; déplace le(s) enregistrement(s) concerné(s) dans la table &lt;code&gt;archived_posts&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='annulation_de_la_suppression'&gt;Annulation de la suppression&lt;/h2&gt;

&lt;p&gt;ActsAsArchive fournit une méthode &lt;code&gt;restore_all&lt;/code&gt; permettant de restaurer des enregistrements supprimés. Un &lt;code&gt;id&lt;/code&gt; peut lui être passé en paramètre pour spécifier un enregistrement particulier. Une première possibilité pour effectuer une annulation serait de créer une action &lt;code&gt;restore&lt;/code&gt; sur le contrôler &lt;code&gt;PostsController&lt;/code&gt;. Pour nous conformer à la méthode REST, nous allons plutôt considérer cette annulation comme la suppression d&amp;#8217;un &lt;code&gt;ArchivedPost&lt;/code&gt; (action &lt;code&gt;destroy&lt;/code&gt; du contrôleur &lt;code&gt;ArchivedPostsController&lt;/code&gt;. Nous générons ce contrôleur et y ajoutons le code nécessaire :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    script/generate controller archived_posts
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;# app/controllers/archived_posts_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;ArchivedPostsController&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ApplicationController&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;destroy&lt;/span&gt;
        &lt;span class='no'&gt;Post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;restore_all&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;id = ?&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:id&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:success&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Le post a bien été restauré.&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;posts_path&lt;/span&gt; &lt;span class='ow'&gt;and&lt;/span&gt; &lt;span class='k'&gt;return&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Il ne nous reste plus qu&amp;#8217;à afficher un lien vers l&amp;#8217;action d&amp;#8217;annulation dans le message flash de suppression d&amp;#8217;un post :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/posts_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;destroy&lt;/span&gt;
      &lt;span class='vi'&gt;@post&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:id&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;destroy&lt;/span&gt;
        &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:success&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Le post a bien été supprimé. &amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt;
          &lt;span class='vi'&gt;@template&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;button_to&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Annuler&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='ss'&gt;:controller&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:archived_posts&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:destroy&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:id&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vi'&gt;@post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;id&lt;/span&gt;&lt;span class='p'&gt;},&lt;/span&gt; &lt;span class='ss'&gt;:method&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:delete&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;posts_path&lt;/span&gt; &lt;span class='ow'&gt;and&lt;/span&gt; &lt;span class='k'&gt;return&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;La variable &lt;code&gt;@template&lt;/code&gt; permet d&amp;#8217;accéder aux méthodes de helpers disponibles dans les vues pour générer le bouton de suppression. Dans la vue &lt;code&gt;index&lt;/code&gt; du controller &lt;code&gt;PostsController&lt;/code&gt;, nous pouvons alors remplacer le lien de suppression avec confirmation par un simple bouton :&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='vi'&gt;@posts&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;each&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;post&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;title&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;button_to&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Supprimer&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:destroy&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:id&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;id&lt;/span&gt;&lt;span class='p'&gt;},&lt;/span&gt; &lt;span class='ss'&gt;:method&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:delete&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Définir des paramètres de configuration avec SettingsLogic</title>
   <link href="http://www.tutoriaux-rails.com/articles/definir-des-parametres-de-configuration-avec-settingslogic"/>
   <updated>2010-04-16T00:00:00+02:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/definir-des-parametres-de-configuration-avec-settingslogic</id>
   <content type="html">&lt;h2 id='prsentation_de_settingslogic'&gt;Présentation de SettingsLogic&lt;/h2&gt;

&lt;p&gt;&lt;a href='http://github.com/binarylogic/settingslogic'&gt;SettingsLogic&lt;/a&gt; est une gem permettant d&amp;#8217;accéder par l&amp;#8217;intermédiaire d&amp;#8217;une classe au contenu d&amp;#8217;un fichier de configuration au format YAML. Dans ce dernier, nous allons définir tous les paramètres dont nous avons besoin en fonction de chaque environnement, comme par exemple l&amp;#8217;adresse email d&amp;#8217;expédition des message envoyés par le site. La valeur correspondante à l&amp;#8217;environnement en cours sera ensuite disponible dans notre application.&lt;/p&gt;

&lt;h2 id='installation'&gt;Installation&lt;/h2&gt;

&lt;p&gt;Nous ajoutons au fichier &lt;code&gt;config/environment.rb&lt;/code&gt; la gem SettingsLogic, dépaquetons le code et versionnons le tout :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/environnement.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;gem&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;settingslogic&amp;#39;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;sudo rake gems:install
    &lt;span class='nv'&gt;$ &lt;/span&gt;rake gems:unpack:dependencies
    &lt;span class='nv'&gt;$ &lt;/span&gt;git add .
    &lt;span class='nv'&gt;$ &lt;/span&gt;git commit -am &lt;span class='s2'&gt;&amp;quot;SettingsLogic&amp;quot;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configuration'&gt;Configuration&lt;/h2&gt;

&lt;p&gt;Nous commençons par créer la classe &lt;code&gt;Settings&lt;/code&gt; nous permettant d&amp;#8217;accéder aux différents paramètres :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/settings.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Settings&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;Settingslogic&lt;/span&gt;
      &lt;span class='n'&gt;source&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='no'&gt;Rails&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;root&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;/config/application.yml&amp;quot;&lt;/span&gt;
      &lt;span class='n'&gt;namespace&lt;/span&gt; &lt;span class='no'&gt;Rails&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;env&lt;/span&gt;
      &lt;span class='nb'&gt;load&lt;/span&gt;&lt;span class='o'&gt;!&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous voyons ici que le fichier de paramétrage est lu, puis les paramètres sont chargés en fonction de l&amp;#8217;environnement dans lequel est exécutée l&amp;#8217;application.&lt;/p&gt;

&lt;p&gt;Nous créons ensuite deux versions de ce fichier. L&amp;#8217;une &lt;code&gt;application.yml.default&lt;/code&gt; sera versionnée, l&amp;#8217;autre &lt;code&gt;application.yml&lt;/code&gt; ignorée. Cela permet à chaque développeur de définir les paramètres en fonction de son environnement de travail, et de ne pas versionner les paramètres utilisés en production (cf. &lt;a href='/articles/mettre-en-ligne-un-site-chez-alwaysdata-avec-git-et-capistrano'&gt;l&amp;#8217;article sur le déploiement avec Capistrano&lt;/a&gt;).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/application.yml.default&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='yaml'&gt;    &lt;span class='l-Scalar-Plain'&gt;defaults&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='nl'&gt;&amp;amp;defaults&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;emails&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt;
        &lt;span class='l-Scalar-Plain'&gt;contact&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;contact@example.com&lt;/span&gt;
        &lt;span class='l-Scalar-Plain'&gt;from&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;no-reply@example.com&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;par_page&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;10&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;dynamique&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;&amp;lt;%= 1 + 2 %&amp;gt;&lt;/span&gt;

    &lt;span class='l-Scalar-Plain'&gt;development&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='nv'&gt;*defaults&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;par_page&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;20&lt;/span&gt;

    &lt;span class='l-Scalar-Plain'&gt;test&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='nv'&gt;*defaults&lt;/span&gt;

    &lt;span class='l-Scalar-Plain'&gt;production&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='nv'&gt;*defaults&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;# config/application.yml&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='yaml'&gt;    &lt;span class='l-Scalar-Plain'&gt;defaults&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='nl'&gt;&amp;amp;defaults&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;emails&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt;
        &lt;span class='l-Scalar-Plain'&gt;contact&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;contact@monsite.com&lt;/span&gt;
        &lt;span class='l-Scalar-Plain'&gt;from&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;no-reply@monsite.com&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;par_page&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;10&lt;/span&gt;

    &lt;span class='l-Scalar-Plain'&gt;development&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='nv'&gt;*defaults&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;par_page&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;20&lt;/span&gt;

    &lt;span class='l-Scalar-Plain'&gt;test&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='nv'&gt;*defaults&lt;/span&gt;

    &lt;span class='l-Scalar-Plain'&gt;production&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='nv'&gt;*defaults&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous voyons ici que SettingsLogic est flexible, il permet de définir des paramètres imbriqués, d&amp;#8217;utiliser ERB, etc.&lt;/p&gt;

&lt;p&gt;Nous ajoutons au fichier &lt;code&gt;.gitignore&lt;/code&gt; le fichier de configuration :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# .gitignore&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    config/application.yml
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis nous versionnons la classe Settings et les paramètres par défaut :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;git add .
    &lt;span class='nv'&gt;$ &lt;/span&gt;git commit -am &lt;span class='s2'&gt;&amp;quot;Configuration par défaut&amp;quot;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='accs_aux_paramtres'&gt;Accès aux paramètres&lt;/h2&gt;

&lt;p&gt;Nous pouvons maintenant accéder aux paramètres de configuration dans l&amp;#8217;application. Par exemple, pour utiliser les emails dans un formulaire de contact :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/contact_mailer.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;ContactMailer&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActionMailer&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
        &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;contact&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;contact&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
          &lt;span class='n'&gt;subject&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Nouveau contact&amp;quot;&lt;/span&gt;
          &lt;span class='n'&gt;from&lt;/span&gt; &lt;span class='no'&gt;Settings&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;emails&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;from&lt;/span&gt;
          &lt;span class='n'&gt;recipients&lt;/span&gt; &lt;span class='no'&gt;Settings&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;emails&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;contact&lt;/span&gt;
          &lt;span class='n'&gt;sent_on&lt;/span&gt; &lt;span class='no'&gt;Time&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;now&lt;/span&gt;
          &lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='ss'&gt;:contact&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;contact&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;L&amp;#8217;email de contact aura pour expéditeur et destinataire les emails correspondants définis dans le fichier de paramétrage. SettingsLogic permet également de donner une valeur par défaut si un paramètre n&amp;#8217;est pas défini :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;par_page&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Settings&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pagination&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;articles_par_page&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;||=&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ici &lt;code&gt;par_page&lt;/code&gt; aura pour valeur &lt;code&gt;10&lt;/code&gt; car &lt;code&gt;articles_par_page&lt;/code&gt; n&amp;#8217;est pas défini dans les paramètres.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Définir le titre et la description des pages</title>
   <link href="http://www.tutoriaux-rails.com/articles/definir-le-titre-et-la-description-des-pages"/>
   <updated>2010-04-05T00:00:00+02:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/definir-le-titre-et-la-description-des-pages</id>
   <content type="html">&lt;h2 id='paramtrage_du_layout'&gt;Paramétrage du layout&lt;/h2&gt;

&lt;p&gt;Dans le layout principal &lt;code&gt;app/views/application.html.erb&lt;/code&gt;, nous trouvons une ligne un peu particulière :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &amp;lt;head&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;title&amp;gt;Le titre&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;meta name=&amp;quot;description&amp;quot; content=&amp;quot;La description&amp;quot; /&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;div id=&amp;quot;content&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ce &lt;code&gt;yield&lt;/code&gt; définit un emplacement où sera inséré le contenu de la vue actuellement affichée. C&amp;#8217;est en fait un raccourci pour &lt;code&gt;yield :content&lt;/code&gt;, le contenu de la vue étant présent dans le symbole &lt;code&gt;:content&lt;/code&gt;. Nous pouvons utiliser la même technique pour insérer le titre et la description de la page en ajoutant deux symboles &lt;code&gt;:title&lt;/code&gt; et &lt;code&gt;:description&lt;/code&gt; :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &amp;lt;head&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;title&amp;gt;&lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='k'&gt;yield&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:title&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;||&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Le titre par défaut&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x'&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;meta name=&amp;quot;description&amp;quot; content=&amp;quot;&lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='k'&gt;yield&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:description&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;||&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;La description par défaut&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x'&gt;&amp;quot; /&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;div id=&amp;quot;content&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Si &lt;code&gt;:title&lt;/code&gt; ou &lt;code&gt;:description&lt;/code&gt; sont vides, &lt;code&gt;yield&lt;/code&gt; ne retournera rien, sans lever d&amp;#8217;exception. Nous pouvons ainsi omettre de définir le titre ou la description pour une vue donnée, la valeur par défaut indiquée dans le layout étant alors prise en compte.&lt;/p&gt;

&lt;p&gt;Il ne nous reste plus qu&amp;#8217;à renseigner &lt;code&gt;:title&lt;/code&gt; et &lt;code&gt;:description&lt;/code&gt; dans les vues.&lt;/p&gt;

&lt;h2 id='dfinition_depuis_chaque_page'&gt;Définition depuis chaque page&lt;/h2&gt;

&lt;p&gt;Nous utilisons la méthode &lt;a href='http://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html#M001763'&gt;&lt;code&gt;content_for&lt;/code&gt;&lt;/a&gt; qui sert à insérer du contenu dans un symbole. Le contenu de ce symbole est ensuite inséré dans le layout à l&amp;#8217;appel du &lt;code&gt;yield&lt;/code&gt; correspondant. Voyons ce que cela donne dans une vue :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;content_for&lt;/span&gt; &lt;span class='ss'&gt;:title&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      Le titre de la page&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;content_for&lt;/span&gt; &lt;span class='ss'&gt;:description&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      La description de la page&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &amp;lt;p&amp;gt;Le contenu.&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Si nous reprenons le layout vu précédemment, le code HTML suivant est généré :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='html'&gt;    &lt;span class='nt'&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Le titre de la page&lt;span class='nt'&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;lt;meta&lt;/span&gt; &lt;span class='na'&gt;name=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;description&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;content=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;La description de la page&amp;quot;&lt;/span&gt; &lt;span class='err'&gt;%&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;&amp;quot; /&amp;gt;
    &lt;span class='nt'&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;lt;div&lt;/span&gt; &lt;span class='na'&gt;id=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Le contenu.&lt;span class='nt'&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Le seul petit souci est que nous devons ajouter 6 lignes de code à chaque vue. Nous remédions à cela en créant une méthode de helper pour simplifier nos vues :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/helpers/application_helper.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nn'&gt;ApplicationHelper&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;title&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;title&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;content_for&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:title&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;title&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;description&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;description&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;content_for&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:description&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;description&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous vérifions que le helper est inclus dans notre &lt;code&gt;ApplicationController&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/application_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;helper&lt;/span&gt; &lt;span class='ss'&gt;:all&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis nous modifions notre vue en conséquence :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;title&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Le titre de la page&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;description&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;La description de la page&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &amp;lt;p&amp;gt;Le contenu.&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous pouvons maintenant définir facilement le titre et la description de chaque page. Cette combinaison de &lt;code&gt;yield&lt;/code&gt; et &lt;code&gt;content_for&lt;/code&gt; est très pratique pour modifier certains endroits du layout en fonction de la vue, comme par exemple une zone de navigation, une inclusion de javascript, etc.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Mettre en ligne un site chez Alwaysdata avec Git et Capistrano</title>
   <link href="http://www.tutoriaux-rails.com/articles/mettre-en-ligne-un-site-chez-alwaysdata-avec-git-et-capistrano"/>
   <updated>2010-03-29T00:00:00+02:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/mettre-en-ligne-un-site-chez-alwaysdata-avec-git-et-capistrano</id>
   <content type="html">&lt;p&gt;&lt;a href='http://github.com/capistrano/capistrano'&gt;Capistrano&lt;/a&gt; est un outil permettant entre autres de mettre en ligne un site de manière automatique et fiable. Il offe plusieurs avantages intéressants comme la mise à jour de la base de données à partir des migrations et la possibilité de revenir facilement à une version antérieure en cas de problème.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.alwaysdata.com'&gt;Alwaysdata&lt;/a&gt; est aujourd&amp;#8217;hui, à ma connaissance, le seul hébergeur français à proposer un hébergement mutualisé pour Ruby on Rails. Les performances sont bonnes, les outils nombreux (dont un accès SSH complet avec support de git, un accès SFTP et MySQL accessible de l&amp;#8217;extérieur) et le support excellent. Une sauvegarde quotidienne sur 30 jours des fichiers et bases de données est également réalisée de manière automatique.&lt;/p&gt;

&lt;h2 id='prrequis'&gt;Prérequis&lt;/h2&gt;

&lt;p&gt;Par souci de simplicité, nous partons du principe que le code est versionné avec Git, que toutes les gems utilisées sont dépaquetées dans &lt;code&gt;vendor&lt;/code&gt; avec &lt;code&gt;rake gems:unpack:dependencies&lt;/code&gt;, et que Rails est également dépaqueté avec &lt;code&gt;rake rails:freeze:edge RELEASE=x.x.x&lt;/code&gt;. Cela évite notamment de devoir installer toutes les gems sur le serveur et permet de s&amp;#8217;assurer qu&amp;#8217;une mise à jour sur le serveur ne cassera pas notre application. De plus cela permet d&amp;#8217;utiliser une version de Rails différente de celles installées sur Alwaysdata. Pour plus d&amp;#8217;informations, se reporter à &lt;a href='/articles/demarrer-une-nouvelle-application-rails-avec-git-et-un-modele'&gt;l&amp;#8217;article sur le démarrage d&amp;#8217;une application Rails avec Git&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='hbergement_du_dpt_git'&gt;Hébergement du dépôt Git&lt;/h2&gt;

&lt;p&gt;Pour commencer, il nous faut héberger notre dépôt à un emplacement accessible depuis le serveur pour que Capistrano puisse y récupérer la dernière version du code. Par souci de simplicité, nous allons l&amp;#8217;héberger sur notre compte Alwaysdata puisque Git y est disponible.&lt;/p&gt;

&lt;p&gt;Après avoir ouvert un compte, nous activons l&amp;#8217;utilisateur SSH dans la partie &amp;#8220;Accès Distant &amp;gt; SSH&amp;#8221; de la console d&amp;#8217;administration.&lt;/p&gt;

&lt;p&gt;Pour ne pas avoir à saisir le mot de passe à chaque déploiement, nous allons générer une clé publique sur notre poste et la copier sur le serveur.&lt;/p&gt;

&lt;p&gt;Des instructions pour Windows, Mac OS X et Linux sont disponibles sur le &lt;a href='http://wiki.alwaysdata.com/wiki/Se_connecter_en_SSH_avec_sa_clé_publique'&gt;wiki d&amp;#8217;Alwaysdata&lt;/a&gt;. Je reprends ici les indications pour Mac OS X.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Génération de la clé&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;mkdir -p ~/.ssh
    &lt;span class='nv'&gt;$ &lt;/span&gt;chmod 0700 ~/.ssh
    &lt;span class='nv'&gt;$ &lt;/span&gt;ssh-keygen -t dsa -f ~/.ssh/id_dsa
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;# Copie de la clé sur le serveur&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;scp ~/.ssh/id_dsa.pub user@ssh.alwaysdata.com:/home/user
    &lt;span class='nv'&gt;$ &lt;/span&gt;ssh user@ssh.alwaysdata.com
    user@ssh:~&lt;span class='nv'&gt;$ &lt;/span&gt;mkdir -p ~/.ssh
    user@ssh:~&lt;span class='nv'&gt;$ &lt;/span&gt;chmod 0700 ~/.ssh
    user@ssh:~&lt;span class='nv'&gt;$ &lt;/span&gt;cat id_dsa.pub &amp;gt;&amp;gt; ~/.ssh/authorized_keys
    user@ssh:~&lt;span class='nv'&gt;$ &lt;/span&gt;chmod 600 ~/.ssh/authorized_keys
    user@ssh:~&lt;span class='nv'&gt;$ &lt;/span&gt;rm id_dsa.pub
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous pouvons maintenant nous connecter sans mot de passe :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;ssh user@ssh.alwaysdata.com
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Profitons d&amp;#8217;être connectés pour créer le dépôt sur le serveur :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    user@ssh:~&lt;span class='nv'&gt;$ &lt;/span&gt;mkdir -p git/monsite.git
    user@ssh:~&lt;span class='nv'&gt;$ &lt;/span&gt;&lt;span class='nb'&gt;cd &lt;/span&gt;git/monsite.git
    user@ssh:~/git/monsite&lt;span class='nv'&gt;$ &lt;/span&gt;git init --bare
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous venons de créer un dépôt vide prêt à recevoir notre code. Il nous faut maintenant indiquer dans notre dépôt local le chemin vers lequel envoyer le code sur le serveur. Ce dépôt distant est accessible en ssh à l&amp;#8217;adresse &lt;code&gt;ssh://user@ssh.alwaysdata.com/home/user/git/monsite.git&lt;/code&gt;. Nous ajoutons à notre dépôt local l&amp;#8217;adresse du dépôt distant :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;&lt;span class='nb'&gt;cd&lt;/span&gt; ~/Code/monsite
    &lt;span class='nv'&gt;$ &lt;/span&gt;git remote add origin ssh://user@ssh.alwaysdata.com/home/user/git/monsite.git
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Si nous tapons &lt;code&gt;git remote -v&lt;/code&gt; nous voyons l&amp;#8217;adresse du dépôt distant &lt;code&gt;origin&lt;/code&gt; (appelé ainsi par convention). Il ne nous reste plus qu&amp;#8217;à y envoyer notre code :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;git push origin master
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Le site &lt;a href='http://progit.org/book/'&gt;ProGit&lt;/a&gt; propose un &lt;a href='http://progit.org/book/ch2-5.html'&gt;chapitre sur les dépôts distants&lt;/a&gt; pour en savoir plus. Notre code est maintenant accessible, nous pouvons passer à son déploiement avec Capistrano.&lt;/p&gt;

&lt;h2 id='installation_et_configuration_de_capistrano'&gt;Installation et configuration de Capistrano&lt;/h2&gt;

&lt;p&gt;Nous commençons par installer et versionner la gem Capistrano :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/environment.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;gem&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;capistrano&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:lib&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;sudo rake gems:install
    &lt;span class='nv'&gt;$ &lt;/span&gt;rake gems:unpack:dependencies
    &lt;span class='nv'&gt;$ &lt;/span&gt;git add .
    &lt;span class='nv'&gt;$ &lt;/span&gt;git commit -am &lt;span class='s2'&gt;&amp;quot;Ajout de Capistrano&amp;quot;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous utilisons ici &lt;code&gt;:lib =&amp;gt; false&lt;/code&gt; pour indiquer que ces gems n&amp;#8217;ont pas besoin d&amp;#8217;être chargées au lancement du serveur de l&amp;#8217;application. Elles ne sont utilisées qu&amp;#8217;en local pour le déploiement, nous évitons d&amp;#8217;alourdir la charge mémoire du serveur.&lt;/p&gt;

&lt;p&gt;Nous préparons ensuite notre application à être déployée :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;capify .
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Cette commande génère deux fichiers : &lt;code&gt;Capfile&lt;/code&gt; et &lt;code&gt;config/deploy.rb&lt;/code&gt;. &lt;code&gt;Capfile&lt;/code&gt; permet à Capistrano de charger les fichiers contenant les tâches à effectuer pour le déploiement. &lt;code&gt;config/deploy.rb&lt;/code&gt; va contenir les instructions de déploiement de notre site.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/deploy.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:user&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;nom du user ssh&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:application&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;monsite&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:branch&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;master&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:domain&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;ssh.alwaysdata.com&amp;quot;&lt;/span&gt;

    &lt;span class='n'&gt;server&lt;/span&gt; &lt;span class='n'&gt;domain&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:app&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:web&lt;/span&gt;
    &lt;span class='n'&gt;role&lt;/span&gt; &lt;span class='ss'&gt;:db&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;domain&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:primary&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;
    &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:runner&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;user&lt;/span&gt;

    &lt;span class='n'&gt;ssh_options&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:forward_agent&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;
    &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:scm&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:git&lt;/span&gt;
    &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:repository&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;ssh://user@ssh.alwaysdata.com/~/git/monsite.git&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:deploy_via&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:remote_cache&lt;/span&gt;
    &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:git_enable_submodules&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;
    &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:deploy_to&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;/home/user/rails/&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;application&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:keep_releases&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt;
    &lt;span class='n'&gt;default_run_options&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:pty&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;
    &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:use_sudo&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;

    &lt;span class='n'&gt;after&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;deploy:update_code&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
      &lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class='no'&gt;CMD&lt;/span&gt;
&lt;span class='sh'&gt;        ln -nfs #{shared_path}/config/environments/production.rb #{release_path}/config/environments/production.rb&lt;/span&gt;
&lt;span class='no'&gt;      CMD&lt;/span&gt;
      &lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class='no'&gt;CMD&lt;/span&gt;
&lt;span class='sh'&gt;        ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml&lt;/span&gt;
&lt;span class='no'&gt;      CMD&lt;/span&gt;
      &lt;span class='sx'&gt;%w(files sitemap.xml robots.txt dispatch.fcgi .htaccess)&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;each&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;file&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
        &lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class='no'&gt;CMD&lt;/span&gt;
&lt;span class='sh'&gt;          ln -nfs #{shared_path}/public/#{file} #{release_path}/public/#{file}&lt;/span&gt;
&lt;span class='no'&gt;        CMD&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
      &lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;cd &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;release_path&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt; ; rake RAILS_ENV=production gems:build&amp;quot;&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='n'&gt;after&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;deploy&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;deploy:cleanup&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;after&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;deploy:migrations&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;deploy:cleanup&amp;quot;&lt;/span&gt;

    &lt;span class='n'&gt;namespace&lt;/span&gt; &lt;span class='ss'&gt;:deploy&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
      &lt;span class='n'&gt;task&lt;/span&gt; &lt;span class='ss'&gt;:cold&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
        &lt;span class='n'&gt;update&lt;/span&gt;
        &lt;span class='n'&gt;load_schema&lt;/span&gt;
        &lt;span class='n'&gt;start&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='n'&gt;task&lt;/span&gt; &lt;span class='ss'&gt;:load_schema&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:roles&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:app&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
        &lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;cd &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;current_path&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;; rake RAILS_ENV=production db:schema:load&amp;quot;&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='n'&gt;deploy&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;task&lt;/span&gt; &lt;span class='ss'&gt;:start&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
       &lt;span class='c1'&gt;# nothing&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='n'&gt;deploy&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;task&lt;/span&gt; &lt;span class='ss'&gt;:stop&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
      &lt;span class='c1'&gt;# nothing&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='n'&gt;deploy&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;task&lt;/span&gt; &lt;span class='ss'&gt;:restart&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
      &lt;span class='c1'&gt;# nothing&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;La première partie définit un ensemble de variables, je vous invite à consulter &lt;a href='http://wiki.github.com/capistrano/capistrano/significant-configuration-variables'&gt;la documentation des variables principales de Capistrano&lt;/a&gt; ainsi que &lt;a href='http://wiki.github.com/capistrano/capistrano/roles'&gt;celle sur les rôles&lt;/a&gt; pour en savoir plus. Ici nous déployons sur un seul serveur sur lequel se trouve également le dépôt Git, la configuration est donc assez simple. Nous noterons parmi ces variables &lt;code&gt;repository&lt;/code&gt;, &lt;code&gt;:deploy_to&lt;/code&gt; et &lt;code&gt;:keep_releases&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:repository&lt;/code&gt; indique où récupérer le code versionné&lt;/li&gt;

&lt;li&gt;&lt;code&gt;:deploy_to&lt;/code&gt; indique le répertoire propre où sera déployé le code&lt;/li&gt;

&lt;li&gt;&lt;code&gt;:keep_releases&lt;/code&gt; ici à 5 spécifie le nombre de versions du site que nous souhaitons conserver. Capistrano conserve les versions antérieures pour pouvoir revenir en arrière en cas de problème, il nous faut donc nettoyer les anciennes versions sous peine de voir notre espace complètement rempli au bout d&amp;#8217;un certain nombre de déploiements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La deuxième partie indique quoi faire à chaque étape du déploiement.&lt;/p&gt;

&lt;p&gt;La tâche &lt;code&gt;after &amp;#39;deploy:update_code&amp;#39;&lt;/code&gt; est exécutée comme son nom l&amp;#8217;indique une fois que le code a été récupéré depuis Git. Elle crée des liens symboliques vers des fichiers situés dans un répertoire &lt;code&gt;shared_path&lt;/code&gt;. Pourquoi se donner cette peine ? Nous l&amp;#8217;avons vu dans &lt;a href='/articles/demarrer-une-nouvelle-application-rails-avec-git-et-un-modele'&gt;l&amp;#8217;article sur le démarrage d&amp;#8217;une application avec Git&lt;/a&gt;, nous ne versionnons pas les fichiers contenant des données de configuration, seulement une version &amp;#8220;exemple&amp;#8221;, ceci car :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nous souhaitons éviter d&amp;#8217;enregistrer dans Git des données sensibles comme les mots de passe&lt;/li&gt;

&lt;li&gt;nous ne souhaitons pas modifier le code versionné à chaque changement d&amp;#8217;hébergement ou de configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nous allons donc devoir créer ces fichiers dans un répertoire spécial que Capistrano met à notre disposition. Il permet de stocker tous les fichiers qui ne sont pas versionnés mais dont l&amp;#8217;application a besoin : fichiers de configuration, fichiers uploadés par les utilisateurs, etc. Nous y reviendrons dans un instant.&lt;/p&gt;

&lt;p&gt;Nous lançons également à cette étape la compilation des gems avec &lt;code&gt;rake gems:build&lt;/code&gt; au cas où certaines le nécessitent.&lt;/p&gt;

&lt;p&gt;La tâche &lt;code&gt;after &amp;quot;deploy&amp;quot;, &amp;quot;deploy:cleanup&amp;quot;&lt;/code&gt; permet une fois le déploiement terminé de nettoyer les anciennes versions en ne gardant que le nombre indiqué pour &lt;code&gt;:keep_releases&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ensuite nous redéfinissons la tâche &lt;code&gt;cold&lt;/code&gt; du namespace &lt;code&gt;deploy&lt;/code&gt;. Celle-ci est exécutée pour le premier déploiement, nous lui faisons également charger la base de données à l&amp;#8217;aide de la tâche rake &lt;code&gt;db:schema:load&lt;/code&gt; avant de démarrer l&amp;#8217;application.&lt;/p&gt;

&lt;p&gt;Enfin les tâches &lt;code&gt;deploy.task :start&lt;/code&gt;, &lt;code&gt;deploy.task :stop&lt;/code&gt; et &lt;code&gt;deploy.task :restart&lt;/code&gt; sont redéfinies vides car le redémarrage du serveur n&amp;#8217;est pour le moment pas possible en ligne de commande chez Alwaysdata. Ce n&amp;#8217;est pas très grave car il est facile de le faire depuis la console d&amp;#8217;administration, l&amp;#8217;équipe a de plus prévu de le rendre possible en ligne de commande par la suite.&lt;/p&gt;

&lt;p&gt;Il ne nous reste plus qu&amp;#8217;à paramétrer les répertoires nécessaires sur le serveur et vérifier que tout est bien en place avant le déploiement. Capistrano fournit pour cela deux tâches &lt;code&gt;setup&lt;/code&gt; et &lt;code&gt;check&lt;/code&gt; très pratiques que nous exécutons :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;cap deploy:setup
    &lt;span class='nv'&gt;$ &lt;/span&gt;cap deploy:check
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Elles permettent de créer les répertoires nécessaires au fonctionnement de Capistrano et de vérifier que tout est installé correctement.&lt;/p&gt;

&lt;h2 id='paramtrage_sur_le_serveur'&gt;Paramétrage sur le serveur&lt;/h2&gt;

&lt;p&gt;Tout est prêt sur notre poste, il nous reste à créer sur le serveur les divers fichiers de configuration et répertoires partagés de notre application. Nous commençons par nous connecter au serveur et regardons ce qui a été créé par Capistrano :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;ssh user@ssh.alwaysdata.com
    user@ssh:~&lt;span class='nv'&gt;$ &lt;/span&gt;ls rails
    monsite
    user@ssh:~&lt;span class='nv'&gt;$ &lt;/span&gt;&lt;span class='nb'&gt;cd &lt;/span&gt;rails/monsite
    user@ssh:~/rails/monsite&lt;span class='nv'&gt;$ &lt;/span&gt;ls
    releases shared
    user@ssh:~/rails/monsite&lt;span class='nv'&gt;$ &lt;/span&gt;ls shared
    log pids system
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Le répertoire &lt;code&gt;releases&lt;/code&gt; va contenir les différentes version de notre application. Une fois déployée, un lien symbolique &lt;code&gt;current&lt;/code&gt; pointant vers la version actuelle sera créé. À chaque nouveau déploiement, un nouveau répertoire sera créé dans &lt;code&gt;releases&lt;/code&gt; et &lt;code&gt;current&lt;/code&gt; sera modifié pour pointer sur la nouvelle version.&lt;/p&gt;

&lt;p&gt;Le répertoire &lt;code&gt;shared&lt;/code&gt; est utilisé pour stocker tous les fichiers conservés à chaque déploiement, comme les fichiers de logs. Nous avons vu dans &lt;code&gt;config/deploy.rb&lt;/code&gt; une référence à une variable &lt;code&gt;shared_path&lt;/code&gt;, elle correspond à ce répertoire. Nous y créons les répertoires nécessaires :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    user@ssh:~&lt;span class='nv'&gt;$ &lt;/span&gt;&lt;span class='nb'&gt;cd&lt;/span&gt; ~/rails/monsite/shared
    user@ssh:~/rails/monsite/shared&lt;span class='nv'&gt;$ &lt;/span&gt;mkdir public
    user@ssh:~/rails/monsite/shared&lt;span class='nv'&gt;$ &lt;/span&gt;mkdir -p config/environments
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Il nous faut maintenant créer dans le répertoire &lt;code&gt;shared&lt;/code&gt; de chaque environnement un certain nombre de fichiers dont voici la liste :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;config/database.yml&lt;/code&gt; : la configuration de la base de données&lt;/li&gt;

&lt;li&gt;&lt;code&gt;config/environments/production.rb&lt;/code&gt; : la configuration de l&amp;#8217;environnement&lt;/li&gt;

&lt;li&gt;&lt;code&gt;public/.htaccess&lt;/code&gt; : pour rediriger les requêtes sur le processus FCGI&lt;/li&gt;

&lt;li&gt;&lt;code&gt;public/dispatch.fcgi&lt;/code&gt; : nous allons en utiliser une version paramétrée pour Alwaysdata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Voici ci-dessous le contenu de chaque fichier, à saisir soit directement en éditant les fichiers sur le serveur avec un éditeur comme vi, soit en les copiant par SFTP.&lt;/p&gt;

&lt;p&gt;Il faut également créer dans la console d&amp;#8217;administration la base de données.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/database.yml&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='yaml'&gt;    &lt;span class='l-Scalar-Plain'&gt;production&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;adapter&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;mysql&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;database&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;base&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;host&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;mysql.alwaysdata.com&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;username&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;login&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;password&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;password&lt;/span&gt;
      &lt;span class='l-Scalar-Plain'&gt;encoding&lt;/span&gt;&lt;span class='p-Indicator'&gt;:&lt;/span&gt; &lt;span class='l-Scalar-Plain'&gt;utf8&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;# config/environments/production.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;cache_classes&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;

    &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;action_controller&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;consider_all_requests_local&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
    &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;action_controller&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;perform_caching&lt;/span&gt;             &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;
    &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;action_view&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;cache_template_loading&lt;/span&gt;            &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;

    &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;action_mailer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;default_url_options&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='ss'&gt;:host&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;www.monsite.com&amp;#39;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='no'&gt;ActionMailer&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;delivery_method&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='ss'&gt;:smtp&lt;/span&gt;
    &lt;span class='no'&gt;ActionMailer&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;smtp_settings&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='ss'&gt;:address&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;smtp.alwaysdata.com&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
      &lt;span class='ss'&gt;:port&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;25&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
      &lt;span class='ss'&gt;:domain&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;alwaysdata.net&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
      &lt;span class='ss'&gt;:authentication&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:login&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
      &lt;span class='ss'&gt;:user_name&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;login@alwaysdata.net&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
      &lt;span class='ss'&gt;:password&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;password&amp;quot;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;# public/.htaccess&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='apacheconf'&gt;    &lt;span class='nb'&gt;AddHandler&lt;/span&gt; fcgid-script .fcgi
    &lt;span class='nb'&gt;AddHandler&lt;/span&gt; cgi-script .cgi
    &lt;span class='nb'&gt;Options&lt;/span&gt; +FollowSymLinks +ExecCGI

    &lt;span class='nb'&gt;RewriteEngine&lt;/span&gt; &lt;span class='k'&gt;On&lt;/span&gt;

    &lt;span class='nb'&gt;RewriteRule&lt;/span&gt; ^$ index.html [QSA]
    &lt;span class='nb'&gt;RewriteRule&lt;/span&gt; ^([^.]+)$ $1.html [QSA]
    &lt;span class='nb'&gt;RewriteCond&lt;/span&gt; %{REQUEST_FILENAME} !-f
    &lt;span class='nb'&gt;RewriteRule&lt;/span&gt; ^(.*)$ dispatch.fcgi [QSA,L]

    &lt;span class='nb'&gt;ErrorDocument&lt;/span&gt; &lt;span class='m'&gt;500&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&amp;lt;h2&amp;gt;Application error&amp;lt;/h2&amp;gt;Rails application failed to start properly&amp;quot;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;# public/dispatch.fcgi&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='c1'&gt;#!/usr/bin/env ruby&lt;/span&gt;

    &lt;span class='no'&gt;ENV&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;RAILS_ENV&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;production&amp;#39;&lt;/span&gt;
    &lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;dirname&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='bp'&gt;__FILE__&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;/../config/environment&amp;quot;&lt;/span&gt;
    &lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;fcgi_handler&amp;#39;&lt;/span&gt;
    &lt;span class='no'&gt;RailsFCGIHandler&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;process!&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Dans &lt;code&gt;dispatch.fcgi&lt;/code&gt;, nous ajoutons &lt;code&gt;ENV[&amp;#39;RAILS_ENV&amp;#39;] = &amp;#39;production&amp;#39;&lt;/code&gt; pour définir avant le chargement de l&amp;#8217;application l&amp;#8217;environnement dans lequel elle doit s&amp;#8217;exécuter.&lt;/p&gt;

&lt;p&gt;Pour le mot de passe de la base de données, dans la console d&amp;#8217;administration :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;cliquer sur &amp;#8220;MySQL&amp;#8221; dans la partie &amp;#8220;Base de données&amp;#8221;&lt;/li&gt;

&lt;li&gt;cliquer sur &amp;#8220;Gestion des utilisateurs&amp;#8221;&lt;/li&gt;

&lt;li&gt;cliquer sur &amp;#8220;Modifier&amp;#8221; sur l&amp;#8217;utilisateur du même nom que le pack&lt;/li&gt;

&lt;li&gt;modifier le mot de passe et le reporter dans le fichier &lt;code&gt;config/database.yml&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pour le mot de passe des emails, dans la console d&amp;#8217;administration :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;cliquer sur &amp;#8220;Emails&amp;#8221;&lt;/li&gt;

&lt;li&gt;cliquer sur &amp;#8220;Modifier&amp;#8221; sur l&amp;#8217;utilisateur du même nom que le pack dans la partie &amp;#8220;alwaysdata.net&amp;#8221;&lt;/li&gt;

&lt;li&gt;modifier le mot de passe et le reporter dans le fichier &lt;code&gt;config/environments/production.rb&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Une fois ces fichiers créés, il faut rendre le fichier &lt;code&gt;dispatch.fcgi&lt;/code&gt; exécutable :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    user@ssh:~&lt;span class='nv'&gt;$ &lt;/span&gt;chmod +x /home/login/rails/monsite/shared/public/dispatch.fcgi
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='dploiement_de_lapplication'&gt;Déploiement de l&amp;#8217;application&lt;/h2&gt;

&lt;p&gt;Tout est prêt, nous pouvons lancer le premier déploiement depuis notre poste :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    cap deploy:cold
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Cela prend un peu de temps car tout est initialisé pour la première fois ; les déploiements suivants seront plus rapides.&lt;/p&gt;

&lt;p&gt;Pour accéder à notre site il faut maintenant faire pointer le domaine sur le répertoire &lt;code&gt;public&lt;/code&gt; de l&amp;#8217;environnement. Pour cela, nous nous rendons dans la console d&amp;#8217;administration dans la rubrique &amp;#8220;Domaines&amp;#8221;. Si un domaine est enregistré, il faut faire pointer &lt;code&gt;www&lt;/code&gt; sur &lt;code&gt;/rails/monsite/current/public&lt;/code&gt;. Si aucun domaine n&amp;#8217;est installé, il faut faire pointer le domaine &lt;code&gt;nomdupack.alwaysdata.net&lt;/code&gt; sur &lt;code&gt;/rails/monsite/current/public&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nous pouvons alors nous rendre sur le site, et si tout s&amp;#8217;est bien passé nous devrions voir la page d&amp;#8217;accueil de notre application.&lt;/p&gt;

&lt;p&gt;En cas d&amp;#8217;erreur, une première piste est de se connecter au serveur en ssh et de lancer le fichier &lt;code&gt;dispatch.fcgi&lt;/code&gt; pour voir si une erreur se produit :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    user@ssh:/rails/monsite/current/public&lt;span class='nv'&gt;$ &lt;/span&gt;./dispatch.fcgi
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Les erreurs FCGI sont également enregistrées dans &lt;code&gt;shared/log/fastcgi.crash.log&lt;/code&gt;. Les autres erreurs sont enregistrées dans le fichier &lt;code&gt;shared/log/production.log&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='et_ensuite_'&gt;Et ensuite ?&lt;/h2&gt;

&lt;p&gt;Tout ceci semble peut-être représenter un gros travail pour une &amp;#8220;simple&amp;#8221; mise en ligne, mais les avantages sont déjà nombreux. Lors d&amp;#8217;une mise à jour, il n&amp;#8217;y a plus de risque d&amp;#8217;oublier un fichier lors de grosses mises à jour ou de risquer qu&amp;#8217;un visiteur se rende sur le site et rencontre une erreur.&lt;/p&gt;

&lt;p&gt;Les déploiements suivants se font de manière très simple et entièrement automatique :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nv'&gt;$ &lt;/span&gt;git push origin master
    &lt;span class='nv'&gt;$ &lt;/span&gt;cap deploy
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Lorsque par la suite des migrations ont eu lieu, il suffit de lancer &lt;code&gt;cap deploy:migrations&lt;/code&gt; au lieu de &lt;code&gt;cap deploy&lt;/code&gt; et elles seront appliquées sur la base en ligne. En cas d&amp;#8217;erreur, &lt;code&gt;cap deploy:rollback&lt;/code&gt; permet de revenir en arrière.&lt;/p&gt;

&lt;p&gt;La seule chose qui reste aujourd&amp;#8217;hui manuelle est le redémarrage du processus FCGI dans la console d&amp;#8217;administration à la rubrique &amp;#8220;Avancé &amp;gt; Processus&amp;#8221; en cliquant sur &amp;#8220;Terminer tous&amp;#8221;. Lorsque le redémarrage sera possible en ligne de commande, il suffira de modifier la tâche &lt;code&gt;deploy.task :restart&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cette méthode est une base pouvant être améliorée en fonction des besoins. Par exemple, nous avons utilisé dans &lt;code&gt;config/deploy.rb&lt;/code&gt; plusieurs liens symboliques qui seront vraisemblablement réutilisés pour chaque nouvelle application. Nous pouvons donc envisager de les regrouper dans un plugin versionné à part que nous incluerons ensuite dans nos applications pour en simplifier le déploiement. De même, une tâche s&amp;#8217;occupant de créer les répertoires et fichiers dans &lt;code&gt;shared&lt;/code&gt; serait un ajout utile à ce plugin. Avec quelques petites modfications, il est facile de déployer sur plusieurs environnements pour avoir également un site de test permettant la validation de modifications par le client avant leur passage en production. Ces sujets feront l&amp;#8217;objet de prochains articles.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Réinitialiser le mot de passe d'un utilisateur avec Authlogic</title>
   <link href="http://www.tutoriaux-rails.com/articles/reinitialiser-le-mot-de-passe-d-un-utilisateur-avec-authlogic"/>
   <updated>2010-03-22T00:00:00+01:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/reinitialiser-le-mot-de-passe-d-un-utilisateur-avec-authlogic</id>
   <content type="html">&lt;p&gt;Cet article s&amp;#8217;appuie sur le &lt;a href='http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic/'&gt;tutorial de Ben Johnson&lt;/a&gt; et fait suite aux précédents articles sur &lt;a href='/articles/inscription-et-connexion-d-un-utilisateur-avec-authlogic/'&gt;l&amp;#8217;inscription&lt;/a&gt; et sur &lt;a href='/articles/activation-d-un-compte-utilisateur-avec-authlogic/'&gt;l&amp;#8217;activation&lt;/a&gt; d&amp;#8217;un compte utilisateur.&lt;/p&gt;

&lt;p&gt;Le processus de réinitialisation d&amp;#8217;un mot de passe suit les étapes suivantes :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;l&amp;#8217;utilisateur demande la réinitialisation de son mot de passe&lt;/li&gt;

&lt;li&gt;un email contenant un lien de réinitialisation lui est envoyé&lt;/li&gt;

&lt;li&gt;l&amp;#8217;utilisateur clique sur le lien et arrive sur un formulaire où saisir son nouveau mot de passe&lt;/li&gt;

&lt;li&gt;une fois le mot de passe modifié l&amp;#8217;utilisateur est automatiquement connecté et le lien ayant servi à la réinitialisation est expiré&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id='vrification_de_la_prsence_des_champs_ncessaires'&gt;Vérification de la présence des champs nécessaires&lt;/h3&gt;

&lt;p&gt;Nous allons avoir besoin de deux champs &lt;code&gt;email&lt;/code&gt; et &lt;code&gt;perishable_token&lt;/code&gt; sur le modèle &lt;code&gt;User&lt;/code&gt;. Si vous avez suivi &lt;a href='/articles/inscription-et-connexion-d-un-utilisateur-avec-authlogic/'&gt;le tutorial sur l&amp;#8217;inscription d&amp;#8217;un utilisateur&lt;/a&gt; ces champs sont déjà présents et vous pouvez passer à l&amp;#8217;étape suivante. Sinon, ajoutons-les à l&amp;#8217;aide d&amp;#8217;une migration.&lt;/p&gt;

&lt;p&gt;Commençons par générer le fichier de migration :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    script/generate migration add_users_passwords_reset_fields
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous ajoutons ensuite au fichier les champs nécessaires :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# db/migrate/xxx_add_users_passwords_reset_fields.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;AddUsersPasswordResetFields&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Migration&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nc'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nf'&gt;up&lt;/span&gt;
        &lt;span class='n'&gt;add_column&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:perishable_token&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:string&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:default&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:null&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
        &lt;span class='n'&gt;add_column&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:email&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:string&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:default&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:null&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
        &lt;span class='n'&gt;add_index&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:perishable_token&lt;/span&gt;
        &lt;span class='n'&gt;add_index&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:email&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nc'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nf'&gt;down&lt;/span&gt;
        &lt;span class='n'&gt;remove_column&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:perishable_token&lt;/span&gt;
        &lt;span class='n'&gt;remove_column&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:email&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Appliquons enfin la migration :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    rake db:migrate
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Le modèle User est maintenant prêt, nous pouvons passer à l&amp;#8217;étape suivante.&lt;/p&gt;

&lt;h3 id='demande_de_rinitialisation_du_mot_de_passe'&gt;Demande de réinitialisation du mot de passe&lt;/h3&gt;

&lt;p&gt;Nous allons avoir besoin d&amp;#8217;un formulaire permettant à un utilisateur de saisir son email pour recevoir le lien de réinitialisation. Pour nous conformer à la méthode REST, nous allons créer une resource &lt;code&gt;PasswordReset&lt;/code&gt;. Une demande de réinitialisation correspond alors à la création d&amp;#8217;une &lt;code&gt;PasswordReset&lt;/code&gt; (action &lt;code&gt;create&lt;/code&gt; du contrôleur &lt;code&gt;PasswordResetsController&lt;/code&gt;). Nous créons ce contrôleur :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    script/generate controller password_resets
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous y ajoutons deux actions &lt;code&gt;new&lt;/code&gt; et &lt;code&gt;create&lt;/code&gt; correspondant respectivement à l&amp;#8217;affichage du formulaire et à son traitement :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/password_resets_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;PasswordResetsController&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ApplicationController&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;new&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create&lt;/span&gt;
        &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find_by_email&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:email&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;
          &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;deliver_password_reset_instructions!&lt;/span&gt;
          &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:succes&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Les instructions vous permettant de réinitialiser votre mot de passe vous ont été envoyées par email.&amp;quot;&lt;/span&gt;
          &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;root_url&lt;/span&gt;
        &lt;span class='k'&gt;else&lt;/span&gt;
          &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:avertissement&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Aucun utilisateur n&amp;#39;a été trouvé avec cette adresse email.&amp;quot;&lt;/span&gt;
          &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:new&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;La méthode &lt;code&gt;deliver_password_reset_instructions!&lt;/code&gt; initialise le champ &lt;code&gt;perishable_token&lt;/code&gt; et envoie un email contenant le lien de réinitialisation. Voyons le code de cette méthode dans le modèle &lt;code&gt;User&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;User&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;deliver_password_reset_instructions!&lt;/span&gt;
        &lt;span class='n'&gt;reset_perishable_token!&lt;/span&gt;
        &lt;span class='no'&gt;UserMailer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;deliver_password_reset_instructions&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;La méthode &lt;code&gt;reset_perishable_token!&lt;/code&gt; est fournie par Authlogic, elle génère un nouveau &lt;code&gt;perishable_token&lt;/code&gt; et sauvegarde l&amp;#8217;enregistrement.&lt;/p&gt;

&lt;p&gt;Nous ajoutons au &lt;code&gt;UserMailer&lt;/code&gt; créé dans &lt;a href='/articles/inscription-et-connexion-d-un-utilisateur-avec-authlogic/'&gt;le précédent article sur l&amp;#8217;inscription d&amp;#8217;un utilisateur&lt;/a&gt; le code suivant :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user_mailer.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UserMailer&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActionMailer&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;password_reset_instructions&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;subject&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Instructions pour la réinitialisation de votre mot de passe&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;from&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;no-reply@example.com&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;recipients&lt;/span&gt; &lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;email&lt;/span&gt;
        &lt;span class='n'&gt;sent_on&lt;/span&gt; &lt;span class='no'&gt;Time&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;now&lt;/span&gt;
        &lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='ss'&gt;:edit_password_reset_url&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;edit_password_reset_url&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;perishable_token&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;L&amp;#8217;adresse &lt;code&gt;edit_password_reset_url&lt;/code&gt; correspond au formulaire de saisie de nouveau mot de passe que nous allons créer dans un instant. Il ne nous manque plus pour cette étape que le contenu de l&amp;#8217;email, du formulaire et la route permettant d&amp;#8217;accéder au différentes actions. Commençons par l&amp;#8217;email :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/user_mailer/password_reset_instructions.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    Une demande de réinitialisation de mot de passe a été faite pour votre compte sur le site example.com.&lt;/span&gt;

&lt;span class='x'&gt;    Si vous n&amp;#39;avez pas effectué cette demande, vous pouvez ignorer cet email&lt;/span&gt;

&lt;span class='x'&gt;    Si vous avez effectué cette demande, il vous suffit de cliquer sur le lien ci-dessous pour indiquer votre nouveau mot de passe.&lt;/span&gt;

&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='vi'&gt;@edit_password_reset_url&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;

&lt;span class='x'&gt;    Si l&amp;#39;adresse ci-dessus ne fonctionne pas, tentez de la copier / coller directement dans votre navigateur.&lt;/span&gt;

&lt;span class='x'&gt;    Si vous rencontrez un problème, n&amp;#39;hésitez pas à nous contacter.&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis le formulaire :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/password_resets/new.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &amp;lt;h1&amp;gt;Mot de passe oublié ?&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class='x'&gt;    &amp;lt;p&amp;gt;Indiquez votre email ci-dessous et les instructions vous permettant de réinitialiser votre mot de passe vous seront envoyées.&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;form_tag&lt;/span&gt; &lt;span class='n'&gt;password_resets_path&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &amp;lt;label&amp;gt;Email&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;text_field_tag&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;email&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;submit_tag&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Réinitialiser mon mot de passe&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Et enfin les routes :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/routes.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;resources&lt;/span&gt; &lt;span class='ss'&gt;:password_resets&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Un utilisateur peut maintenant demander la réinitialisation de son mot de passe vers laquelle nous pouvons créer un lien avec la méthode &lt;code&gt;new_password_reset_url&lt;/code&gt;. Voyons maintenant ce qu&amp;#8217;il se passe une fois l&amp;#8217;email reçu.&lt;/p&gt;

&lt;h3 id='rinitialisation_du_mot_de_passe'&gt;Réinitialisation du mot de passe&lt;/h3&gt;

&lt;p&gt;Lorsque l&amp;#8217;utilisateur clique sur le lien contenu dans l&amp;#8217;email, il est envoyé sur l&amp;#8217;action &lt;code&gt;edit&lt;/code&gt; du contrôleur &lt;code&gt;PasswordResets&lt;/code&gt; pour modifier son mot de passe. Nous lui ajoutons le code nécessaire :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/password_resets_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;before_filter&lt;/span&gt; &lt;span class='ss'&gt;:load_user_using_perishable_token&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:only&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:edit&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:update&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;

    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;edit&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;update&lt;/span&gt;
      &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;password&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:user&lt;/span&gt;&lt;span class='o'&gt;][&lt;/span&gt;&lt;span class='ss'&gt;:password&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
      &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;password_confirmation&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:user&lt;/span&gt;&lt;span class='o'&gt;][&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='n'&gt;password_confirmation&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;save&lt;/span&gt;
        &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:notice&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Le mot de passe a bien été modifié&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;account_url&lt;/span&gt;
      &lt;span class='k'&gt;else&lt;/span&gt;
        &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:avertissement&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Le mot de passe n&amp;#39;a pas pu être modifié&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:edit&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='kp'&gt;private&lt;/span&gt;

    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;load_user_using_perishable_token&lt;/span&gt;
      &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find_using_perishable_token&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:id&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;
        &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:notice&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Nous sommes désolés, nous n&amp;#39;avons pas pu retrouver votre compte. &amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt;
        &lt;span class='s2'&gt;&amp;quot;Si vous rencontrez un problème, tentez de copier / coller l&amp;#39;adresse &amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt;
        &lt;span class='s2'&gt;&amp;quot;depuis l&amp;#39;email dans votre navigateur, ou recommencez &amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt;
        &lt;span class='s2'&gt;&amp;quot;le processus de réinitialisation du mot de passe&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;root_url&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;La méthode &lt;code&gt;load_user_using_perishable_token&lt;/code&gt; permet de retrouver l&amp;#8217;utilisateur à partir du &lt;code&gt;perishable_token&lt;/code&gt; contenu dans le lien. Elle utilise la méthode &lt;code&gt;find_using_perishable_token&lt;/code&gt; fournie par Authlogic ; cette méthode s&amp;#8217;assure que le token utilisé n&amp;#8217;est pas vide et est toujours valide, Authlogic expirant automatiquement les tokens au bout de 10 minutes.&lt;/p&gt;

&lt;p&gt;L&amp;#8217;utilisateur est retrouvé avant l&amp;#8217;appel aux deux actions &lt;code&gt;edit&lt;/code&gt; et &lt;code&gt;update&lt;/code&gt; grâce au &lt;code&gt;before_filter&lt;/code&gt;. Si la modification du mot de passe réussit, l&amp;#8217;utilisateur est automatiquement connecté grâce à Authlogic.&lt;/p&gt;

&lt;p&gt;Nous créons le formulaire de réinitialisation du mot de passe :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/password_resets/edit.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &amp;lt;h1&amp;gt;Modifier mon mot de passe&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;form_for&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:url&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;password_reset_path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:method&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:put&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;error_messages&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='ss'&gt;:password&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Mot de passe&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;password_field&lt;/span&gt; &lt;span class='ss'&gt;:password&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='ss'&gt;:password_confirmation&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Saisissez à nouveau votre mot de passe&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;password_field&lt;/span&gt; &lt;span class='ss'&gt;:password_confirmation&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;submit&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Modifier mon mot de passe et me connecter&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Il ne nous reste plus qu&amp;#8217;à restreindre l&amp;#8217;accẻs en s&amp;#8217;assurant que seul un utilisateur non connecté peut réinitialiser son mot de passe. Nous allons pour cela ajouter un autre &lt;code&gt;before_filter&lt;/code&gt; appelant une méthode &lt;code&gt;require_no_user&lt;/code&gt; présente dans &lt;code&gt;ApplicationController&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/application_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;require_no_user&lt;/span&gt;
      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;current_user&lt;/span&gt;
        &lt;span class='n'&gt;store_location&lt;/span&gt;
        &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:avertissement&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Vous devez être déconnecté pour accéder à cette page&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;root_url&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;store_location&lt;/span&gt;
      &lt;span class='n'&gt;session&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:return_to&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;request&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;request_uri&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;# app/controllers/password_resets_controller&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;before_filter&lt;/span&gt; &lt;span class='ss'&gt;:require_no_user&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nos utilisateurs ont maintenant la possibilité de réinitialiser leur mot de passe de manière simple, sûre et conforme à la méthode REST.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Traduire les messages et les dates en français</title>
   <link href="http://www.tutoriaux-rails.com/articles/traduire-les-messages-et-les-dates-en-francais"/>
   <updated>2010-03-15T00:00:00+01:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/traduire-les-messages-et-les-dates-en-francais</id>
   <content type="html">&lt;h3 id='rcupration_des_traductions_depuis_github'&gt;Récupération des traductions depuis GitHub&lt;/h3&gt;

&lt;p&gt;Rails utilise un système basé sur un fichier YAML ou ruby contenant les traductions de toutes les chaînes du cœur. Des traductions dans un grand nombre de langues dont le français sont disponibles dans un dépôt Git disponible sur GitHub. Nous commençons par cloner ce dépôt pour pouvoir facilement récupérer les mises à jour par la suite.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nb'&gt;cd&lt;/span&gt; ~/Code &lt;span class='c'&gt;# ou tout autre répertoire de votre choix&lt;/span&gt;
    git clone git://github.com/svenfuchs/rails-i18n.git
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Si vous ne disposez pas de Git, des explications pour l&amp;#8217;installer sont disponibles pour &lt;a href='/articles/installation-d-un-environnement-de-developpement-rails-sur-mac-os-x'&gt;Mac OS X&lt;/a&gt;, &lt;a href='/articles/installation-d-un-environnement-de-developpement-sur-windows-xp'&gt;Windows&lt;/a&gt; et &lt;a href='/articles/installation-d-un-environnement-de-developpement-sur-linux-ubuntu'&gt;Linux Ubuntu&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Si nous regardons le code que nous venons de cloner, nous trouvons l&amp;#8217;ensemble des traductions dans le répertoire &lt;code&gt;rails/locale&lt;/code&gt;. Nous copions le fichier &lt;code&gt;fr.yml&lt;/code&gt; qui nous intéresse dans le répertoire &lt;code&gt;config/locales&lt;/code&gt; de notre application.&lt;/p&gt;

&lt;h3 id='configuration_de_lapplication'&gt;Configuration de l&amp;#8217;application&lt;/h3&gt;

&lt;p&gt;Il nous faut maintenant indiquer à Rails que la locale par défaut est le français. Il nous suffit pour cela de modifier une ligne se trouvant à la fin du fichier &lt;code&gt;config/environment.rb&lt;/code&gt; :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;i18n&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;default_locale&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='ss'&gt;:fr&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Une fois le serveur relancé, les messages et dates s&amp;#8217;affichent en français. Simple, non ?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Avertir l'utilisateur grâce aux messages flash</title>
   <link href="http://www.tutoriaux-rails.com/articles/avertir-l-utilisateur-grace-aux-messages-flash"/>
   <updated>2010-03-07T00:00:00+01:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/avertir-l-utilisateur-grace-aux-messages-flash</id>
   <content type="html">&lt;p&gt;Nous allons définir deux types de messages : succès (vert) et avertissement (orange).&lt;/p&gt;

&lt;h3 id='cration_des_messages'&gt;Création des messages&lt;/h3&gt;

&lt;p&gt;La création de messages est très simple, il suffit dans une action de contrôleur de stocker dans &lt;code&gt;flash&lt;/code&gt; le contenu et le type de notre message :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:succes&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;L&amp;#39;article a bien été créé&amp;quot;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;De même pour créer un message d&amp;#8217;avertissement :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:avertissement&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Tous les champs obligatoires ne sont pas remplis&amp;quot;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous aurons accès à &lt;code&gt;flash[:succes]&lt;/code&gt; dans la vue lors de la requête suivante.&lt;/p&gt;

&lt;h3 id='affichage_des_messages'&gt;Affichage des messages&lt;/h3&gt;

&lt;p&gt;Nous ajoutons à notre gabarit un bloc affichant les messages présents dans &lt;code&gt;flash&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/layouts/application.html.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;each&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;key&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;msg&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;content_tag&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:div&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;content_tag&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:p&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;msg&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='ss'&gt;:class&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;message &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;key&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ce bloc va générer pour notre précédent message de succès le code HTML suivant :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='html'&gt;    &lt;span class='nt'&gt;&amp;lt;div&lt;/span&gt; &lt;span class='na'&gt;class=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;lt;div&lt;/span&gt; &lt;span class='na'&gt;class=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;succes&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;p&amp;gt;&lt;/span&gt;L&amp;#39;article a bien été créé&lt;span class='nt'&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Et pour le message d&amp;#8217;avertissement :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='html'&gt;    &lt;span class='nt'&gt;&amp;lt;div&lt;/span&gt; &lt;span class='na'&gt;class=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;lt;div&lt;/span&gt; &lt;span class='na'&gt;class=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;avertissement&amp;quot;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;p&amp;gt;&lt;/span&gt;L&amp;#39;article a bien été créé&lt;span class='nt'&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Il ne nous reste plus qu&amp;#8217;à styler ce bloc pour différencier les types de messages :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# public/stylesheets/&amp;lt;fichier css&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='css'&gt;    &lt;span class='nc'&gt;.message&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='k'&gt;margin-bottom&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='m'&gt;10px&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='nc'&gt;.message&lt;/span&gt; &lt;span class='nt'&gt;div&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='k'&gt;padding&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='m'&gt;10px&lt;/span&gt; &lt;span class='m'&gt;10px&lt;/span&gt; &lt;span class='m'&gt;15px&lt;/span&gt; &lt;span class='m'&gt;50px&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='nc'&gt;.message&lt;/span&gt; &lt;span class='nc'&gt;.succes&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='k'&gt;border&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='m'&gt;1px&lt;/span&gt; &lt;span class='k'&gt;solid&lt;/span&gt; &lt;span class='m'&gt;#2b8a0d&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      &lt;span class='k'&gt;background&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='sx'&gt;url(/images/succes.gif)&lt;/span&gt; &lt;span class='m'&gt;10px&lt;/span&gt; &lt;span class='m'&gt;5px&lt;/span&gt; &lt;span class='k'&gt;no-repeat&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      &lt;span class='k'&gt;color&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='m'&gt;#2b8a0d&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='nc'&gt;.message&lt;/span&gt; &lt;span class='nc'&gt;.avertissement&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='k'&gt;border&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='m'&gt;1px&lt;/span&gt; &lt;span class='k'&gt;solid&lt;/span&gt; &lt;span class='m'&gt;#dd4f00&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      &lt;span class='k'&gt;background&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='sx'&gt;url(/images/avertissement.gif)&lt;/span&gt; &lt;span class='m'&gt;10px&lt;/span&gt; &lt;span class='m'&gt;5px&lt;/span&gt; &lt;span class='k'&gt;no-repeat&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
      &lt;span class='k'&gt;color&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='m'&gt;#dd4f00&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='nc'&gt;.message&lt;/span&gt; &lt;span class='nt'&gt;p&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='k'&gt;font-weight&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='k'&gt;bold&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='rsultat'&gt;Résultat&lt;/h3&gt;

&lt;p&gt;Messages :&lt;/p&gt;

&lt;p&gt;&lt;img src='http://img.skitch.com/20091029-86ber765rjpm53d3nwgyym7c7g.jpg' alt='Message de succès' /&gt; &lt;img src='http://img.skitch.com/20091029-b4r1x7iepyhuw5kwc4h1jiys68.jpg' alt='Message davertissement' /&gt;&lt;/p&gt;

&lt;p&gt;Icônes :&lt;/p&gt;

&lt;p&gt;&lt;img src='http://img.skitch.com/20091029-gkbn8pwa8367fn8rjrhbbfqjr1.jpg' alt='Icône succès' /&gt; &lt;img src='http://img.skitch.com/20091029-pun2heucqdj8duu7i4yxxkek49.jpg' alt='Icône avertissement' /&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Activation d'un compte utilisateur avec Authlogic</title>
   <link href="http://www.tutoriaux-rails.com/articles/activation-d-un-compte-utilisateur-avec-authlogic"/>
   <updated>2010-03-04T00:00:00+01:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/activation-d-un-compte-utilisateur-avec-authlogic</id>
   <content type="html">&lt;p&gt;Cet article est une traduction adaptée du &lt;a href='http://github.com/matthooks/authlogic-activation-tutorial'&gt;tutorial de Matt Hooks&lt;/a&gt; et fait suite au &lt;a href='/articles/inscription-et-connexion-d-un-utilisateur-avec-authlogic'&gt;précédent article&lt;/a&gt; sur l&amp;#8217;inscription et la connexion d&amp;#8217;utilisateurs.&lt;/p&gt;

&lt;h3 id='prparation_du_modle_user'&gt;Préparation du modèle User&lt;/h3&gt;

&lt;p&gt;Nous allons ajouter au modèle User une colonne &lt;code&gt;actif&lt;/code&gt; qui indiquera si l&amp;#8217;utilisateur a vérifié son adresse email. Nous commençons par créer une migration :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    script/generate migration add_actif_to_user actif:boolean
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Rails reconnaît dans cette commande que nous souhaitons ajouter à la table &lt;code&gt;users&lt;/code&gt; une colonne &lt;code&gt;actif&lt;/code&gt; stockant un booléen. Il génère le fichier suivant :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# db/migrate/xxxx_add_actif_to_users.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;AddActifToUsers&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Migration&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nc'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nf'&gt;up&lt;/span&gt;
        &lt;span class='n'&gt;add_column&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:actif&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:boolean&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nc'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nf'&gt;down&lt;/span&gt;
        &lt;span class='n'&gt;remove_column&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:actif&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous modifions la ligne &lt;code&gt;add_column&lt;/code&gt; pour spécifier que la colonne est à &lt;code&gt;false&lt;/code&gt; par défaut, et ne peut être nulle :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;add_column&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:actif&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:boolean&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:default&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:null&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous appliquons la migration sur la base de données :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    rake db:migrate
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Authlogic exécute automatiquement la méthode &lt;code&gt;active?&lt;/code&gt; si elle est présente sur le modèle. Nous modifions le modèle User pour ajouter cette méthode, et nous en profitons pour empêcher l&amp;#8217;assignation en masse des attributs sensibles. Cela évitera qu&amp;#8217;un utilisateur puisse activer son compte en envoyant un formulaire créé de toute pièce (&lt;a href='http://railspikes.com/2008/9/22/is-your-rails-application-safe-from-mass-assignment'&gt;en savoir plus sur &lt;code&gt;attr_accessible&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;User&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;

      &lt;span class='n'&gt;attr_accessible&lt;/span&gt; &lt;span class='ss'&gt;:email&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:password&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:password_confirmation&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;active?&lt;/span&gt;
        &lt;span class='n'&gt;actif&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Si nous essayons de nous connecter après nous être inscrit, nous recevons comme prévu un message nous indiquant que notre compte n&amp;#8217;est pas actif.&lt;/p&gt;

&lt;h3 id='activation_dun_compte_utilisateur'&gt;Activation d&amp;#8217;un compte utilisateur&lt;/h3&gt;

&lt;p&gt;Nous allons utiliser le &lt;code&gt;perishable_token&lt;/code&gt; fourni par Authlogic pour le processus d&amp;#8217;activation. Lorsqu&amp;#8217;un utilisateur s&amp;#8217;inscrit, il reçoit un email contenant un lien unique d&amp;#8217;activation valable pendant un certain temps (ici une semaine). Ce lien contient le &lt;code&gt;perishable_token&lt;/code&gt; de l&amp;#8217;utilisateur et nous permet de le retrouver. Il n&amp;#8217;a plus qu&amp;#8217;à cliquer sur &amp;#8220;Activer mon compte&amp;#8221; pour pouvoir se connecter.&lt;/p&gt;

&lt;p&gt;Nous commençons par modifier l&amp;#8217;action &lt;code&gt;create&lt;/code&gt; du contrôleur &lt;code&gt;UsersController&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/users_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create&lt;/span&gt;
      &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:user&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

      &lt;span class='c1'&gt;# le user n&amp;#39;est pas encore activé, on désactive le login automatique&lt;/span&gt;
      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;save_without_session_maintenance&lt;/span&gt;
       &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;deliver_activation_instructions!&lt;/span&gt;
       &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:notice&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Votre compte a bien été créé.&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt;
         &lt;span class='s2'&gt;&amp;quot;Vous allez recevoir un email contenant les instructions pour l&amp;#39;activer.&amp;quot;&lt;/span&gt;
       &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;root_url&lt;/span&gt;
      &lt;span class='k'&gt;else&lt;/span&gt;
       &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:new&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis nous créons un contrôleur &lt;code&gt;ActivationsController&lt;/code&gt; chargé de gérer le processus d&amp;#8217;activation. Il contient deux actions :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new&lt;/code&gt; retrouve l&amp;#8217;utilisateur à partir du &lt;code&gt;perishable_token&lt;/code&gt; et lui présente le formulaire &amp;#8220;Activer mon compte&amp;#8221;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;create&lt;/code&gt; active l&amp;#8217;utilisateur et lui envoie l&amp;#8217;email de confirmation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nous créons ce contrôleur :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    script/generate controller activations new create
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis nous y ajoutons le code des deux actions :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/activations_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;ActivationsController&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ApplicationController&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;new&lt;/span&gt;
        &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find_using_perishable_token&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:activation_code&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;week&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;||&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;raise&lt;/span&gt; &lt;span class='no'&gt;Exception&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='k'&gt;raise&lt;/span&gt; &lt;span class='no'&gt;Exception&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;active?&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create&lt;/span&gt;
        &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:id&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

        &lt;span class='k'&gt;raise&lt;/span&gt; &lt;span class='no'&gt;Exception&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;active?&lt;/span&gt;

        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;activate!&lt;/span&gt;
          &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;deliver_activation_confirmation!&lt;/span&gt;
          &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;root_url&lt;/span&gt;
        &lt;span class='k'&gt;else&lt;/span&gt;
          &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:new&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Les exceptions servent à empêcher l&amp;#8217;activation d&amp;#8217;un utilisateur déjà activé ou au &lt;code&gt;perishable_token&lt;/code&gt; expiré. Vous voudrez certainement remplacer cette gestion d&amp;#8217;erreur par quelque chose de plus élaboré, comme la possibilité pour un utilisateur dont le &lt;code&gt;perishable_token&lt;/code&gt; a expiré d&amp;#8217;en demander un nouveau.&lt;/p&gt;

&lt;p&gt;Nous créons la vue correspondant à l&amp;#8217;activation :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/activations/new.html.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &amp;lt;h1&amp;gt;Activez votre compte&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;form_for&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:url&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;activate_path&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;id&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='ss'&gt;:html&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='ss'&gt;:method&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:post&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;error_messages&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;submit&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Activer mon compte&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ces contrôleurs font appel à un certain nombre de méthodes du modèle User qui n&amp;#8217;existent pas encore. Remédions à cela :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;activate!&lt;/span&gt;
      &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;actif&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;
      &lt;span class='n'&gt;save&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;deliver_activation_instructions!&lt;/span&gt;
      &lt;span class='n'&gt;reset_perishable_token!&lt;/span&gt;
      &lt;span class='no'&gt;UserMailer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;deliver_activation_instructions&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;deliver_activation_confirmation!&lt;/span&gt;
      &lt;span class='n'&gt;reset_perishable_token!&lt;/span&gt;
      &lt;span class='no'&gt;UserMailer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;deliver_activation_confirmation&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Il ne nous manque plus que les envois d&amp;#8217;emails, nous générons pour cela &lt;code&gt;UserMailer&lt;/code&gt; :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    script/generate user_mailer activation_instructions activation_confirmation
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis nous ajoutons le code suivant au mailer :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user_mailer.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UserMailer&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActionMailer&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;activation_instructions&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;subject&lt;/span&gt;       &lt;span class='s2'&gt;&amp;quot;Veuillez confirmer la création de votre compte&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;from&lt;/span&gt;          &lt;span class='s2'&gt;&amp;quot;Mon Appli &amp;lt;noreply@example.com&amp;gt;&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;recipients&lt;/span&gt;    &lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;email&lt;/span&gt;
        &lt;span class='n'&gt;sent_on&lt;/span&gt;       &lt;span class='no'&gt;Time&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;now&lt;/span&gt;
        &lt;span class='n'&gt;body&lt;/span&gt;          &lt;span class='ss'&gt;:account_activation_url&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;register_url&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;perishable_token&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;activation_confirmation&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;subject&lt;/span&gt;       &lt;span class='s2'&gt;&amp;quot;Votre compte a bien été créé&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;from&lt;/span&gt;          &lt;span class='s2'&gt;&amp;quot;Mon Appli &amp;lt;noreply@example.com&amp;gt;&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;recipients&lt;/span&gt;    &lt;span class='n'&gt;user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;email&lt;/span&gt;
        &lt;span class='n'&gt;sent_on&lt;/span&gt;       &lt;span class='no'&gt;Time&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;now&lt;/span&gt;
        &lt;span class='n'&gt;body&lt;/span&gt;          &lt;span class='ss'&gt;:root_url&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;root_url&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous ajoutons les routes utilisées dans le mailer :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/routes.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;register&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/register/:activation_code&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:controller&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;activations&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;new&amp;#39;&lt;/span&gt;
    &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;activate&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/activate/:id&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:controller&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;activations&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;create&amp;#39;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous créons enfin les vues contenant les instructions d&amp;#8217;activation :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/user_mailer/activation_instructions.html.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    Nous vous remercions d&amp;#39;avoir créé un compte. Veuillez cliquer sur le lien ci-dessous pour l&amp;#39;activer :&lt;/span&gt;

&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='vi'&gt;@account_activation_url&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;et de confirmation de l&amp;#8217;activation :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/user_mailer/activation_confirmation.html.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    Votre compte a bien été activé.&lt;/span&gt;

&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='vi'&gt;@root_url&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Dernière chose pour les emails, il faut indiquer à Rails quelle url de base utiliser pour la génération des liens :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/environments/development.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;action_mailer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;default_url_options&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='ss'&gt;:host&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;localhost:3000&amp;#39;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Vérifions maintenant que tout fonctionne. Nous nous rendons sur http://localhost:3000/users/new et créons un utilisateur. Nous voyons dans le log du serveur l&amp;#8217;email envoyé avec le lien d&amp;#8217;activation. Nous copions ce lien et nous rendons sur &lt;code&gt;http://localhost:3000/user_session/new&lt;/code&gt; pour tenter de nous connecter. Nous obtenons bien un message d&amp;#8217;erreur nous indiquant que le compte n&amp;#8217;est pas actif.&lt;/p&gt;

&lt;p&gt;Nous pouvons alors copier/coller dans notre navigateur l&amp;#8217;adresse récupérée dans l&amp;#8217;email (de la forme &lt;code&gt;http://localhost:3000/register/:perishable_token&lt;/code&gt;). Nous voyons alors la page contenant le bouton &amp;#8220;Activer mon compte&amp;#8221; sur lequel nous cliquons. Nous voyons dans le log du serveur l&amp;#8217;email de confirmation, il est maintenant possible de se connecter.&lt;/p&gt;

&lt;p&gt;Tout cela est déjà bien pratique, mais ne serait-ce pas mieux si nous étions connecté dès l&amp;#8217;activation du compte ? Voyons comment mettre en place ce processus.&lt;/p&gt;

&lt;h3 id='connexion_ds_lactivation'&gt;Connexion dès l&amp;#8217;activation&lt;/h3&gt;

&lt;p&gt;Authlogic connecte automatiquement l&amp;#8217;utilisateur lors de la modification du mot de passe, or ici le mot de passe n&amp;#8217;a pas été modifié. Nous allons donc modifier le processus pour ne demander que l&amp;#8217;email à l&amp;#8217;inscription et demander le mot de passe lors de l&amp;#8217;activation, connectant ainsi l&amp;#8217;utilisateur en même temps.&lt;/p&gt;

&lt;p&gt;Nous commençons par indiquer à Authlogic de ne vérifier la longueur du mot de passe que si celui-ci est vide lors d&amp;#8217;un &lt;code&gt;update&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;acts_as_authentic&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
      &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;validates_length_of_password_field_options&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='ss'&gt;:on&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:update&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:minimum&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:if&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:has_no_credentials?&lt;/span&gt;
      &lt;span class='p'&gt;}&lt;/span&gt;
      &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;validates_length_of_password_confirmation_field_options&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='ss'&gt;:on&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:update&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:minimum&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:if&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:has_no_credentials?&lt;/span&gt;
      &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;has_no_credentials?&lt;/span&gt;
      &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;crypted_password&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;blank?&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous séparons ensuite l&amp;#8217;inscription d&amp;#8217;un utilisateur en deux processus :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;signup!&lt;/code&gt; qui affecte l&amp;#8217;email choisi et sauvegarde sans login automatique&lt;/li&gt;

&lt;li&gt;&lt;code&gt;activate!&lt;/code&gt; qui affecte le mot de passe choisi et sauvegarde avec login automatique&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nous modifions de nouveau le modèle &lt;code&gt;User&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;signup!&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;email&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:user&lt;/span&gt;&lt;span class='o'&gt;][&lt;/span&gt;&lt;span class='ss'&gt;:email&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
      &lt;span class='c1'&gt;# Ces colonnes sont NOT NULL, on évite une erreur SQL&lt;/span&gt;
      &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;crypted_password&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;
      &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;password_salt&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;
      &lt;span class='n'&gt;save_without_session_maintenance&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;activate!&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;actif&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;
      &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;password&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:user&lt;/span&gt;&lt;span class='o'&gt;][&lt;/span&gt;&lt;span class='ss'&gt;:password&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
      &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;password_confirmation&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:user&lt;/span&gt;&lt;span class='o'&gt;][&lt;/span&gt;&lt;span class='ss'&gt;:password_confirmation&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
      &lt;span class='n'&gt;save&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous modifions ensuite la méthode &lt;code&gt;create&lt;/code&gt; des contrôleurs &lt;code&gt;ActivationsController&lt;/code&gt; et &lt;code&gt;UsersController&lt;/code&gt; pour utiliser nos nouvelles méthodes &lt;code&gt;signup!&lt;/code&gt; et &lt;code&gt;activate!&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nous commençons par &lt;code&gt;UsersController&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/users_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create&lt;/span&gt;
      &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;

      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;signup!&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;deliver_activation_instructions!&lt;/span&gt;
        &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:notice&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Votre compte a bien été créé.&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt;
          &lt;span class='s2'&gt;&amp;quot;Vous allez recevoir un email contenant les instructions pour l&amp;#39;activer.&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;root_url&lt;/span&gt;
      &lt;span class='k'&gt;else&lt;/span&gt;
        &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:new&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis &lt;code&gt;ActivationsController&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/activations_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create&lt;/span&gt;
      &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:id&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

      &lt;span class='k'&gt;raise&lt;/span&gt; &lt;span class='no'&gt;Exception&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;active?&lt;/span&gt;

      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;activate!&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;deliver_activation_confirmation!&lt;/span&gt;
        &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:notice&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Votre compte a bien été activé.&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;root_url&lt;/span&gt;
      &lt;span class='k'&gt;else&lt;/span&gt;
        &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:new&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Il ne nous reste plus qu&amp;#8217;à modifier les formulaires. Nous commençons par supprimer le mot de passe lors de l&amp;#8217;inscription :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/users/new.html.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &amp;lt;h1&amp;gt;Créer un compte&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;form_for&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;error_messages&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Email&amp;#39;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;text_field&lt;/span&gt; &lt;span class='ss'&gt;:email&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;submit&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Créer mon compte&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis nous l&amp;#8217;ajoutons lors de l&amp;#8217;activation :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/activations/new.html.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &amp;lt;h1&amp;gt;Activez votre compte&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;form_for&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:url&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;activate_path&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;id&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='ss'&gt;:html&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='ss'&gt;:method&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:post&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;error_messages&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='ss'&gt;:password&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Mot de passe&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;password_field&lt;/span&gt; &lt;span class='ss'&gt;:password&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='ss'&gt;:password_confirmation&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Confirmer le mot de passe&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;password_field&lt;/span&gt; &lt;span class='ss'&gt;:password_confirmation&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;submit&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Activer mon compte&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</content>
 </entry>
 
 <entry>
   <title>Inscription et connexion d'un utilisateur avec Authlogic</title>
   <link href="http://www.tutoriaux-rails.com/articles/inscription-et-connexion-d-un-utilisateur-avec-authlogic"/>
   <updated>2010-03-03T00:00:00+01:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/inscription-et-connexion-d-un-utilisateur-avec-authlogic</id>
   <content type="html">&lt;p&gt;&lt;a href='http://github.com/binarylogic/authlogic'&gt;Authlogic&lt;/a&gt; est une solution simple et élégante pour gérer l&amp;#8217;inscription et la connexion d&amp;#8217;utilisateurs. Voyons comment l&amp;#8217;intégrer à un site existant.&lt;/p&gt;

&lt;h3 id='installation'&gt;Installation&lt;/h3&gt;

&lt;p&gt;Nous commençons par indiquons dans &lt;code&gt;config/environment.rb&lt;/code&gt; que notre application utilise la gem Authlogic :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/environment.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='no'&gt;Rails&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Initializer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
      &lt;span class='c1'&gt;# ...&lt;/span&gt;
      &lt;span class='n'&gt;config&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;gem&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;authlogic&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:source&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;http://gemcutter.org&amp;#39;&lt;/span&gt;
      &lt;span class='c1'&gt;# ...&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous installons ensuite la gem et décompressons son code dans le répertoire &lt;code&gt;vendor/gems&lt;/code&gt; :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo rake gems:install
    rake gems:unpack:dependencies
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous paramétrons ensuite notre application pour Authlogic. Une &lt;a href='http://github.com/binarylogic/authlogic_example'&gt;application exemple&lt;/a&gt; avec les instructions d&amp;#8217;installation et des explications est disponible sur github. Nous en reprenons ici les différentes étapes.&lt;/p&gt;

&lt;h3 id='cration_du_modle_usersession'&gt;Création du modèle UserSession&lt;/h3&gt;

&lt;p&gt;Authlogic permet de gérer des sessions gérées comme un modèle ActiveRecord. Elles peuvent êtres créées et détruites par un controller RESTful que nous allons créer par la suite. Nous créons le modèle &lt;code&gt;UserSession&lt;/code&gt; grâce au générateur fourni :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    script/generate session user_session
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Un fichier &lt;code&gt;app/models/user_session.rb&lt;/code&gt; est créé et contient le code suivant :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UserSession&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;Authlogic&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Session&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous ajoutons enfin une route pour la création et destruction de la session :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/routes.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;resource&lt;/span&gt; &lt;span class='ss'&gt;:user_session&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='cration_du_modle_user'&gt;Création du modèle User&lt;/h3&gt;

&lt;p&gt;Avoir une gestion des sessions est pratique, mais encore faut-il avoir des utilisateurs à authentifier ! Créons un modèle User :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    script/generate model user
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Plusieurs fichiers sont créés, dont un fichier de migration qui va nous servir à créer la table en base de données. Nous éditons ce fichier situé dans &lt;code&gt;db/migrate&lt;/code&gt; pour ajouter les colonnes nécessaires au fonctionnement d&amp;#8217;Authlogic :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# db/migrate/xxxxxxxxxxxxxx_create_users.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;CreateUsers&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Migration&lt;/span&gt;
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nc'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nf'&gt;up&lt;/span&gt;
        &lt;span class='n'&gt;create_table&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;string&lt;/span&gt; &lt;span class='ss'&gt;:email&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:null&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;string&lt;/span&gt; &lt;span class='ss'&gt;:crypted_password&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:null&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;string&lt;/span&gt; &lt;span class='ss'&gt;:password_salt&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:null&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;string&lt;/span&gt; &lt;span class='ss'&gt;:persistence_token&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:null&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;string&lt;/span&gt; &lt;span class='ss'&gt;:perishable_token&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:null&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;integer&lt;/span&gt; &lt;span class='ss'&gt;:login_count&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:null&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:default&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;integer&lt;/span&gt; &lt;span class='ss'&gt;:failed_login_count&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:null&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:default&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;datetime&lt;/span&gt; &lt;span class='ss'&gt;:last_request_at&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;datetime&lt;/span&gt; &lt;span class='ss'&gt;:current_login_at&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;datetime&lt;/span&gt; &lt;span class='ss'&gt;:last_login_at&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;string&lt;/span&gt; &lt;span class='ss'&gt;:current_login_ip&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;string&lt;/span&gt; &lt;span class='ss'&gt;:last_login_ip&lt;/span&gt;
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;timestamps&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nc'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nf'&gt;down&lt;/span&gt;
        &lt;span class='n'&gt;drop_table&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Chacun des choix faits ici est configurable ou modifiable, Authlogic permettant une grande souplesse à ce niveau. Voyons à quoi sert chaque champ :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;l&amp;#8217;email de l&amp;#8217;utilisateur est utilisé comme login.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;crypted_password&lt;/code&gt; et &lt;code&gt;password_salt&lt;/code&gt; sont utilisés pour le cryptage et le stockage du mot de passe&lt;/li&gt;

&lt;li&gt;&lt;code&gt;persistence_token&lt;/code&gt; sert à maintenir l&amp;#8217;utilisateur connecté&lt;/li&gt;

&lt;li&gt;&lt;code&gt;perishable_token&lt;/code&gt; est utilisé pour identifier un utilisateur lors de la confirmation de son ouverture de compte et de la réinitialisation de son mot de passe.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;login_count&lt;/code&gt; sert à stocker le nombre de fois où l&amp;#8217;utilisateur s&amp;#8217;est connecté&lt;/li&gt;

&lt;li&gt;&lt;code&gt;failed_login_count&lt;/code&gt; est utilisé pour la protection contre les attaques &amp;#8220;brute force&amp;#8221; (par défaut Authlogic suspend un utilisateur pour 2 heures au bout de 50 essais infructueux, ces valeurs étant bien sûr configurables.)&lt;/li&gt;

&lt;li&gt;&lt;code&gt;last_request_at&lt;/code&gt; sert à stocker la date de dernière action sur le site&lt;/li&gt;

&lt;li&gt;&lt;code&gt;current_login_at&lt;/code&gt; sert à stocker la date de dernière connexion&lt;/li&gt;

&lt;li&gt;&lt;code&gt;last_login_at&lt;/code&gt; sert à stocker la valeur de &lt;code&gt;current_login_at&lt;/code&gt; avant qu&amp;#8217;il ne soit réinitialisé&lt;/li&gt;

&lt;li&gt;&lt;code&gt;current_login_ip&lt;/code&gt; sert à stocker l&amp;#8217;adresse IP de dernière connexion&lt;/li&gt;

&lt;li&gt;&lt;code&gt;last_login_ip&lt;/code&gt; sert à stocker la valeur de &lt;code&gt;current_login_ip&lt;/code&gt; avant qu&amp;#8217;il ne soit réinitialisé&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nous pouvons maintenant mettre à jour la base de données avec la migration :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    rake db:migrate
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='configuration_du_modle_user'&gt;Configuration du modèle User&lt;/h3&gt;

&lt;p&gt;Nous allons maintenant indiquer qu&amp;#8217;un utilisateur est identifié par Authlogic. Il suffit d&amp;#8217;ajouter une ligne au modèle &lt;code&gt;User&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;User&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
      &lt;span class='n'&gt;acts_as_authentic&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Pour le moment nous conservons la configuration par défaut. Par la suite il sera facile de rajouter des options de configuration dans un bloc :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/user.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;User&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActiveRecord&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
      &lt;span class='n'&gt;acts_as_authentic&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
        &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;config_option&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;config_value&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;La &lt;a href='http://rdoc.info/projects/binarylogic/authlogic'&gt;documentation d&amp;#8217;Authlogic&lt;/a&gt; donne la liste des options disponibles pour chaque module dans &lt;code&gt;Authlogic::ActsAsAuthentic::&amp;lt;module&amp;gt;::Config&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id='inscription_des_utilisateurs'&gt;Inscription des utilisateurs&lt;/h3&gt;

&lt;p&gt;Nos modèles sont prêts, nous pouvons démarrer la réalisation des différentes actions. Nous allons commencer par permettre aux utilisateurs de s&amp;#8217;inscrire. Nous créons tout d&amp;#8217;abord un contrôleur &lt;code&gt;UsersController&lt;/code&gt; :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    script/generate controller users
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous y ajoutons les actions REST &lt;code&gt;new&lt;/code&gt; et &lt;code&gt;create&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/users_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UsersController&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ApplicationController&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;new&lt;/span&gt;
        &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create&lt;/span&gt;
        &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:user&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;save&lt;/span&gt;
          &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:notice&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Votre compte a bien été créé&amp;quot;&lt;/span&gt;
          &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/&amp;#39;&lt;/span&gt;
        &lt;span class='k'&gt;else&lt;/span&gt;
          &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:new&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous créons ensuite la vue correspondante :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/users/new.html.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &amp;lt;h1&amp;gt;Créer un compte&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;form_for&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;error_messages&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Email&amp;#39;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;text_field&lt;/span&gt; &lt;span class='ss'&gt;:email&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Mot de passe&amp;#39;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;password_field&lt;/span&gt; &lt;span class='ss'&gt;:password&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Confirmer le mot de passe&amp;#39;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;password_field&lt;/span&gt; &lt;span class='ss'&gt;:password_confirmation&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;submit&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Créer mon compte&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous ajoutons la route correspondante aux actions REST sur &lt;code&gt;UsersController&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/routes.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='no'&gt;ActionController&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Routing&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Routes&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;draw&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
      &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;resources&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous pouvons maintenant nous rendre sur &lt;code&gt;http://localhost:3000/users/new&lt;/code&gt; et remplir le formulaire d&amp;#8217;inscription. Une fois inscrit, nous lançons la console pour vérifier que l&amp;#8217;utilisateur est bien enregistré :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    script/console
    y User.last
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous voyons les informations de notre utilisateur s&amp;#8217;afficher, nous pouvons maintenant nous intéresser à sa connexion.&lt;/p&gt;

&lt;h3 id='connexion_et_dconnexion_des_utilisateurs'&gt;Connexion et déconnexion des utilisateurs&lt;/h3&gt;

&lt;p&gt;Une fois l&amp;#8217;utilisateur créé, nous devons lui permettre de se connecter. Nous commençons par créer une page d&amp;#8217;accueil sur laquelle nous verrons :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;un lien vers le formulaire de connexion si l&amp;#8217;utilisateur n&amp;#8217;est pas connecté&lt;/li&gt;

&lt;li&gt;l&amp;#8217;email de l&amp;#8217;utilisateur connecté sinonNous créons pour cela un contrôleur&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nous ajoutons tout d&amp;#8217;abord une route pour la page d&amp;#8217;accueil :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/routes.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='no'&gt;ActionController&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Routing&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Routes&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;draw&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
      &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;root&lt;/span&gt; &lt;span class='ss'&gt;:controller&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:index&lt;/span&gt;
      &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;resources&lt;/span&gt; &lt;span class='ss'&gt;:users&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;ainsi que deux méthodes &lt;code&gt;current_user&lt;/code&gt; et &lt;code&gt;current_user_session&lt;/code&gt; à &lt;code&gt;ApplicationController&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/application_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;ApplicationController&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ActionController&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
      &lt;span class='n'&gt;helper&lt;/span&gt; &lt;span class='ss'&gt;:all&lt;/span&gt; &lt;span class='c1'&gt;# include all helpers, all the time&lt;/span&gt;
      &lt;span class='n'&gt;protect_from_forgery&lt;/span&gt; &lt;span class='c1'&gt;# See ActionController::RequestForgeryProtection for details&lt;/span&gt;

      &lt;span class='n'&gt;filter_parameter_logging&lt;/span&gt; &lt;span class='ss'&gt;:password&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:password_confirmation&lt;/span&gt;
      &lt;span class='n'&gt;helper_method&lt;/span&gt; &lt;span class='ss'&gt;:current_user_session&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:current_user&lt;/span&gt;

      &lt;span class='kp'&gt;private&lt;/span&gt;
        &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;current_user_session&lt;/span&gt;
          &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='vi'&gt;@current_user_session&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;defined?&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='vi'&gt;@current_user_session&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
          &lt;span class='vi'&gt;@current_user_session&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;UserSession&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;

        &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;current_user&lt;/span&gt;
          &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='vi'&gt;@current_user&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;defined?&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='vi'&gt;@current_user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
          &lt;span class='vi'&gt;@current_user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;current_user_session&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;current_user_session&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;user&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous ajoutons ensuite une action &lt;code&gt;index&lt;/code&gt; à notre contrôleur &lt;code&gt;UsersController&lt;/code&gt; :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/users_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UsersController&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ApplicationController&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;index&lt;/span&gt;

      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;new&lt;/span&gt;
        &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create&lt;/span&gt;
        &lt;span class='vi'&gt;@user&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;User&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:user&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;save&lt;/span&gt;
          &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:notice&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Votre compte a bien été créé&amp;quot;&lt;/span&gt;
          &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/&amp;#39;&lt;/span&gt;
        &lt;span class='k'&gt;else&lt;/span&gt;
          &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:new&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis nous créons la vue correspondante :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/users/index.html.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &amp;lt;h1&amp;gt;Bienvenue&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;current_user&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;current_user&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;email&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x'&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;link_to&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Déconnexion&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;user_session_path&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:method&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:delete&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;link_to&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Connexion&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;new_user_session_path&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x'&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;link_to&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;S&amp;#39;inscrire&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;new_user_path&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x'&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous créons maintenant le contrôleur &lt;code&gt;UserSessions&lt;/code&gt; qui va gérer la création et la suppression de sessions :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    script/generate controller user_sessions new create destroy
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous y ajoutons le code classique d&amp;#8217;un contrôleur RESTful :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/controllers/user_sessions_controller.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;UserSessionsController&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;ApplicationController&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;new&lt;/span&gt;
        &lt;span class='vi'&gt;@user_session&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;UserSession&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;create&lt;/span&gt;
        &lt;span class='vi'&gt;@user_session&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;UserSession&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:user_session&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='vi'&gt;@user_session&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;save&lt;/span&gt;
          &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:notice&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Vous êtes maintenant connecté&amp;quot;&lt;/span&gt;
          &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;root_path&lt;/span&gt;
        &lt;span class='k'&gt;else&lt;/span&gt;
          &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:action&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:new&lt;/span&gt;
        &lt;span class='k'&gt;end&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;destroy&lt;/span&gt;
        &lt;span class='n'&gt;current_user_session&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;destroy&lt;/span&gt;
        &lt;span class='n'&gt;flash&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:notice&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Vous êtes maintenant déconnecté&amp;quot;&lt;/span&gt;
        &lt;span class='n'&gt;redirect_to&lt;/span&gt; &lt;span class='n'&gt;root_url&lt;/span&gt;
      &lt;span class='k'&gt;end&lt;/span&gt;

    &lt;span class='k'&gt;end&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis nous créons la vue correspondant au formulaire de connexion :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/views/user_sessions/new.html.erb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='erb'&gt;&lt;span class='x'&gt;    &amp;lt;h1&amp;gt;Connexion&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='n'&gt;form_for&lt;/span&gt; &lt;span class='vi'&gt;@user_session&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:url&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;user_session_path&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='cp'&gt;-%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;error_messages&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Email&amp;#39;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;text_field&lt;/span&gt; &lt;span class='ss'&gt;:email&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Mot de passe&amp;#39;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;password_field&lt;/span&gt; &lt;span class='ss'&gt;:password&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;check_box&lt;/span&gt; &lt;span class='ss'&gt;:remember_me&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;        &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Se souvenir de moi&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class='x'&gt;      &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%=&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;submit&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Connexion&amp;quot;&lt;/span&gt; &lt;span class='cp'&gt;%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;&lt;span class='cp'&gt;&amp;lt;%&lt;/span&gt; &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='cp'&gt;-%&amp;gt;&lt;/span&gt;&lt;span class='x' /&gt;
&lt;span class='x'&gt;    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous pouvons maintenant nous rendre sur &lt;code&gt;http://localhost:3000&lt;/code&gt;, nous y voyons &amp;#8220;Bienvenue&amp;#8221; ainsi que les liens de connexion et d&amp;#8217;inscription. Une fois connecté, nous voyons apparaître l&amp;#8217;email de l&amp;#8217;utilisateur en cours ainsi que le lien de déconnexion.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Démarrer une nouvelle application Rails avec Git et un modèle</title>
   <link href="http://www.tutoriaux-rails.com/articles/demarrer-une-nouvelle-application-rails-avec-git-et-un-modele"/>
   <updated>2010-03-02T00:00:00+01:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/demarrer-une-nouvelle-application-rails-avec-git-et-un-modele</id>
   <content type="html">&lt;p&gt;Nous allons voir comment utiliser les modèles d&amp;#8217;application pour générer un squelette incluant d&amp;#8217;office les fonctionnalités couramment utilisées.&lt;/p&gt;

&lt;h3 id='les_modles_dapplication'&gt;Les modèles d&amp;#8217;application&lt;/h3&gt;

&lt;p&gt;Les modèles d&amp;#8217;application sont de simple fichiers Ruby contenant du code permettant d&amp;#8217;effectuer un certain nombre d&amp;#8217;actions à la création d&amp;#8217;une application. Différentes méthodes sont disponibles, permettant d&amp;#8217;inclure une gem ou un plugin, de manipuler git, de créer une route, de lancer un script, etc.&lt;/p&gt;

&lt;p&gt;Pour indiquer à Rails d&amp;#8217;utiliser un fichier modèle, il suffit d&amp;#8217;utiliser le paramètre &lt;code&gt;- m&lt;/code&gt; lors de la création d&amp;#8217;une application :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    rails mon-appli -m ~/rails-modele.rb
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Il est également possible d&amp;#8217;indiquer un fichier situé sur un serveur web :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    rails mon-appli -m http://gist.github.com/211697.txt
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous allons créer un fichier modèle qui réalise les actions suivantes :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gestion de source avec Git&lt;/li&gt;

&lt;li&gt;installation de gems et de plugins&lt;/li&gt;

&lt;li&gt;configuration de la base de données&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='gestion_de_source_avec_git'&gt;Gestion de source avec Git&lt;/h3&gt;

&lt;p&gt;Comme nous allons versionner notre code avec Git, nous profitons du modèle d&amp;#8217;application pour exécuter les commandes permettant d&amp;#8217;initialiser un dépôt et de le paramétrer pour ignorer les fichiers qui ne seront pas versionnés : fichiers de configuration, de logs, temporaires&amp;#8230;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# ~/rails-modele.rb&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='c1'&gt;# Initialisation du dépôt&lt;/span&gt;
    &lt;span class='n'&gt;git&lt;/span&gt; &lt;span class='ss'&gt;:init&lt;/span&gt;

    &lt;span class='c1'&gt;# Copie du fichier de configuration de la base de données vers une version d&amp;#39;exemple&lt;/span&gt;
    &lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;cp config/database.yml config/database.yml.default&amp;quot;&lt;/span&gt;

    &lt;span class='c1'&gt;# Ajout d&amp;#39;un fichier .gitignore dans chaque répertoire vide&lt;/span&gt;
    &lt;span class='c1'&gt;# Git ne versionne que le contenu des fichiers, un répertoire ou fichier vide est ignoré&lt;/span&gt;
    &lt;span class='c1'&gt;# Pour forcer la création des répertoires vides nous y insérons un fichier caché spécial&lt;/span&gt;
    &lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='sx'&gt;%{find . -type d -empty | xargs -I % touch %/.gitignore}&lt;/span&gt;

    &lt;span class='c1'&gt;# Ajout des fichiers à ignorer dans le fichier .gitignore principal&lt;/span&gt;
    &lt;span class='n'&gt;file&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;.gitignore&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class='no'&gt;END&lt;/span&gt;
&lt;span class='sh'&gt;    log/*.log&lt;/span&gt;
&lt;span class='sh'&gt;    db/*.db&lt;/span&gt;
&lt;span class='sh'&gt;    db/*.sqlite3&lt;/span&gt;
&lt;span class='sh'&gt;    tmp/**/*&lt;/span&gt;
&lt;span class='sh'&gt;    config/database.yml&lt;/span&gt;
&lt;span class='no'&gt;    END&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;La méthode &lt;code&gt;git&lt;/code&gt; permet de répliquer le fonctionnement de l&amp;#8217;utilitaire en ligne de commande.&lt;/p&gt;

&lt;p&gt;La méthode &lt;code&gt;run&lt;/code&gt; permet d&amp;#8217;exécuter directement une commande shell.&lt;/p&gt;

&lt;p&gt;La méthode &lt;code&gt;file&lt;/code&gt; permet de créer un fichier avec un contenu donné.&lt;/p&gt;

&lt;h3 id='installation_de_gems_et_plugins'&gt;Installation de gems et plugins&lt;/h3&gt;

&lt;p&gt;Une fois notre dépôt initialisé, nous allons pouvoir ajouter les gems et plugins couramment utilisés. Pour le moment nous nous en tiendrons au minimum : la pagination de résultats avec &lt;a href='http://github.com/mislav/will_paginate'&gt;WillPaginate&lt;/a&gt;. Le plugin d&amp;#8217;inscription et de connexion des utilisateurs nécessitant plus d&amp;#8217;explications, il fera l&amp;#8217;objet d&amp;#8217;un prochain article.&lt;/p&gt;

&lt;p&gt;Nous ajoutons les lignes suivantes à notre fichier modèle :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;gem&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;will_paginate&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:source&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;http://gemcutter.org&amp;#39;&lt;/span&gt;
    &lt;span class='n'&gt;rake&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;gems:install&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:sudo&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;
    &lt;span class='n'&gt;rake&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;gems:unpack:dependencies&amp;#39;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;La méthode &lt;code&gt;gem&lt;/code&gt; permet d&amp;#8217;indiquer à Rails que l&amp;#8217;application dépend d&amp;#8217;une gem, en ajoutant au fichier &lt;code&gt;config/environment.rb&lt;/code&gt; le nom et la version de la gem utilisée. Nous installons ensuite la gem grâce à rake avant d&amp;#8217;en extraire le code dans le répertoire &lt;code&gt;vendor/gems&lt;/code&gt; de l&amp;#8217;application. Cela assure ainsi de versionner l&amp;#8217;application avec l&amp;#8217;ensemble de ses dépendances externes et d&amp;#8217;éviter les mauvaises surprises lors du déploiement (gem non installée ou de version différente par exemple).&lt;/p&gt;

&lt;p&gt;Nous allons également &amp;#8220;freezer&amp;#8221; Rails à la version utilisée dans l&amp;#8217;application :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='n'&gt;rake&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;rails:freeze:edge RELEASE=2.3.5&amp;#39;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='configuration_de_la_base_de_donnes'&gt;Configuration de la base de données&lt;/h3&gt;

&lt;p&gt;Par défaut, Rails utilise en mode de développement la base de données SQLite. Or nous avons installé à l&amp;#8217;&lt;a href='/articles/installation-d-un-environnement-de-developpement-rails-sur-mac-os-x'&gt;étape précédente&lt;/a&gt; MySQL pour retrouver en développement la même configuration que sur notre futur serveur de production. Il nous faut donc modifier le fichier de configuration de la base de données pour y indiquer nos paramètres :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='c1'&gt;# Création du fichier de configuration de la base de données&lt;/span&gt;
    &lt;span class='n'&gt;file&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;config/database.yml&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class='no'&gt;END&lt;/span&gt;
&lt;span class='sh'&gt;    development:&lt;/span&gt;
&lt;span class='sh'&gt;      adapter: mysql&lt;/span&gt;
&lt;span class='sh'&gt;      database: database&lt;/span&gt;
&lt;span class='sh'&gt;      host: localhost&lt;/span&gt;
&lt;span class='sh'&gt;      username: username&lt;/span&gt;
&lt;span class='sh'&gt;      password: password&lt;/span&gt;
&lt;span class='sh'&gt;      encoding: utf8&lt;/span&gt;
&lt;span class='no'&gt;    END&lt;/span&gt;
    &lt;span class='n'&gt;database&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;ask&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Nom de la base ?&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;username&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;ask&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Nom d&amp;#39;utilisateur ?&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;password&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;ask&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Mot de passe ?&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;sed -e &amp;#39;s/database:.*/database: &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;database&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;/&amp;#39; -e &amp;#39;s/username:.*/username: &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;username&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;/&amp;#39; -e &amp;#39;s/password:.*/password: &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;password&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;/&amp;#39; config/database.yml &amp;gt; config/database.yml.tmp&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;mv config/database.yml.tmp config/database.yml&amp;quot;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;La méthode &lt;code&gt;ask&lt;/code&gt; permet de demander des valeurs à l&amp;#8217;utilisateur et de les utiliser ensuite. Il existe également les méthodes &lt;code&gt;yes?&lt;/code&gt; et &lt;code&gt;no?&lt;/code&gt; qui permettent d&amp;#8217;effectuer ou non des actions suivant la réponse de l&amp;#8217;utilisateur.&lt;/p&gt;

&lt;h3 id='finalisation'&gt;Finalisation&lt;/h3&gt;

&lt;p&gt;L&amp;#8217;application est maintenant prête à être créée, il ne nous reste plus qu&amp;#8217;à enregistrer le code dans le dépôt et commiter :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;    &lt;span class='c1'&gt;# Ajout dans le dépôt Git&lt;/span&gt;
    &lt;span class='n'&gt;git&lt;/span&gt; &lt;span class='ss'&gt;:add&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;.&amp;#39;&lt;/span&gt;
    &lt;span class='n'&gt;git&lt;/span&gt; &lt;span class='ss'&gt;:commit&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;-m &amp;#39;Commit initial&amp;#39;&amp;quot;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous pouvons maintenant créer notre application et le dépôt associé :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    rails mon-appli -m ~/rails-modele.rb
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Le contenu du fichier rails-modele.rb est également disponible en ligne :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    rails mon-appli -m http://gist.github.com/211697.txt
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous sommes maintenant prêts à démarrer le développement proprement dit.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Installation d'un environnement de développement Rails sur Windows XP</title>
   <link href="http://www.tutoriaux-rails.com/articles/installation-d-un-environnement-de-developpement-sur-windows-xp"/>
   <updated>2010-03-01T00:00:00+01:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/installation-d-un-environnement-de-developpement-sur-windows-xp</id>
   <content type="html">&lt;p&gt;J&amp;#8217;utilise Mac OS X, les instructions pour Windows XP sont donc indicatives.&lt;/p&gt;

&lt;h3 id='installation_de_git'&gt;Installation de Git&lt;/h3&gt;

&lt;p&gt;La meilleure option pour installer Git sur Windows semble être par l&amp;#8217;intermédiaire de &lt;a href='http://code.google.com/p/msysgit/'&gt;msysGit&lt;/a&gt;. Nous téléchargeons la dernière version stable et lançons l&amp;#8217;installation.&lt;/p&gt;

&lt;p&gt;À l&amp;#8217;étape où apparaît un message en rouge et 3 choix nous choisissions la troisième option (l&amp;#8217;option 1 est recommandée au cas où vous utilisez les utilitaires natifs de Windows find.exe et sort.exe, ceux-ci étant remplacés par leur version Unix avec l&amp;#8217;option 3).&lt;/p&gt;

&lt;p&gt;À l&amp;#8217;étape du choix de format de fin de ligne, tout dépend de votre environnement :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;si vous travaillez avec des personnes sur Unix (Linux, Mac OS X), ou participez à des projets open source, choisissez l&amp;#8217;option 1&lt;/li&gt;

&lt;li&gt;si vous travaillez seul sous Windows ou avec d&amp;#8217;autres personnes toutes sur Windows, choisissez l&amp;#8217;option 2&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='installation_de_mysql'&gt;Installation de MySQL&lt;/h3&gt;

&lt;p&gt;Nous téléchargeons &lt;a href='http://dev.mysql.com/downloads'&gt;la version Community Server de MySQL&lt;/a&gt; en choissisant Windows, Windows Essentials, Pick a mirror.&lt;/p&gt;

&lt;p&gt;À la fin de l&amp;#8217;installation nous choisissons &amp;#8220;Configure MySQL now&amp;#8221;, &amp;#8220;Standard configuration&amp;#8221;. Nous cochons ensuite la case &amp;#8220;Include Bin Directory in Windows PATH&amp;#8221; et saisissons le mot de passe root. Nous pouvons alors finir l&amp;#8217;installation et vérifier que le serveur est bien installé en cliquant sur &amp;#8220;Démarrer &amp;gt; Exécuter &amp;gt; cmd&amp;#8221; puis en tapant&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    mysql -u root -p
    show databases;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous voyons la liste des bases de données par défaut (information_schema, mysql et test), MySQL fonctionne.&lt;/p&gt;

&lt;h3 id='installation_de_ruby_et_rails'&gt;Installation de Ruby et Rails&lt;/h3&gt;

&lt;p&gt;Nous téléchargeons le &lt;a href='http://rubyforge.org/frs/download.php/47082/ruby186-27_rc2.exe'&gt;programme d&amp;#8217;installation de Ruby 1.8.6 pour Windows&lt;/a&gt; et l&amp;#8217;exécutons. Il faut ensuite cocher &amp;#8220;Enable RubyGems&amp;#8221; et &amp;#8220;European Keyboard&amp;#8221;.&lt;/p&gt;

&lt;p&gt;En ligne de commande nous vérifions que Ruby est accessible :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    ruby -v &lt;span class='c'&gt;# ruby 1.8.6 (2008-08-11 patchlevel 287) [i386-mswin32]&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous mettons RubyGems à jour, la version livrée avec Ruby est ancienne :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    gem update
    gem -v &lt;span class='c'&gt;# 1.3.5&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous pouvons maintenant installer Rails et les gems nécessaires :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    gem install mysql rails --no-ri --no-rdoc
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Dernière petite chose, il semble y avoir parfois des soucis avec la connexion MySQL qui sont résolus en téléchargeant une &lt;a href='http://instantrails.rubyforge.org/svn/trunk/InstantRails-win/InstantRails/mysql/bin/libmySQL.dll'&gt;version plus ancienne de &lt;code&gt;libmySQL.dll&lt;/code&gt;&lt;/a&gt; dans &lt;code&gt;c:\Ruby\bin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nous voilà fin prêts pour démarrer le développement d&amp;#8217;une application !&lt;/p&gt;

&lt;h3 id='autres_outils'&gt;Autres outils&lt;/h3&gt;

&lt;p&gt;Voici une liste non exhaustive de logiciels facilitant le développement.&lt;/p&gt;

&lt;h4 id='diteurs_de_texte_et_ide'&gt;Éditeurs de texte et IDE&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://www.openkomodo.com/'&gt;Komodo Edit&lt;/a&gt; : une version libre de l&amp;#8217;IDE d&amp;#8217;ActiveState&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.aptana.com/'&gt;Aptana&lt;/a&gt; : une version d&amp;#8217;Eclipse adapté au développement avec Ruby On Rails&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.e-texteditor.com/'&gt;E-Editor&lt;/a&gt; : un clone de TextMate pour Windows, compatible avec les bundles de TextMate&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id='gui_pour_mysql'&gt;GUI pour MySQL&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://code.google.com/p/sqlyog/'&gt;SQLyog&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://dev.mysql.com/downloads/gui-tools/5.0.html'&gt;MySQL GUI Tools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id='gui_pour_git'&gt;GUI pour Git&lt;/h4&gt;

&lt;p&gt;Nous reviendrons dans un prochain article sur l&amp;#8217;utilisation de Git. En attendant, voici quelques outils pour en faciliter l&amp;#8217;utilisation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git GUI : fourni avec msysGit&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 <entry>
   <title>Installation d'un environnement de développement Rails sur Linux Ubuntu</title>
   <link href="http://www.tutoriaux-rails.com/articles/installation-d-un-environnement-de-developpement-sur-linux-ubuntu"/>
   <updated>2010-03-01T00:00:00+01:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/installation-d-un-environnement-de-developpement-sur-linux-ubuntu</id>
   <content type="html">&lt;p&gt;J&amp;#8217;utilise Mac OS X, les instructions pour Ubuntu sont donc indicatives.&lt;/p&gt;

&lt;h3 id='installation_de_git'&gt;Installation de Git&lt;/h3&gt;

&lt;p&gt;Nous commençons par mettre à jour la liste des paquets disponibles pour apt-get :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo apt-get update
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;puis nous installons Git grâce à apt-get :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo apt-get install git-core
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='installation_de_mysql'&gt;Installation de MySQL&lt;/h3&gt;

&lt;p&gt;Nous installons MySQL grâce à apt-get :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo apt-get install mysql-server-5.1 mysql-client-5.1 libmysql-ruby libmysqlclient-dev
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Vérifions que le serveur fonctionne :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    mysql -u root -p
    show databases;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous voyons la liste des bases de données par défaut (information_schema, mysql et test), MySQL fonctionne. Plusieurs outils de gestion des bases sont disponibles via le centre de téléchargement Ubuntu.&lt;/p&gt;

&lt;h3 id='installation_de_ruby_et_rails'&gt;Installation de Ruby et Rails&lt;/h3&gt;

&lt;p&gt;Nous installons Ruby et RubyGems grâce à apt-get :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo apt-get install ruby rubygems ruby-dev libopenssl-ruby
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous installons ensuite les gems nécessaires :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo gem install mysql rails --no-ri --no-rdoc
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Pour accéder facilement aux différents exécutables fournis par les gems, nous ajoutons la ligne suivante au fichier ~/.bashrc :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nb'&gt;export &lt;/span&gt;&lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/var/libs/gems/1.8/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis nous regénérons l&amp;#8217;environnement :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nb'&gt;source&lt;/span&gt; ~/.bashrc
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous pouvons alors tester l&amp;#8217;ensemble des programmes installés :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    ruby -v &lt;span class='c'&gt;# ruby 1.8.7 (2009-06-12 patchlevel 174) [i486-linux]&lt;/span&gt;
    gem -v &lt;span class='c'&gt;# 1.3.5&lt;/span&gt;
    rails -v &lt;span class='c'&gt;# Rails 2.3.5&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous voilà fin prêts pour démarrer le développement d&amp;#8217;une application !&lt;/p&gt;

&lt;h3 id='autres_outils'&gt;Autres outils&lt;/h3&gt;

&lt;p&gt;Voici une liste non exhaustive de logiciels facilitant le développement.&lt;/p&gt;

&lt;h4 id='diteurs_de_texte_et_ide'&gt;Éditeurs de texte et IDE&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://www.openkomodo.com/'&gt;Komodo Edit&lt;/a&gt; : une version libre de l&amp;#8217;IDE d&amp;#8217;ActiveState&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.aptana.com/'&gt;Aptana&lt;/a&gt; : une version d&amp;#8217;Eclipse adapté au développement avec Ruby On Rails&lt;/li&gt;

&lt;li&gt;un grand nombre d&amp;#8217;autres éditeurs sont disponibles par apt-get ou par le Centre de logiciels : emacs, vi, bluefish&amp;#8230;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id='gui_pour_mysql'&gt;GUI pour MySQL&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;MySQL GUI Tools et plusieurs autres sont disponibles sur le Centre de logiciels&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id='gui_pour_git'&gt;GUI pour Git&lt;/h4&gt;

&lt;p&gt;Nous reviendrons dans un prochain article sur l&amp;#8217;utilisation de Git. En attendant, voici quelques outils pour en faciliter l&amp;#8217;utilisation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git GUI : fourni avec Git&lt;/li&gt;

&lt;li&gt;d&amp;#8217;autres GUI sont disponibles sur le Centre de logiciels&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 <entry>
   <title>Installation d'un environnement de développement Rails sur Mac OS X</title>
   <link href="http://www.tutoriaux-rails.com/articles/installation-d-un-environnement-de-developpement-rails-sur-mac-os-x"/>
   <updated>2010-03-01T00:00:00+01:00</updated>
   <id>http://www.tutoriaux-rails.com/articles/installation-d-un-environnement-de-developpement-rails-sur-mac-os-x</id>
   <content type="html">&lt;p&gt;Ruby et Ruby On Rails sont fournis sur les versions récentes (10.5 et 10.6) de Mac OS X. Nous allons cependant en installer nos propres versions, cela permettra de les mettre à jour plus facilement par la suite. Nous utilisons pour cela MacPorts.&lt;/p&gt;

&lt;h3 id='installation_de_macports_et_git'&gt;Installation de MacPorts et Git&lt;/h3&gt;

&lt;p&gt;MacPorts est un système de gestion de paquets pour Mac, dans le même genre qu&amp;#8217;apt-get sous Debian. Il permet d&amp;#8217;installer et de maintenir facilement un grand nombre de logiciels Unix adaptés pour Mac OS X.&lt;/p&gt;

&lt;p&gt;Git est un système de &lt;a href='http://fr.wikipedia.org/wiki/Gestion_de_versions'&gt;gestion de versions&lt;/a&gt; utilisé notamment pour le développement de Ruby on Rails.&lt;/p&gt;

&lt;h4 id='installation_de_macports'&gt;Installation de MacPorts&lt;/h4&gt;

&lt;p&gt;MacPorts nécessite l&amp;#8217;installation de XCode, fourni sur le CD de Mac OS X (répertoire Optional Installs) ou disponible sur le site de l&amp;#8217;ADC &lt;a href='http://developer.apple.com/mac/'&gt;Apple Developper Connection&lt;/a&gt;. Le téléchargement est gratuit, il suffit de créer un compte.&lt;/p&gt;

&lt;p&gt;Une fois XCode installé, nous pouvons installer MacPorts. Il est disponible en téléchargement sur le &lt;a href='http://www.macports.org/'&gt;site de MacPorts&lt;/a&gt;. Il suffit de télécharger l&amp;#8217;image DMG correspondant à la version de Mac OS X et de lancer le programme d&amp;#8217;installation fourni. MacPorts est alors installé dans &lt;code&gt;/opt/local&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nous mettons à jour MacPorts pour être sûr de disposer des dernières versions des paquets :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo port -v selfupdate
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous ajoutons au fichier &lt;code&gt;.profile&lt;/code&gt; situé dans notre répertoire utilisateur le chemin vers les exécutables et la documentation MacPorts&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# ~/.profile&lt;/code&gt;&lt;/pre&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nb'&gt;export &lt;/span&gt;&lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/opt/local/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;
    &lt;span class='nb'&gt;export &lt;/span&gt;&lt;span class='nv'&gt;MANPATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/opt/local/share/man:&lt;span class='nv'&gt;$MANPATH&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Puis nous rafraîchissons la session ouverte dans le terminal :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    &lt;span class='nb'&gt;source&lt;/span&gt; ~/.profile
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 id='installation_de_git'&gt;Installation de Git&lt;/h4&gt;

&lt;p&gt;Une fois MacPorts installé, nous installons git :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo port install git-core +bash_completion
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Après un certain temps (MacPorts compile l&amp;#8217;ensemble des dépendances nécessaires à Git) MacPorts et Git sont installés. Nous pouvons passer à l&amp;#8217;installation des outils nécessaires au développement proprement dit.&lt;/p&gt;

&lt;h3 id='installation_de_mysql'&gt;Installation de MySQL&lt;/h3&gt;

&lt;p&gt;Nous installons MySQL :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo port install mysql5-server
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Une fois MySQL installé nous paramétrons les bases de données :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo mysql_install_db5
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;En cas d&amp;#8217;erreur, indiquer le bon utilisateur (merci à Denis pour avoir trouvé une solution ):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo mysql_install_db5 --user&lt;span class='o'&gt;=&lt;/span&gt;_mysql
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous chargeons MySQL au démarrage de la session :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo launchctl load -w /Library/LaunchDaemons/org.macports.mysql5.plist
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous démarrons MySQL manuellement pour la première utilisation :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo mysqld_safe5 &amp;amp;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous modifions le mot de passe root, en remplacant &lt;code&gt;new-password&lt;/code&gt; par le mot de passe souhaité :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo mysqladmin5 -u root password &lt;span class='s1'&gt;&amp;#39;new-password&amp;#39;&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Enfin nous vérifions le bon fonctionnement en ligne de commande :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    mysql5 -u root -p
    show databases;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous voyons la liste des bases de données par défaut (information_schema, mysql et test), MySQL fonctionne.&lt;/p&gt;

&lt;h3 id='installation_de_ruby_et_rails'&gt;Installation de Ruby et Rails&lt;/h3&gt;

&lt;p&gt;Nous installons Ruby :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo port install ruby
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous installons maintenant RubyGems, le système de gestion de modules Ruby :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo port install wget
    wget http://rubyforge.org/frs/download.php/60718/rubygems-1.3.5.tgz
    tar -xzf rubygems-1.3.5.tgz
    &lt;span class='nb'&gt;cd &lt;/span&gt;rubygems-1.3.5 &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo ruby setup.rb
    sudo gem update --system
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous pouvons maintenant installer les gems nécessaires :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    sudo gem install mysql rails --no-ri --no-rdoc
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Vérifions les chemins et versions de nos exécutables :&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;    which ruby &lt;span class='c'&gt;# /opt/local/bin/ruby&lt;/span&gt;
    which rails &lt;span class='c'&gt;# /opt/local/bin/rails&lt;/span&gt;
    ruby -v &lt;span class='c'&gt;# ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10]&lt;/span&gt;
    rails -v &lt;span class='c'&gt;# Rails 2.3.5&lt;/span&gt;
    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nous voilà fin prêts pour démarrer le développement d&amp;#8217;une application !&lt;/p&gt;

&lt;h3 id='autres_outils'&gt;Autres outils&lt;/h3&gt;

&lt;p&gt;Voici une liste non exhaustive de logiciels facilitant le développement.&lt;/p&gt;

&lt;h4 id='diteurs_de_texte_et_ide'&gt;Éditeurs de texte et IDE&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://macromates.com/'&gt;Textmate&lt;/a&gt; : l&amp;#8217;éditeur que j&amp;#8217;utilise, très puissant notamment grâce à son système de &amp;#8220;snippets&amp;#8221;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://code.google.com/p/macvim/'&gt;MacVim&lt;/a&gt; : une version mac du célèbre éditeur vim, très puissant également mais demande un temps d&amp;#8217;adaptation assez long&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.openkomodo.com/'&gt;Komodo Edit&lt;/a&gt; : une version libre de l&amp;#8217;IDE d&amp;#8217;ActiveState&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.aptana.com/'&gt;Aptana RadRails&lt;/a&gt; : une version d&amp;#8217;Eclipse adapté au développement avec Ruby On Rails&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id='gui_pour_mysql'&gt;GUI pour MySQL&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://www.sequelpro.com/'&gt;Sequel Pro&lt;/a&gt; : celui que j&amp;#8217;utilise, très pratique pour les opérations courantes sur les bases de données (visualisation, modifications, import/export&amp;#8230;)&lt;/li&gt;

&lt;li&gt;&lt;a href='http://dev.mysql.com/downloads/gui-tools/5.0.html'&gt;MySQL GUI Tools&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.navicat.com/en/products/navicat_mysql/mysql_detail_mac.html'&gt;Navicat&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id='gui_pour_git'&gt;GUI pour Git&lt;/h4&gt;

&lt;p&gt;Nous reviendrons dans un prochain article sur l&amp;#8217;utilisation de Git. En attendant, voici quelques outils pour en faciliter l&amp;#8217;utilisation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://gitx.frim.nl/'&gt;GitX&lt;/a&gt; : celui que j&amp;#8217;utilise, très pratique pour visualiser l&amp;#8217;arborescence et l&amp;#8217;historique d&amp;#8217;un projet, gérer les commit etc&lt;/li&gt;

&lt;li&gt;&lt;a href='http://github.com/Caged/gitnub'&gt;GitNub&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;Git GUI : fourni avec Git, offre sensiblement les mêmes fonctionnalités mais sans l&amp;#8217;interface &amp;#8220;Mac-like&amp;#8221;. Se lance avec &lt;code&gt;git gui&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id='gui_pour_macports'&gt;GUI pour MacPorts&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://porticus.alittledrop.com/'&gt;Porticus&lt;/a&gt; permet de visualiser, d&amp;#8217;installer et de désinstaller des paquets&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 
</feed>