<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>Frailers.net</title>
    <link>http://www.frailers.net/articles.rss</link>
    <description>Ressources Ruby on Rails en Français</description>
    <pubDate>Fri, 26 Jun 2009 00:00:00 +0000</pubDate>
    <lastBuildDate>Fri, 26 Jun 2009 00:00:00 +0000</lastBuildDate>
    <language>fr</language>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/FrailersArticles" type="application/rss+xml" /><item>
      <title>Deuxième edition d'ArrrrCamp</title>
      <description>&lt;p&gt;&lt;a href="http://arrrrcamp.be"&gt;ArrrrCamp&lt;/a&gt; &amp;#8211; &amp;#8220;About Ruby, Rails, Radiant and Rum&amp;#8221;-Camp, le rendez-vous Ruby en Belgique. Après une première edition le 8 mai dernier, les organisateurs d&amp;#8217; &lt;a href="http://arrrrcamp.be"&gt;ArrrrCamp&lt;/a&gt; remettent le couvert. Rendez-vous le 16 Octobre 2009.&lt;/p&gt; &lt;p&gt;&lt;a href="http://arrrrcamp.be"&gt;ArrrrCamp&lt;/a&gt; tente de rassembler toute les personnes qui, en Belgique (et ailleurs), ont un intérêt pour Ruby et ses dérivés. La première edition fût un succès. Pour en savoir plus, le site d&amp;#8217; &lt;a href="http://arrrrcamp.be"&gt;ArrrrCamp&lt;/a&gt; reprend les slides/videos des différentes présentations qui ont eu lieu lors de la première edition.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://arrrrcamp.be"&gt;http://arrrrcamp.be&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Les inscriptions pour la deuxième edition ont commencé, déjà 11 inscrits ! Venez grossir les rangs des participants !&lt;/p&gt;
&lt;p&gt;&lt;a href="http://arrrrcamp.be/participants/new"&gt;http://arrrrcamp.be/participants/new&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Voilà une bonne occasion de parler de votre passion, le tout autour d&amp;#8217;un bon verre ;)&lt;/p&gt;
&lt;p&gt;Si vous souhaitez sponsoriser l&amp;#8217;évènement, il suffit de vous rendre sur le site d&amp;#8217; &lt;a href="http://arrrrcamp.be"&gt;ArrrrCamp&lt;/a&gt; et de contacter l&amp;#8217;équipe.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/FrailersArticles/~4/5ABzVWuFigQ" height="1" width="1"/&gt;</description>
      <pubDate>Fri, 26 Jun 2009 00:00:00 +0000</pubDate>
      <link>http://feedproxy.google.com/~r/FrailersArticles/~3/5ABzVWuFigQ/64-deuxie-me-edition-d-arrrrcamp</link>
      <guid isPermaLink="false">http://www.frailers.net/articles/64-deuxie-me-edition-d-arrrrcamp</guid>
    <feedburner:origLink>http://www.frailers.net/articles/64-deuxie-me-edition-d-arrrrcamp</feedburner:origLink></item>
    <item>
      <title>Importez vos contacts avec le plugin Contacts</title>
      <description>&lt;p&gt;Si vous travaillez sur des réseaux sociaux, ou si simplement vous souhaitez que votre application permette à vos utilisateurs d&amp;#8217;inviter un maximum de personnes, alors Contacts peut vous aider. Ce plugin vous permettra de récupérer la liste des contacts de vos utilisateurs, à partir d&amp;#8217;un compte &lt;strong&gt;Hotmail&lt;/strong&gt;, &lt;strong&gt;Gmail&lt;/strong&gt;, &lt;strong&gt;Yahoo&lt;/strong&gt; ou &lt;strong&gt;Plaxo&lt;/strong&gt;.&lt;/p&gt; &lt;h2&gt;Etape 1 : Installer Contacts&lt;/h2&gt;
&lt;p&gt;Contacts a été initialement créé par &lt;a href="http://github.com/cardmagic"&gt;cardmagic&lt;/a&gt; mais les versions que j&amp;#8217;ai eu l&amp;#8217;occasion d&amp;#8217;utiliser ne fonctionnaient plus avec Hotmail. Je vous conseille donc d&amp;#8217;utiliser le fork de &lt;a href="http://github.com/waheedi"&gt;waheedi&lt;/a&gt; qui règle le problème.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; script&lt;span class="Keyword"&gt;/&lt;/span&gt;plugin install git&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;/&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;github.&lt;span class="Entity"&gt;com&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;waheedi&lt;span class="Keyword"&gt;/&lt;/span&gt;contacts.git
&lt;/pre&gt;
&lt;h2&gt;Etape 2 : Récupérer les contacts&lt;/h2&gt;
&lt;p&gt;L&amp;#8217;utilisation de contacts est ridiculement simple.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt; vous connaissez la plateforme concernée&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; &lt;span class="Support"&gt;Contacts&lt;/span&gt;::&lt;span class="Entity"&gt;Hotmail&lt;/span&gt;.&lt;span class="Entity"&gt;new&lt;/span&gt;(login, password).&lt;span class="Entity"&gt;contacts&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="Support"&gt;Contacts&lt;/span&gt;::&lt;span class="Entity"&gt;Yahoo&lt;/span&gt;.&lt;span class="Entity"&gt;new&lt;/span&gt;(login, password).&lt;span class="Entity"&gt;contacts&lt;/span&gt;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt; &lt;span class="Support"&gt;Contacts&lt;/span&gt;::&lt;span class="Entity"&gt;Gmail&lt;/span&gt;.&lt;span class="Entity"&gt;new&lt;/span&gt;(login, password).&lt;span class="Entity"&gt;contacts&lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;   
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt; &lt;span class="Support"&gt;Contacts&lt;/span&gt;.&lt;span class="Entity"&gt;new&lt;/span&gt;(&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;gmail&lt;/span&gt;, login, password).&lt;span class="Entity"&gt;contacts&lt;/span&gt;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt; &lt;span class="Support"&gt;Contacts&lt;/span&gt;.&lt;span class="Entity"&gt;new&lt;/span&gt;(&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;hotmail&lt;/span&gt;, login, password).&lt;span class="Entity"&gt;contacts&lt;/span&gt;
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt; &lt;span class="Support"&gt;Contacts&lt;/span&gt;.&lt;span class="Entity"&gt;new&lt;/span&gt;(&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;yahoo&lt;/span&gt;, login, password).&lt;span class="Entity"&gt;contacts&lt;/span&gt;
&lt;span class="line-numbers"&gt;   9 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;  10 &lt;/span&gt; &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt; laisser contacts deviner de quel type de compte il s'agit&lt;/span&gt;
&lt;span class="line-numbers"&gt;  11 &lt;/span&gt; &lt;span class="Support"&gt;Contacts&lt;/span&gt;.&lt;span class="Entity"&gt;guess&lt;/span&gt;(login, password).contacts
&lt;/pre&gt;
&lt;p&gt;Vous récupérez alors un tableau de contacts de la forme :&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; [[&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;name&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;foo@bar.com&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], [&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;name2&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;foo2@bar2.com&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]]
&lt;/pre&gt;
&lt;p&gt;A vous de jouer !&lt;/p&gt;
&lt;p&gt;Plus d&amp;#8217;infos sur le fork de contacts par waheedi ici :&lt;br /&gt;
&lt;a href="http://github.com/waheedi/contacts/tree/master"&gt;http://github.com/waheedi/contacts/tree/master&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/FrailersArticles/~4/kTt4Mxuc8NA" height="1" width="1"/&gt;</description>
      <pubDate>Wed, 24 Jun 2009 00:00:00 +0000</pubDate>
      <link>http://feedproxy.google.com/~r/FrailersArticles/~3/kTt4Mxuc8NA/63-importez-vos-contacts-avec-le-plugin-contacts</link>
      <guid isPermaLink="false">http://www.frailers.net/articles/63-importez-vos-contacts-avec-le-plugin-contacts</guid>
    <feedburner:origLink>http://www.frailers.net/articles/63-importez-vos-contacts-avec-le-plugin-contacts</feedburner:origLink></item>
    <item>
      <title>Babilu : I18n dans votre javascript !</title>
      <description>&lt;p&gt;Babilu est un plugin très facile à utiliser qui copie littéralement votre configuration I18n en &lt;span class="caps"&gt;JSON&lt;/span&gt; et Javascript. Cela vous permet d&amp;#8217;utiliser vos traductions côté client, et c&amp;#8217;est parfois assez pratique&amp;#8230;&lt;/p&gt; &lt;h2&gt;Etape 1 : Installer Babilu et ses dépendances&lt;/h2&gt;
&lt;p&gt;Babilu a besoin de &lt;a href="http://github.com/toretore/lucy"&gt;Lucy&lt;/a&gt; pour fonctionner.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; script&lt;span class="Keyword"&gt;/&lt;/span&gt;plugin install git&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;/&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;github.&lt;span class="Entity"&gt;com&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;toretore&lt;span class="Keyword"&gt;/&lt;/span&gt;lucy.&lt;span class="Entity"&gt;git&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; script&lt;span class="Keyword"&gt;/&lt;/span&gt;plugin install git&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;/&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;github.&lt;span class="Entity"&gt;com&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;toretore&lt;span class="Keyword"&gt;/&lt;/span&gt;babilu.git
&lt;/pre&gt;
&lt;h2&gt;Etape 2 : Ajouter Babilu a notre application&lt;/h2&gt;
&lt;p&gt;Il vous suffit alors simplement d&amp;#8217;ajouter&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;head&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;   &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;script type&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;text/javascript&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; src&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;/javascripts/locales.js&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&amp;gt;&lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;script&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;head&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;dans l&amp;#8217;en-tête de votre layout pour charger le fichier généré. Et d&amp;#8217;utilisez directement&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Variable"&gt;I18n&lt;/span&gt;.&lt;span class="Entity"&gt;t&lt;/span&gt;(&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;string1&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;) 
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; &lt;span class="Variable"&gt;I18n&lt;/span&gt;.&lt;span class="Entity"&gt;t&lt;/span&gt;(&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;messages.invalid&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;, {scope:[&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;activerecord&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;errors&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;]})
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="Variable"&gt;I18n&lt;/span&gt;.&lt;span class="Entity"&gt;t&lt;/span&gt;(&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;activerecord.errors.template.header&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;, {count:&lt;span class="Constant"&gt;2&lt;/span&gt;, &lt;span class="Support"&gt;model&lt;/span&gt;&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:'&lt;/span&gt;user&lt;span class="Constant"&gt;'&lt;/span&gt;&lt;/span&gt;}) 
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="String"&gt;&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;/&lt;/span&gt;&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;2 erreurs empêchent la sauvegarde de User&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;dans votre javascript.&lt;/p&gt;
&lt;p&gt;Et voilà !&lt;/p&gt;
&lt;p&gt;Le fichier javascript contenant les traductions est régénéré à chaque requête en développement et à chaque démarrage du serveur en production.&lt;/p&gt;
&lt;p&gt;Pour plus de détails sur babilu :&lt;br /&gt;
&lt;a href="http://github.com/toretore/babilu/tree/master"&gt;http://github.com/toretore/babilu/tree/master&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/FrailersArticles/~4/7RnR4kwores" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 16 Jun 2009 00:00:00 +0000</pubDate>
      <link>http://feedproxy.google.com/~r/FrailersArticles/~3/7RnR4kwores/62-babilu-i18n-dans-votre-javascript</link>
      <guid isPermaLink="false">http://www.frailers.net/articles/62-babilu-i18n-dans-votre-javascript</guid>
    <feedburner:origLink>http://www.frailers.net/articles/62-babilu-i18n-dans-votre-javascript</feedburner:origLink></item>
    <item>
      <title>Un form_builder pour afficher les erreurs d'un champ autrement</title>
      <description>&lt;p&gt;Si vous avez déjà travaillé au développement de plusieurs applications Rails, il est possible qu&amp;#8217;un jour, vous vous soyez dit : &amp;#8220;J&amp;#8217;en ai marre de cette tartine que me génère error_messages_for&amp;#8221;.&lt;/p&gt;
&lt;p&gt;A force de bidouille par-ci par là vous êtes parvenu à un résultat qui vous convenait. Mais comment afficher les erreurs d&amp;#8217;un champ de manière élégante, par exemple, juste à côté du champ ? Le FormBuilder est votre ami !&lt;/p&gt; &lt;p&gt;On aimerait arriver à ce résultat là :&lt;br /&gt;
&lt;img src="http://www.frailers.net/uploads/email_validation.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Créons notre Builder lib/error_form_builder.rb qui étend le FormBuilder de &amp;#8216;base&amp;#8217;&lt;br /&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;ErrorFormBuilder&lt;span class="Superclass"&gt; &lt;span class="Superclass"&gt;&amp;lt;&lt;/span&gt; ActionView::Helpers::FormBuilder&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Dans ce builder, on va surdéfinir les helpers pour les éléments d&amp;#8217;un formulaire. Nous ne ferons le détail que pour le textfield, pour les autres éléments, il suffit de suivre le même exemple en analysant bien la structure de l&amp;#8217;objet dans le FormBuilder de base.&lt;/p&gt;
&lt;p style="errors.is_a?(Array) ? errors.first : errors;"&gt;C&amp;#8217;est partit :&lt;br /&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;text_field&lt;/span&gt;(&lt;span class="Variable"&gt;method&lt;span class="Variable"&gt;,&lt;/span&gt; options &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Variable"&gt;{&lt;/span&gt;&lt;span class="Variable"&gt;}&lt;/span&gt;&lt;/span&gt;)
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;       object &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;template&lt;/span&gt;.&lt;span class="Entity"&gt;instance_variable_get&lt;/span&gt;(&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;@&lt;span class="String"&gt;&lt;span class="String"&gt;#{&lt;/span&gt;&lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;object_name&lt;/span&gt;&lt;span class="String"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;       &lt;span class="Keyword"&gt;unless&lt;/span&gt; object.&lt;span class="Entity"&gt;nil?&lt;/span&gt; &lt;span class="Keyword"&gt;||&lt;/span&gt; options[&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;hide_errors&lt;/span&gt;]
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;         errors &lt;span class="Keyword"&gt;=&lt;/span&gt; object.&lt;span class="Entity"&gt;errors&lt;/span&gt;.&lt;span class="Entity"&gt;on&lt;/span&gt;(method.&lt;span class="Entity"&gt;to_sym&lt;/span&gt;)
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;         &lt;span class="Keyword"&gt;if&lt;/span&gt; errors
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt;           text &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt; &amp;lt;span class=&lt;span class="Constant"&gt;\&amp;quot;&lt;/span&gt;error&lt;span class="Constant"&gt;\&amp;quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt; &lt;span class="String"&gt;              &lt;span class="String"&gt;&lt;span class="String"&gt;#{&lt;/span&gt;errors&lt;span class="String"&gt;&lt;span class="String"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;is_a?&lt;/span&gt;&lt;/span&gt;&lt;span class="String"&gt;(&lt;/span&gt;&lt;span class="Variable"&gt;Array&lt;/span&gt;&lt;span class="String"&gt;)&lt;/span&gt; &lt;span class="Keyword"&gt;?&lt;/span&gt; errors&lt;span class="String"&gt;&lt;span class="String"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;first&lt;/span&gt;&lt;/span&gt; &lt;span class="String"&gt;:&lt;/span&gt; errors&lt;span class="String"&gt;}&lt;/span&gt;&lt;/span&gt;&amp;lt;/span&amp;gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt;         &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;   9 &lt;/span&gt;       &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;  10 &lt;/span&gt;       &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;template&lt;/span&gt;.&lt;span class="Entity"&gt;text_field&lt;/span&gt;(&lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;object_name&lt;/span&gt;, method, 
&lt;span class="line-numbers"&gt;  11 &lt;/span&gt;          &lt;span class="Entity"&gt;objectify_options&lt;/span&gt;(options))&lt;span class="Keyword"&gt;+&lt;/span&gt;text.&lt;span class="Entity"&gt;to_s&lt;/span&gt;
&lt;span class="line-numbers"&gt;  12 &lt;/span&gt;   &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;La première chose que l&amp;#8217;on fait dans ce nouveau helper text_field, c&amp;#8217;est récupérer l&amp;#8217;objet. Ensuite on vérifie s&amp;#8217;il contient des erreurs relatives à la méthode que l&amp;#8217;on passe en paramètre. Et si il y a des erreurs relatives à cette méthode, on vient concaténer un bloc span contenant le premier message d&amp;#8217;erreur.&lt;/p&gt;
&lt;p&gt;Un peu de css :&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; span.&lt;span class="Entity"&gt;error&lt;/span&gt; {
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;   color:&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt;c30;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;   float&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;left&lt;/span&gt;;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;   display&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;block&lt;/span&gt;;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;   font&lt;span class="Keyword"&gt;-&lt;/span&gt;size:&lt;span class="Constant"&gt;1.&lt;/span&gt;1em;
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt;   font&lt;span class="Keyword"&gt;-&lt;/span&gt;weight&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;bold&lt;/span&gt;;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt;   line&lt;span class="Keyword"&gt;-&lt;/span&gt;height:14px;
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt;   text&lt;span class="Keyword"&gt;-&lt;/span&gt;align&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;left&lt;/span&gt;;
&lt;span class="line-numbers"&gt;   9 &lt;/span&gt;   padding:0px &lt;span class="Constant"&gt;0&lt;/span&gt; &lt;span class="Constant"&gt;0&lt;/span&gt; 5px;
&lt;span class="line-numbers"&gt;  10 &lt;/span&gt;   width:190px;
&lt;span class="line-numbers"&gt;  11 &lt;/span&gt; }
&lt;/pre&gt;
&lt;p&gt;Et voilà ! Une toute nouvelle manière d&amp;#8217;ajouter les erreurs dans vos formulaires, et pour pas des masses d&amp;#8217;effort ;)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/FrailersArticles/~4/ks3C-E5lf0Q" height="1" width="1"/&gt;</description>
      <pubDate>Wed, 18 Mar 2009 00:00:00 +0000</pubDate>
      <link>http://feedproxy.google.com/~r/FrailersArticles/~3/ks3C-E5lf0Q/60-un-form-builder-pour-afficher-les-erreurs-d-un-champ-autrement</link>
      <guid isPermaLink="false">http://www.frailers.net/articles/60-un-form-builder-pour-afficher-les-erreurs-d-un-champ-autrement</guid>
    <feedburner:origLink>http://www.frailers.net/articles/60-un-form-builder-pour-afficher-les-erreurs-d-un-champ-autrement</feedburner:origLink></item>
    <item>
      <title>Exporter ses données dans un tableur</title>
      <description>&lt;p&gt;Il arrive souvent que l&amp;#8217;on aie besoin d&amp;#8217;exporter un ensemble d&amp;#8217;informations pour y accéder de manière plus conviviale dans un tableur.&lt;/p&gt;
&lt;p&gt;Dans cet article, je vais vous montrer deux manières d&amp;#8217;exporter un ensemble de données, ou plutôt deux formats différents pour cette exportation.&lt;/p&gt; &lt;h2&gt;Partie 1 : Exporter en csv&lt;/h2&gt;
&lt;p&gt;Le premier format qui me vient à l&amp;#8217;esprit quand on me parle de tableur, est bien évidemment le format csv (Comma Separated Values) qui, pour ceux qui ne le sauraient pas encore, sépare chaque valeur d&amp;#8217;une colonne par une virgule.&lt;/p&gt;
&lt;p&gt;La première chose à faire c&amp;#8217;est d&amp;#8217;installer la gem fastercsv.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; sudo gem install fastercsv
&lt;/pre&gt;
&lt;p&gt;Puis d&amp;#8217;installer le plugin to_csv d&amp;#8217;Ary Djmal dans votre application.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; script&lt;span class="Keyword"&gt;/&lt;/span&gt;plugin install git&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;/&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;github.&lt;span class="Entity"&gt;com&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;arydjmal&lt;span class="Keyword"&gt;/&lt;/span&gt;to_csv.git
&lt;/pre&gt;
&lt;p&gt;La suite est encore plus simple. Pas besoin de &amp;#8216;builder&amp;#8217;, il suffit, dans le bloc respond_to de l&amp;#8217;action de votre contrôleur et pour le format csv, d&amp;#8217;appeler la méthode to_csv sur votre tableau de données, elle est pas belle la vie ? :-)&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;UsersController&lt;span class="Superclass"&gt; &lt;span class="Superclass"&gt;&amp;lt;&lt;/span&gt; ApplicationController&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;   &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;index&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;     &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;users&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;User&lt;/span&gt;.&lt;span class="Entity"&gt;find&lt;/span&gt;(&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;all&lt;/span&gt;)
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;     respond_to &lt;span class="Keyword"&gt;do &lt;/span&gt;|&lt;span class="Variable"&gt;format&lt;/span&gt;|
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt;       format.&lt;span class="Entity"&gt;html&lt;/span&gt;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt;       format.&lt;span class="Entity"&gt;csv&lt;/span&gt; { send_data &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;users&lt;/span&gt;.&lt;span class="Entity"&gt;to_csv&lt;/span&gt; }
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt;     &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;   9 &lt;/span&gt;   &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;  10 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Il suffit alors d&amp;#8217;ajouter dans votre vue un lien du style :&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%=&lt;/span&gt; link_to &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;Exporter en csv&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="Entity"&gt;formatted_users_path&lt;/span&gt;(&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;format&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;csv&lt;/span&gt;) &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Et le tour est joué !&lt;/p&gt;
&lt;h2&gt;Partie 2 : Exporter en xls&lt;/h2&gt;
&lt;p&gt;Mais je vois déjà venir les mauvaises langues avec leurs gros sabots :&lt;/p&gt;
&lt;p&gt;&amp;#8220;Haaaa mais môôôsieur, le csv c&amp;#8217;est bien beau mais mon Excel(lent) tableur préféré ne gère pas les caractères en &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 dans un csv&amp;#8221;&lt;/p&gt;
&lt;p&gt;&amp;#8220;Pas de bol&amp;#8221;, vous dirais-je, mais pas de panique Ary a pensé à vous, pauvres utilisateurs de MS Excel.&lt;/p&gt;
&lt;p&gt;Première étape, il nous faut ajouter ce nouveau type de fichier obscur dans notre initializer mime_types que vous trouverez à config/initializers/mime_types.rb&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Support"&gt;Mime&lt;/span&gt;::&lt;span class="Entity"&gt;Type&lt;/span&gt;.&lt;span class="Entity"&gt;register&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;application/vnd.ms-excel&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;xls&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Et d&amp;#8217;installer un second plugin, to_xls&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; script&lt;span class="Keyword"&gt;/&lt;/span&gt;plugin install git&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;/&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;github.&lt;span class="Entity"&gt;com&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;arydjmal&lt;span class="Keyword"&gt;/&lt;/span&gt;to_xls.git
&lt;/pre&gt;
&lt;p&gt;Ouf ! Le plus dur est fait :-)&lt;/p&gt;
&lt;p&gt;La suite est à peu de choses près exactement la même que pour to_csv, sauf qu&amp;#8217;il s&amp;#8217;agit maintenant de to_xls, donc, au risque de me répéter, elle est pas belle la vie ?&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;UsersController&lt;span class="Superclass"&gt; &lt;span class="Superclass"&gt;&amp;lt;&lt;/span&gt; ApplicationController&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;   &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;index&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;     &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;users&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;User&lt;/span&gt;.&lt;span class="Entity"&gt;find&lt;/span&gt;(&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;all&lt;/span&gt;)
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;     respond_to &lt;span class="Keyword"&gt;do &lt;/span&gt;|&lt;span class="Variable"&gt;format&lt;/span&gt;|
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt;       format.&lt;span class="Entity"&gt;html&lt;/span&gt;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt;       format.&lt;span class="Entity"&gt;xls&lt;/span&gt; { send_data &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;users&lt;/span&gt;.&lt;span class="Entity"&gt;to_xls&lt;/span&gt; }
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt;     &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;   9 &lt;/span&gt;   &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;  10 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Il suffit alors d&amp;#8217;ajouter un lien dans notre vue qui fait appel au bon format :&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%=&lt;/span&gt; link_to &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;Exporter en xls&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="Entity"&gt;formatted_users_path&lt;/span&gt;(&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;format&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;xls&lt;/span&gt;) &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;La méthode to_xls crée en fait un fichier &lt;span class="caps"&gt;XML&lt;/span&gt; lisible par Excel. Attention cependant, cela ne marchera que pour les versions d&amp;#8217;Excel 2003 et plus.&lt;/p&gt;
&lt;p&gt;Quelques liens de référence:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://arydjmal.com/2008/6/11/to_csv-plugin-better-excel-compatibility"&gt;to_csv plugin: Better Excel compatibility&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://arydjmal.com/2009/1/11/to_xls-plugin-export-to-excel-in-rails-the-easy-way"&gt;to_xls plugin: Export to Excel in Rails the easy way&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://arydjmal.com/2008/6/8/export-to-excel-in-rails-2"&gt;Export to Excel in Rails 2&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/FrailersArticles/~4/qlVmgKjmKhY" height="1" width="1"/&gt;</description>
      <pubDate>Fri, 06 Mar 2009 00:00:00 +0000</pubDate>
      <link>http://feedproxy.google.com/~r/FrailersArticles/~3/qlVmgKjmKhY/59-exporter-ses-donne-es-dans-un-tableur</link>
      <guid isPermaLink="false">http://www.frailers.net/articles/59-exporter-ses-donne-es-dans-un-tableur</guid>
    <feedburner:origLink>http://www.frailers.net/articles/59-exporter-ses-donne-es-dans-un-tableur</feedburner:origLink></item>
    <item>
      <title>Recherche "Full text" avec xapian</title>
      <description>&lt;p&gt;Une recherche &amp;#8220;Full text&amp;#8221; devient souvent une nécessité lorsqu&amp;#8217;on travaille sur des projets  ayant beaucoup de contenu. Différents outils permettent de réaliser ce genre de recherches avec plus ou moins d&amp;#8217;efficacité. Pour Rails, il existe bien évidement Ferret, probablement le plus connu, mais aussi Solr basé sur Lucene, Sphinx et enfin, Xapian.&lt;/p&gt;
&lt;p&gt;Je n&amp;#8217;ai pas la prétention de dire que je suis un expert en la matière mais ayant utilisé Xapian durant le dernier projet sur lequel j&amp;#8217;ai travaillé, je me suis dit qu&amp;#8217;un petit partage de connaissances s&amp;#8217;imposait. Histoire de vous donner les moyens de tester tout ça par vous-même.&lt;/p&gt; &lt;h2&gt;Etape 1 : Installer Xapian&lt;/h2&gt;
&lt;p&gt;Suivant votre OS il existe plusieurs manières d&amp;#8217;installer Xapian. Tout est expliqué sur le &lt;a href="http://www.xapian.org"&gt;site de Xapian&lt;/a&gt;. Choisissez la manière qui vous convient le mieux. Pour l&amp;#8217;exemple on partira des fichiers source !&lt;/p&gt;
&lt;p&gt;Télécharger les sources de xapian :&lt;br /&gt;
&lt;a href="http://oligarchy.co.uk/xapian/1.0.10/xapian-core-1.0.10.tar.gz"&gt;http://oligarchy.co.uk/xapian/1.0.10/xapian-core-1.0.10.tar.gz&lt;/a&gt;&lt;br /&gt;
Et les bindings qui nous permettrons de l&amp;#8217;utiliser avec Ruby :&lt;br /&gt;
&lt;a href="http://oligarchy.co.uk/xapian/1.0.10/xapian-bindings-1.0.10.tar.gz"&gt;http://oligarchy.co.uk/xapian/1.0.10/xapian-bindings-1.0.10.tar.gz&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Il est bien évidement conseillé d&amp;#8217;utiliser la même version pour xapian et ses &amp;#8220;bindings&amp;#8221;.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; tar xvzf xapian&lt;span class="Keyword"&gt;-&lt;/span&gt;core&lt;span class="Keyword"&gt;-&lt;/span&gt;version.&lt;span class="Entity"&gt;tar&lt;/span&gt;.&lt;span class="Entity"&gt;gz&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; tar xvzf xapian&lt;span class="Keyword"&gt;-&lt;/span&gt;bindings&lt;span class="Keyword"&gt;-&lt;/span&gt;version.&lt;span class="Entity"&gt;tar&lt;/span&gt;.&lt;span class="Entity"&gt;gz&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt; cd xapian&lt;span class="Keyword"&gt;-&lt;/span&gt;core&lt;span class="Keyword"&gt;-&lt;/span&gt;version
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt; .&lt;span class="Keyword"&gt;/&lt;/span&gt;configure
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt; make
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt; sudo make install
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;   9 &lt;/span&gt; cd xapian&lt;span class="Keyword"&gt;-&lt;/span&gt;bindings&lt;span class="Keyword"&gt;-&lt;/span&gt;version
&lt;span class="line-numbers"&gt;  10 &lt;/span&gt; .&lt;span class="Keyword"&gt;/&lt;/span&gt;configure
&lt;span class="line-numbers"&gt;  11 &lt;/span&gt; make
&lt;span class="line-numbers"&gt;  12 &lt;/span&gt; sudo make install
&lt;/pre&gt;
&lt;h2&gt;Etape 2 : Installer acts_as_xapian&lt;/h2&gt;
&lt;p&gt;La première chose à faire est de récupérer acts_as_xapian sur github.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; script&lt;span class="Keyword"&gt;/&lt;/span&gt;plugin install git&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;/&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;github.&lt;span class="Entity"&gt;com&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;frabcus&lt;span class="Keyword"&gt;/&lt;/span&gt;acts_as_xapian.git
&lt;/pre&gt;
&lt;p&gt;Ensuite, d&amp;#8217;exécuter les migrations associées.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; script&lt;span class="Keyword"&gt;/&lt;/span&gt;generate acts_as_xapian
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; rake db&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;migrate&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Voilà, nous sommes prêts !&lt;/p&gt;
&lt;h2&gt;Etape 3 : Tous dans le bac à sable&lt;/h2&gt;
&lt;p&gt;Dans tous les modèles ou vous souhaitez utiliser une recherche &amp;#8220;Full text&amp;#8221; ajoutez la ligne suivante :&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;Stuff&lt;span class="Superclass"&gt; &lt;span class="Superclass"&gt;&amp;lt;&lt;/span&gt; ActiveRecord:Base&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;  acts_as_xapian &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;texts&lt;/span&gt; =&amp;gt; [&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;title&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;description&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;tags&lt;/span&gt;]
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;En remplaçant, bien évidement :title, :description et :tags par les champs de votre modèle dans lesquels vous souhaitez faire la recherche.&lt;/p&gt;
&lt;p&gt;Ajoutez quelques objets en db et construisez l&amp;#8217;index de recherche en prenant soin de spécifier les modèles (séparés par un espace) pour lesquels il est nécessaire de construire cet index.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; rake xapian&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;build_index&lt;/span&gt; models&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;Stuff AutreModel1 AutreModel2&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;On peut alors tester la recherche en console :&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; rake xapian&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;query&lt;/span&gt; models&lt;span class="Keyword"&gt;=&lt;/span&gt;“&lt;span class="Variable"&gt;Stuff&lt;/span&gt; &lt;span class="Variable"&gt;AutreModel1&lt;/span&gt; &lt;span class="Variable"&gt;AutreModel2&lt;/span&gt;” query&lt;span class="Keyword"&gt;=&lt;/span&gt;“test”
&lt;/pre&gt;
&lt;p&gt;Qui aura pour effet de rechercher &amp;#8220;test&amp;#8221; dans les champs renseignés dans le paramètre :texts de acts_as_xapian des trois modèles spécifiés.&lt;/p&gt;
&lt;h2&gt;Etape 4 : Et dans mon contrôleur ça donne quoi ?&lt;/h2&gt;
&lt;p&gt;C&amp;#8217;est tout simple :&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;query&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;ActsAsXapian&lt;/span&gt;::&lt;span class="Entity"&gt;Search&lt;/span&gt;.&lt;span class="Entity"&gt;new&lt;/span&gt;([&lt;span class="Variable"&gt;Stuff&lt;/span&gt;], &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;query_params&lt;/span&gt;)
&lt;/pre&gt;
&lt;p&gt;On cherche dans le modèle Stuff avec pour paramètres de recherche @query_params (la chaîne de caractères que l&amp;#8217;on veut rechercher).&lt;/p&gt;
&lt;p&gt;Pour obtenir les résultats il suffit de faire :&lt;br /&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;results&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;query&lt;/span&gt;.results
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Attention ! @results n&amp;#8217;est pas un tableau d&amp;#8217;objets d&amp;#8217;un modèle ActiveRecord ! Pour ça, il faut repasser le tout à la moulinette :&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;stuffs&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;results&lt;/span&gt;.&lt;span class="Entity"&gt;collect&lt;/span&gt;{|&lt;span class="Variable"&gt;r&lt;/span&gt;| r[&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;model&lt;/span&gt;]}
&lt;/pre&gt;
&lt;p&gt;Ou pour faire simple et en une seule ligne :&lt;br /&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;stuffs&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;ActsAsXapian&lt;/span&gt;::&lt;span class="Entity"&gt;Search&lt;/span&gt;.&lt;span class="Entity"&gt;new&lt;/span&gt;([&lt;span class="Variable"&gt;Stuff&lt;/span&gt;], &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;query_params&lt;/span&gt;)
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;              .&lt;span class="Entity"&gt;results&lt;/span&gt;.&lt;span class="Entity"&gt;collect&lt;/span&gt;{|&lt;span class="Variable"&gt;r&lt;/span&gt;| r[&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;model&lt;/span&gt;]}
&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;Etape 5 : Et si mes données changent ?&lt;/h2&gt;
&lt;p&gt;Le seul petit problème d&amp;#8217;acts_as_xapian est qu&amp;#8217;il ne propose pas de mise à jour automatique de l&amp;#8217;index lorsqu&amp;#8217;il y a un changement dans les données. Si changement il y a, cette modification est ajoutée à la table acts_as_xapian_jobs que nous avons créée grâce à la migration de l&amp;#8217;étape 2. Et ce n&amp;#8217;est que lorsque l&amp;#8217;on exécute&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; rake xapian&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;update_index&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;que les changements sont pris en compte. Vous trouverez plus d&amp;#8217;explications en suivant le premier lien à la fin de cet article. Qu&amp;#8217;avons-nous fait dans notre dernier projet ? Une simple tâche cron, qui est appelée toutes les x minutes et qui met à jour l&amp;#8217;index. Une autre qui s&amp;#8217;exécute une fois par jour pour reconstruire complètement l&amp;#8217;index.&lt;/p&gt;
&lt;h2&gt;Etape 6 : Et maintenant ?&lt;/h2&gt;
&lt;p&gt;Plusieurs autres possibilités sont présentes dans acts_as_xapian, comme la recherche par &amp;#8216;terms&amp;#8217;, ou encore la possibilité de proposer des corrections ou des alternatives à la recherche effectuée.&lt;/p&gt;
&lt;p&gt;Notre introduction s&amp;#8217;arrête malheureusement là, mais les quelques liens suivants vous serons sûrement très utiles :&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.locomotivation.com/blog/2008/07/23/simple-ruby-on-rails-full-text-search-using-xapian.html"&gt;Simple Ruby on Rails Full Text Search Using Xapian&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://xapian.org/"&gt;The Xapian project&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.locomotivation.com/blog/2008/07/15/mulling-over-our-ruby-on-rails-full-text-search-options.html"&gt;Mulling over our Ruby on Rails full text search options&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/FrailersArticles/~4/i3PoRfltquA" height="1" width="1"/&gt;</description>
      <pubDate>Wed, 04 Mar 2009 00:00:00 +0000</pubDate>
      <link>http://feedproxy.google.com/~r/FrailersArticles/~3/i3PoRfltquA/58-recherche-full-text-avec-xapian</link>
      <guid isPermaLink="false">http://www.frailers.net/articles/58-recherche-full-text-avec-xapian</guid>
    <feedburner:origLink>http://www.frailers.net/articles/58-recherche-full-text-avec-xapian</feedburner:origLink></item>
    <item>
      <title>Une application pas à pas - My Tag Cloud - épisode 3</title>
      <description>&lt;p&gt;Dans mon dernier article, nous avions passé en revue les éléments nécessaires à notre concept de &amp;#8216;tag cloud&amp;#8217;. Cette semaine, on replonge dans facebooker.&lt;/p&gt;
&lt;p&gt;Au menu, mise en place d&amp;#8217;une profile box et du &lt;em&gt;Publisher&lt;/em&gt; qui va avec.&lt;/p&gt; &lt;p&gt;A l&amp;#8217;image de Rails qui propose ActionMailer, une interface claire pour l&amp;#8217;envoi d&amp;#8217;emails, facebooker propose l&amp;#8217;interface &lt;em&gt;Publisher&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Dans ce Publisher, on peut définir des méthodes pour envoyer des notifications, des feeds, ou du contenu à une profile box.&lt;/p&gt;
&lt;p&gt;Commençons par générer notre publisher.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; script&lt;span class="Keyword"&gt;/&lt;/span&gt;generate facebook_publisher facebook
&lt;/pre&gt;
&lt;p&gt;Nous voilà maintenant avec un &lt;em&gt;Publisher&lt;/em&gt; vide et les migrations qui vont avec, migrations qui nous seront utiles lorsque nous voudrons publier des feeds.&lt;/p&gt;
&lt;p&gt;Commençons simplement par ajouter le helper de notre application à notre publisher.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;FacebookPublisher&lt;span class="Superclass"&gt; &lt;span class="Superclass"&gt;&amp;lt;&lt;/span&gt; Facebooker::Rails::Publisher&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;   &lt;span class="Support"&gt;helper&lt;/span&gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;application&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Ajoutons ensuite une méthode profile_update.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;profile_update&lt;/span&gt;(&lt;span class="Variable"&gt;user&lt;/span&gt;)
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;  send_as &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;profile&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;  recipients user
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;  profile &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;Testing...&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Il suffit alors d&amp;#8217;aller ajouter la ligne suivante dans le bas du layout de l&amp;#8217;application&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%=&lt;/span&gt; fb_add_profile_section &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Qui a pour effet d&amp;#8217;ajouter un bouton &amp;#8216;Add to profile&amp;#8217;. Lorsqu&amp;#8217;on clique dessus, on voit apparaître une boîte de dialogue nous demandant notre accord.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://frailers.net/uploads/fb3x2.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Et voilà ce que ça donne dans l&amp;#8217;onglet &amp;#8216;Boîtes&amp;#8217; !&lt;/p&gt;
&lt;p&gt;&lt;img src="http://frailers.net/uploads/fb3x1.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Comme vous le savez peut-être déjà, une profile box peut se placer à plusieurs endroits et avoir plusieurs tailles. Un onglet &amp;#8216;Boîtes&amp;#8217; a été ajouté dans le nouveau profil, qui permet de stocker des &amp;#8216;profile boxes&amp;#8217; de deux largeurs, 380 pixels pour les larges et 180 pixels pour les petites.&lt;/p&gt;
&lt;p&gt;Mais cette boîte peut aussi être ajoutée à votre wall. La taille est, ici, encore différente, 250 pixels de hauteur maximum, la largeur étant également de 180 pixels.&lt;/p&gt;
&lt;p&gt;Les tags &lt;span class="caps"&gt;FBML&lt;/span&gt; suivants permettent de définir un contenu spécifique pour chaque largeur.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;fb&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;wide&lt;/span&gt;&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;fb&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;narrow&lt;/span&gt;&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Dans notre exemple, nous ne différencierons pas les différentes tailles, étant donné que ce que nous devons afficher prend peu de place&amp;#8230;&lt;/p&gt;
&lt;p&gt;Nous pourrions définir le contenu de notre profile box directement après le mot clé &amp;#8220;profile&amp;#8221; dans notre méthode profile_update, mais un partiel semble plus approprié.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;profile_update&lt;/span&gt;(&lt;span class="Variable"&gt;user&lt;/span&gt;)
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;  send_as &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;profile&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;  recipients user
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;  &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;friend&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;Friend&lt;/span&gt;.&lt;span class="Entity"&gt;find_by_facebook_id&lt;/span&gt; user.&lt;span class="Entity"&gt;id&lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;  profile &lt;span class="Support"&gt;render&lt;/span&gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;partial&lt;/span&gt; =&amp;gt; &lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;profile.fbml.erb&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;locals&lt;/span&gt; =&amp;gt; {&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;user&lt;/span&gt; =&amp;gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;friend&lt;/span&gt;}
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Nous envoyons au partiel les informations concernant l&amp;#8217;utilisateur. De cette manière on pourra récupérer les tags dudit utilisateur dans le partiel.&lt;/p&gt;
&lt;p&gt;Dans le dossier apps/views/facebook_publisher/ fraîchement créé, nous ajoutons notre partiel _profile.fbml.erb :&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%&lt;/span&gt; &lt;span class="Keyword"&gt;if&lt;/span&gt; user.&lt;span class="Entity"&gt;tag_list&lt;/span&gt;.&lt;span class="Entity"&gt;empty?&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; &lt;span class="String"&gt; &amp;lt;p&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Variable"&gt;No&lt;/span&gt; tags yet...&lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;p&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%&lt;/span&gt; &lt;span class="Keyword"&gt;else&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt; &lt;span class="String"&gt; &amp;lt;% tag_cloud user.tag_counts(:order =&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;name&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;), 
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;     &lt;span class="String"&gt;&lt;span class="String"&gt;%w(&lt;/span&gt;css1 css2 css3 css4&lt;span class="String"&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class="Keyword"&gt;do &lt;/span&gt;|&lt;span class="Variable"&gt;tag&lt;/span&gt;, &lt;span class="Variable"&gt;css_class&lt;/span&gt;| &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt; &lt;span class="String"&gt;  &amp;lt;span class=&amp;lt;%= css_class %&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&amp;gt;&lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%=&lt;/span&gt; tag.&lt;span class="Entity"&gt;name&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&amp;lt;/span&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt;  &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%&lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt; &lt;span class="String"&gt;&amp;lt;% end %&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Les pages de profils sont mises en cache par les serveurs de Facebook, il est donc nécessaire de forcer la mise à jour de contenu dans une profile box, d&amp;#8217;où l&amp;#8217;importance du &lt;em&gt;Publisher&lt;/em&gt;. Nous devons donc, à un instant dans le processus d&amp;#8217;utilisation de notre application, faire un &amp;#8220;push&amp;#8221; du contenu.&lt;/p&gt;
&lt;p&gt;Il suffit alors de faire l&amp;#8217;appel suivant lorsque quelqu&amp;#8217;un vous a taggé ou lorsque vous taggez quelqu&amp;#8217;un, en prenant soin bien sûr de donner en paramètre le bon utilisateur. Pour les besoins de l&amp;#8217;article et pour voir un résultat directement nous allons placer cet appel dans notre contrôleur Friends, dans l&amp;#8217;action show par exemple. Je rappelle que ce n&amp;#8217;est que pour les besoins de cet article, dans ce cas la profile box ne sera mise à jour que lorsque l&amp;#8217;utilisateur consultera son tag cloud dans l&amp;#8217;application, ce qui n&amp;#8217;a pas grand intérêt&amp;#8230;&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Support"&gt;FacebookPublisher&lt;/span&gt;.&lt;span class="Entity"&gt;deliver_profile_update&lt;/span&gt;(&lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;facebook_session&lt;/span&gt;.&lt;span class="Entity"&gt;user&lt;/span&gt;)
&lt;/pre&gt;
&lt;p&gt;Ce qui donne sur notre profil :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://frailers.net/uploads/fb3x3.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Et voilà le travail ! Dans le prochain article, nous nous attarderons sur les feeds.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/FrailersArticles/~4/rr-nY61hzEc" height="1" width="1"/&gt;</description>
      <pubDate>Thu, 05 Feb 2009 00:00:00 +0000</pubDate>
      <link>http://feedproxy.google.com/~r/FrailersArticles/~3/rr-nY61hzEc/57-une-application-pas-a-pas-my-tag-cloud-e-pisode-3</link>
      <guid isPermaLink="false">http://www.frailers.net/articles/57-une-application-pas-a-pas-my-tag-cloud-e-pisode-3</guid>
    <feedburner:origLink>http://www.frailers.net/articles/57-une-application-pas-a-pas-my-tag-cloud-e-pisode-3</feedburner:origLink></item>
    <item>
      <title>Frailers.net passe à l'open source!</title>
      <description>&lt;p&gt;Après un an et demi d&amp;#8217;activité sur Frailers.net, nous avons décidé de rendre son code source publiquement disponible sur GitHub. Nous en avons profité pour le remettre un peu au goût du jour. Vous trouverez tout ici:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://github.com/belighted/frailers"&gt;http://github.com/belighted/frailers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Comme mentionné dans le &lt;span class="caps"&gt;README&lt;/span&gt;, quelques points forts du code:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;basé sur Rails 2.3&lt;/li&gt;
	&lt;li&gt;utilisation du framework i18n de Rails pour le français&lt;/li&gt;
	&lt;li&gt;mise en évidence de la syntaxe dans le blog (via ultraviolet/oniguruma)&lt;/li&gt;
	&lt;li&gt;100% RESTful&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nous espérons que cela permettra aux débutants (et aux autres!) de voir comment fonctionne une application &amp;#8220;réelle&amp;#8221;, sachant que nous allons continuer à mettre le code à jour au fur et à mesure que de nouvelles fonctionnalités (et bugs ;-)) apparaîtront.&lt;/p&gt;
&lt;p&gt;N&amp;#8217;hésitez bien entendu pas à télécharger et commenter le code. Bon amusement!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/FrailersArticles/~4/b5MYW_gCtTg" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 03 Feb 2009 00:00:00 +0000</pubDate>
      <link>http://feedproxy.google.com/~r/FrailersArticles/~3/b5MYW_gCtTg/55-frailers-net-passe-a-l-open-source</link>
      <guid isPermaLink="false">http://www.frailers.net/articles/55-frailers-net-passe-a-l-open-source</guid>
    <feedburner:origLink>http://www.frailers.net/articles/55-frailers-net-passe-a-l-open-source</feedburner:origLink></item>
    <item>
      <title>Ruby on Rails Dev Room au FOSDEM '09 ce dimanche</title>
      <description>&lt;p&gt;Ce week-end se tiendra à Bruxelles le célèbre &lt;a href="http://www.fosdem.org"&gt;&lt;span class="caps"&gt;FOSDEM&lt;/span&gt;&lt;/a&gt; (Free and Open Source Software Developers&amp;#8217; European Meeting), un ensemble de conférences organisées chaque année autour du logiciel libre.&lt;/p&gt;
&lt;p&gt;Comme l&amp;#8217;an passé, une des &amp;#8220;developer rooms&amp;#8221; est consacrée le dimanche à &lt;a href="http://fosdem.org/2009/schedule/devrooms/rubyandrails"&gt;Ruby on Rails&lt;/a&gt; et vos dévoués serviteurs y auront d&amp;#8217;ailleurs l&amp;#8217;occasion de faire 2 présentations (en english):&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Jean-Baptiste, à 14h45, sur le thème &lt;a href="http://fosdem.org/2009/schedule/events/ror_ruby_and_java"&gt;Ruby and Java: What are the differences?&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Nicolas, à 15h30, sur le thème &lt;a href="http://fosdem.org/2009/schedule/events/ror_i18n_rails_2_2"&gt;Internationalization in Rails 2.2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour la liste complète des présentations, reportez vous à la &lt;a href="http://fosdem.org/2009/schedule/devrooms/rubyandrails"&gt;page officielle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Si vous comptez y être présent, n&amp;#8217;hésitez pas à le signaler via Frailers sur notre page liée à l&amp;#8217;événement: &lt;a href="http://frailers.net/events/5-fosdem-09-ror-devroom"&gt;&lt;span class="caps"&gt;FOSDEM&lt;/span&gt; &amp;#8217;09 &amp;#8211; RoR DevRoom&lt;/a&gt; &amp;#8230; et bien sûr, passez nous dire bonjour!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/FrailersArticles/~4/oefHyKObjUw" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 03 Feb 2009 00:00:00 +0000</pubDate>
      <link>http://feedproxy.google.com/~r/FrailersArticles/~3/oefHyKObjUw/56-ruby-on-rails-dev-room-au-fosdem-09-ce-dimanche</link>
      <guid isPermaLink="false">http://www.frailers.net/articles/56-ruby-on-rails-dev-room-au-fosdem-09-ce-dimanche</guid>
    <feedburner:origLink>http://www.frailers.net/articles/56-ruby-on-rails-dev-room-au-fosdem-09-ce-dimanche</feedburner:origLink></item>
    <item>
      <title>Une application pas à pas - My Tag Cloud - épisode 2</title>
      <description>&lt;p&gt;Après quelques jours de vacances bien méritées, me voilà de retour sur vos écrans pour la suite de notre petite saga (si toi aussi tu chantes Saga Africa en ce moment frappe dans tes mains), la création d&amp;#8217;une application Facebook.&lt;/p&gt;
&lt;p&gt;Dans mon dernier article, nous avons passé en revue la création d&amp;#8217;un système d&amp;#8217;invitations. Cette semaine, nous allons commencer à construire la logique de notre application, moins de concepts liés à facebooker donc&amp;#8230; Au programme, création de modèles et installation des plug-ins nécessaires. Let&amp;#8217;s go!&lt;/p&gt; &lt;p&gt;Rappelez-vous, le but de l&amp;#8217;application &amp;#8220;My Tag Cloud&amp;#8221; est de pouvoir tagger ses amis, mais aussi d&amp;#8217;afficher son propre tag cloud. La première chose que nous allons faire c&amp;#8217;est ajouter des onglets à notre application. Pour ce faire, deux possibilités, soit utiliser du &lt;span class="caps"&gt;FBML&lt;/span&gt; pur&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;fb&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;tabs&lt;/span&gt;&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;   &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;fb&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;tab&lt;/span&gt;&lt;span class="Keyword"&gt;-&lt;/span&gt;item href&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;someplace&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt; title&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;Someplace&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt; selected&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;true&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;   &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;fb&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;tab&lt;/span&gt;&lt;span class="Keyword"&gt;-&lt;/span&gt;item href&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;someotherplace&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt; title&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;Otherplace&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="Keyword"&gt;/&lt;/span&gt;&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;  &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;fb&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;tabs&lt;/span&gt;&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;soit les helpers fournis par facebooker, la solution que nous retiendrons pour l&amp;#8217;occasion.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%&lt;/span&gt; fb_tabs &lt;span class="Keyword"&gt;do &lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; &lt;span class="String"&gt;	&amp;lt;%= fb_tab_item &amp;quot;My Tag Cloud&amp;quot;, friend_path(@user), &lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="String"&gt;       :selected =&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;friends&lt;/span&gt;.&lt;span class="Entity"&gt;nil?&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt; &lt;span class="String"&gt;	&amp;lt;%= fb_tab_item &amp;quot;Tag my friends !&amp;quot;, friends_path, &lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt; &lt;span class="String"&gt;       :selected =&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;span class="Keyword"&gt;!&lt;/span&gt;&lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;friends&lt;/span&gt;.&lt;span class="Entity"&gt;nil?&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt; &lt;span class="String"&gt;&amp;lt;% end %&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Nous avons donc deux onglets. Un qui nous permettra d&amp;#8217;afficher le tag cloud de l&amp;#8217;utilisateur courant, l&amp;#8217;autre pour afficher la liste de tous vos amis à tagger.&lt;/p&gt;
&lt;p&gt;Afin de déterminer quel onglet est sélectionné, il suffit de tester si la variable @friends qui contient la liste de tous vos amis, existe ou pas.&lt;/p&gt;
&lt;p&gt;Avant de pouvoir mettre du contenu dans tout cela, il faut installer quelques plug-ins. Deux plus exactement. Comme son nom l&amp;#8217;indique, dans notre application on souhaite  tagger des objets, il nous faut donc&amp;#8230; acts_as_taggable. J&amp;#8217;utilise personnellement acts_as_taggable_on_steroids.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; script&lt;span class="Keyword"&gt;/&lt;/span&gt;plugin install
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;  http&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;/&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;svn.&lt;span class="Entity"&gt;viney&lt;/span&gt;.&lt;span class="Entity"&gt;net&lt;/span&gt;.&lt;span class="Entity"&gt;nz&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;things&lt;span class="Keyword"&gt;/&lt;/span&gt;rails&lt;span class="Keyword"&gt;/&lt;/span&gt;plugins&lt;span class="Keyword"&gt;/&lt;/span&gt;acts_as_taggable_on_steroids
&lt;/pre&gt;
&lt;p&gt;On génère les migrations qui lui sont associées et voilà !&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; script&lt;span class="Keyword"&gt;/&lt;/span&gt;generate acts_as_taggable_migration
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; rake db&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;migrate&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;On crée maintenant un modèle Friend que nous rendons &amp;#8220;taggable&amp;#8221;.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;Friend&lt;span class="Superclass"&gt; &lt;span class="Superclass"&gt;&amp;lt;&lt;/span&gt; ActiveRecord::Base&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;   acts_as_taggable
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Et la migration qui va avec :&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;CreateFriends&lt;span class="Superclass"&gt; &lt;span class="Superclass"&gt;&amp;lt;&lt;/span&gt; ActiveRecord::Migration&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;   &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;self.up&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;     create_table &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;friends&lt;/span&gt; &lt;span class="Keyword"&gt;do &lt;/span&gt;|&lt;span class="Variable"&gt;t&lt;/span&gt;|
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;       t.&lt;span class="Entity"&gt;integer&lt;/span&gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;facebook_id&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;limit&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;20&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;null&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;false&lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;     &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt;   &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt;   &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;self.down&lt;/span&gt;
&lt;span class="line-numbers"&gt;   9 &lt;/span&gt;     drop_table &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;friends&lt;/span&gt;
&lt;span class="line-numbers"&gt;  10 &lt;/span&gt;   &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;  11 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Bon, maintenant qu&amp;#8217;on entre dans le vif du sujet, il est temps de se faciliter un peu la vie. Rendez-vous dans l&amp;#8217;application_controller. Déplaçons notre before_filter ici, et ajoutons en un créé par nos soins : find_user. Cette méthode a simplement pour effet de créer deux variables @user et @facebook_session. Ca pourra nous être très utile dans nos vues.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;ApplicationController&lt;span class="Superclass"&gt; &lt;span class="Superclass"&gt;&amp;lt;&lt;/span&gt; ActionController::Base&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;   &lt;span class="Support"&gt;helper&lt;/span&gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;all&lt;/span&gt; &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt; include all helpers, all the time&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;   &lt;span class="Support"&gt;before_filter&lt;/span&gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;ensure_authenticated_to_facebook&lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;   &lt;span class="Support"&gt;before_filter&lt;/span&gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;find_user&lt;/span&gt;
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt;   
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt;   &lt;span class="Keyword"&gt;private&lt;/span&gt;
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt;   
&lt;span class="line-numbers"&gt;   9 &lt;/span&gt;   &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;find_user&lt;/span&gt;
&lt;span class="line-numbers"&gt;  10 &lt;/span&gt;      &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;user&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;Friend&lt;/span&gt;.&lt;span class="Entity"&gt;find_or_create_by_facebook_id&lt;/span&gt;(facebook_session.&lt;span class="Entity"&gt;user&lt;/span&gt;.&lt;span class="Entity"&gt;uid&lt;/span&gt;)
&lt;span class="line-numbers"&gt;  11 &lt;/span&gt;      &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;facebook_session&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; facebook_session
&lt;span class="line-numbers"&gt;  12 &lt;/span&gt;   &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;  13 &lt;/span&gt;   
&lt;span class="line-numbers"&gt;  14 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Parlons-en des vues justement. Il est temps de s&amp;#8217;y attarder un peu.&lt;/p&gt;
&lt;p&gt;Pour le moment notre contrôleur &amp;#8216;Friends&amp;#8217; ne contient qu&amp;#8217;une action index. Nous allons devoir lui ajouter une action show ainsi qu&amp;#8217;une action update, pour mettre à jour les tags de nos amis.&lt;/p&gt;
&lt;p&gt;La vue correspondant à l&amp;#8217;action show du contrôleur &amp;#8216;Friend&amp;#8217; affiche le tag cloud de l&amp;#8217;utilisateur courant.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%&lt;/span&gt; &lt;span class="Keyword"&gt;if&lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;user&lt;/span&gt;.&lt;span class="Entity"&gt;tag_list&lt;/span&gt;.&lt;span class="Entity"&gt;empty?&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; &lt;span class="String"&gt; &amp;lt;p&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Variable"&gt;None&lt;/span&gt; of your friends have tagged you.&lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;p&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%&lt;/span&gt; &lt;span class="Keyword"&gt;else&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt; &lt;span class="String"&gt; &amp;lt;% tag_cloud @user.tag_counts(:order =&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;name&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;),
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;     &lt;span class="String"&gt;&lt;span class="String"&gt;%w(&lt;/span&gt;css1 css2 css3 css4&lt;span class="String"&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class="Keyword"&gt;do &lt;/span&gt;|&lt;span class="Variable"&gt;tag&lt;/span&gt;, &lt;span class="Variable"&gt;css_class&lt;/span&gt;| &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt; &lt;span class="String"&gt;   &amp;lt;span class=&amp;lt;%= css_class %&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&amp;gt;&lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%=&lt;/span&gt; tag.&lt;span class="Entity"&gt;name&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&amp;lt;/span&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt;  &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%&lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt; &lt;span class="String"&gt;&amp;lt;% end %&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Les classes css sont simplements les différents styles utilisés pour le tag cloud. Il suffit de les rajouter au début du layout de l&amp;#8217;application.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;style&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; 	.&lt;span class="Entity"&gt;css1&lt;/span&gt; { font&lt;span class="Keyword"&gt;-&lt;/span&gt;size: &lt;span class="Constant"&gt;0.&lt;/span&gt;8em; color: &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt;999999;}&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; 	.&lt;span class="Entity"&gt;css2&lt;/span&gt; { font&lt;span class="Keyword"&gt;-&lt;/span&gt;size: &lt;span class="Constant"&gt;1.&lt;/span&gt;1em; color: &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt;999999;}&lt;/span&gt;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt; 	.&lt;span class="Entity"&gt;css3&lt;/span&gt; { font&lt;span class="Keyword"&gt;-&lt;/span&gt;size: &lt;span class="Constant"&gt;1.&lt;/span&gt;4em; color: &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt;666666;}&lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt; 	.&lt;span class="Entity"&gt;css4&lt;/span&gt; { font&lt;span class="Keyword"&gt;-&lt;/span&gt;size: &lt;span class="Constant"&gt;1.&lt;/span&gt;7em; color: &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt;333333;}&lt;/span&gt;
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;style&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Revenons maintenant sur notre action index.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;index&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;  &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;friends&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; facebook_session.&lt;span class="Entity"&gt;user&lt;/span&gt;.&lt;span class="Entity"&gt;friends&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Pour le moment on ne fait que récupérer les id facebook de nos amis. Nous avons deux types d&amp;#8217;amis&amp;#8230; Ceux qui ont déjà été taggués et qui se trouvent dans notre base de donnée et les autres, qui sont disponibles via la liste récupérée dans la session Facebook. Il nous faut donc, pour tous les amis ne se trouvants pas dans notre base de donnée, créer un objet Friend. Pour ce faire, on utilise la méthode find_or_initialize_by.&lt;/p&gt;
&lt;p&gt;Nous allons avoir besoin de will_paginate, pour nous permettre de présenter notre liste d&amp;#8217;amis correctement.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; script&lt;span class="Keyword"&gt;/&lt;/span&gt;plugin install git&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;/&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;github.&lt;span class="Entity"&gt;com&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;mislav&lt;span class="Keyword"&gt;/&lt;/span&gt;will_paginate.git
&lt;/pre&gt;

&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;index&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;  &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;facebook_friends&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; []
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;  facebook_session.&lt;span class="Entity"&gt;user&lt;/span&gt;.&lt;span class="Entity"&gt;friends&lt;/span&gt;.&lt;span class="Entity"&gt;each&lt;/span&gt; &lt;span class="Keyword"&gt;do &lt;/span&gt;|&lt;span class="Variable"&gt;fb_friend&lt;/span&gt;|
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;   &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;facebook_friends&lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="Support"&gt;Friend&lt;/span&gt;.&lt;span class="Entity"&gt;find_or_initialize_by_facebook_id&lt;/span&gt;(fb_friend.&lt;span class="Entity"&gt;id&lt;/span&gt;)
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;  &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt;  &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;friends&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;facebook_friends&lt;/span&gt;.&lt;span class="Entity"&gt;paginate&lt;/span&gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;page&lt;/span&gt; =&amp;gt; params[&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;page&lt;/span&gt;],&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;per_page&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;10&lt;/span&gt;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Il suffit alors d&amp;#8217;utiliser des text_field_tag  qui permettent d&amp;#8217;ajouter les tags et le tour est joué.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%=&lt;/span&gt; will_paginate &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;friends&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;params&lt;/span&gt; =&amp;gt; { &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;fb_sig_friends&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;nil&lt;/span&gt; } &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&amp;lt;br/&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;  &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%&lt;/span&gt; form_tag &lt;span class="Entity"&gt;friend_path&lt;/span&gt;(&lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;user&lt;/span&gt;), &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;method&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;put&lt;/span&gt; &lt;span class="Keyword"&gt;do &lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="String"&gt;  &amp;lt;% @friends.each do |friend| %&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;     &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;div &lt;span class="Keyword"&gt;class&lt;/span&gt;&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;friend_box&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;      &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;span &lt;span class="Keyword"&gt;class&lt;/span&gt;&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;left&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&amp;gt;&lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%=&lt;/span&gt; &lt;span class="Entity"&gt;fb_profile_pic&lt;/span&gt;(friend) &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&amp;lt;/span&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt;      &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;span&amp;gt;&lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%=&lt;/span&gt; &lt;span class="Entity"&gt;fb_name&lt;/span&gt;(friend) &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&amp;lt;/span&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt;      &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;span &lt;span class="Keyword"&gt;class&lt;/span&gt;&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;right&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt;       &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%=&lt;/span&gt; text_field_tag &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;friend[&lt;span class="String"&gt;&lt;span class="String"&gt;#{&lt;/span&gt;friend&lt;span class="String"&gt;&lt;span class="String"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;facebook_id&lt;/span&gt;&lt;/span&gt;&lt;span class="String"&gt;}&lt;/span&gt;&lt;/span&gt;][tag_list]&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
&lt;span class="line-numbers"&gt;   9 &lt;/span&gt;       friend.&lt;span class="Entity"&gt;tag_list&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;size&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;40&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;style&lt;/span&gt; =&amp;gt; &lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;font-size:1.7em&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&amp;lt;/span&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  10 &lt;/span&gt;      &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;div &lt;span class="Keyword"&gt;class&lt;/span&gt;&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;clear&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;div&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  11 &lt;/span&gt;     &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;div&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  12 &lt;/span&gt;    &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%&lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  13 &lt;/span&gt; &lt;span class="String"&gt; &amp;lt;%= submit_tag &amp;quot;Save all&amp;quot; %&lt;span class="String"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  14 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="Keyword"&gt;%&lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Remarquez que l&amp;#8217;on utilise de nouveau le helper fb_profile_pic pour afficher l&amp;#8217;image du profil d&amp;#8217;un de vos amis, mais aussi fb_name qui a pour but d&amp;#8217;afficher un lien ayant pour texte le nom de votre ami.&lt;/p&gt;
&lt;p&gt;Il ne nous reste plus qu&amp;#8217;a mettre à jour les listes de tags qui ont été modifiées. A la particularité près que si votre ami n&amp;#8217;est pas encore dans la db, il faut l&amp;#8217;y insérer.&lt;/p&gt;
&lt;p&gt;L&amp;#8217;action update fait donc appel à une méthode que nous appellerons update_or_create.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;update&lt;/span&gt;    
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;  params[&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;friend&lt;/span&gt;].&lt;span class="Entity"&gt;each&lt;/span&gt; &lt;span class="Keyword"&gt;do &lt;/span&gt;|&lt;span class="Variable"&gt;friend&lt;/span&gt;|
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;   &lt;span class="Keyword"&gt;unless&lt;/span&gt; friend[&lt;span class="Constant"&gt;1&lt;/span&gt;][&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;tag_list&lt;/span&gt;].&lt;span class="Entity"&gt;blank?&lt;/span&gt;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;    &lt;span class="Support"&gt;Friend&lt;/span&gt;.&lt;span class="Entity"&gt;update_or_create&lt;/span&gt;(friend[&lt;span class="Constant"&gt;0&lt;/span&gt;].&lt;span class="Entity"&gt;to_i&lt;/span&gt;, friend[&lt;span class="Constant"&gt;1&lt;/span&gt;][&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;tag_list&lt;/span&gt;])
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;   &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt;  &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt;  &lt;span class="Support"&gt;redirect_to&lt;/span&gt; friends_path
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Méthode que l&amp;#8217;on retrouve dans le modèle &amp;#8216;Friend&amp;#8217;.&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;self.update_or_create&lt;/span&gt;(&lt;span class="Variable"&gt;facebook_id&lt;span class="Variable"&gt;,&lt;/span&gt; tag_list&lt;/span&gt;)
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;  friend &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;Friend&lt;/span&gt;.&lt;span class="Entity"&gt;find_or_initialize_by_facebook_id&lt;/span&gt;(facebook_id)
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;  friend.&lt;span class="Entity"&gt;tag_list&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; tag_list
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;  friend.&lt;span class="Entity"&gt;save&lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Voilà, nous avons maintenant un système qui nous permet de tagger nos amis et d&amp;#8217;afficher notre propre tag cloud. Dans le prochain article, nous replongerons dans facebooker avec l&amp;#8217;affichage d&amp;#8217;informations dans la profile box, et dans le dernier épisode nous jouerons avec la publication de feeds.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://frailers.net/uploads/fb_2x1.png" alt="" /&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/FrailersArticles/~4/bna1t9Js_6c" height="1" width="1"/&gt;</description>
      <pubDate>Mon, 02 Feb 2009 00:00:00 +0000</pubDate>
      <link>http://feedproxy.google.com/~r/FrailersArticles/~3/bna1t9Js_6c/54-une-application-pas-a-pas-my-tag-cloud-e-pisode-2</link>
      <guid isPermaLink="false">http://www.frailers.net/articles/54-une-application-pas-a-pas-my-tag-cloud-e-pisode-2</guid>
    <feedburner:origLink>http://www.frailers.net/articles/54-une-application-pas-a-pas-my-tag-cloud-e-pisode-2</feedburner:origLink></item>
  </channel>
</rss>
