Rails

Rails 3

Fin 2008, les développeurs de Merb et Rails ont annoncé qu'ils allaient joindre leurs efforts pour sortir un Rails 3 qui combinerait les avantages de Rails et ceux de Merb. Depuis, nous avons porté beaucoup d'espoirs qui s'annonce très prometteuse, mais qui est également une source de frustration que cette version ne soit pas déjà disponible. Enfin, la semaine dernière, Rails 3 est officiellement sorti en beta (avec les release notes détaillées).

Pour le moment, Rails 3 reste encore le domaine des développeurs aventureux, ceux qui n'ont pas peur de rencontrer des bugs. Par exemple, de nombreux plugins ne sont pas encore compatibles avec Rails 3 (railsplugins.org est une bonne source pour connaître la liste de ceux qui le sont).

Si vous faites parti de cette catégorie, alors deux choix s'offrent à vous. Vous pouvez commencer une nouvelle application avec Rails 3. Le 200ème railscast est un très point de départ pour ça. L'autre choix, plus ambitieux, est de porter une application Rails existante vers Rails 3. Je vous conseille alors de vous faire aider par le plugin rails_upgrade en vous laissant guider par les explications du peepcode Rails 3 Upgrade.

Dans tous les cas, il est intéressant de commencer à se plonger dans les nouveautés de Rails 3. Les articles sur le sujet sont dispersés sur de nombreux blogs, mais des listes permettent de s'y retrouver. Celle de Ruby Inside me semble être la plus complète pour le moment.

Je vous encourage également à participer à l'initiative Give Back to Open Source. C'est très simple : prenez votre plus gros projet Rails, regardez les gems et plugins que vous utilisez, et pour chacun d'eux, contribuez en retour : donnez de l'argent, corrigez un bug, écrivez de la documentation, ou simplement, remerciez son auteur. L'important est de donner en retour.

Mise-à-jour : le Rails 3 Upgrade Handbook est un guide PDF qui vous guide dans votre migration vers Rails 3. Il coûte 12$, mais il les vaut. Vous y trouverez toutes les informations utiles, y compris certaines qui sont très difficiles à trouver ailleurs.

Madison Street cable car derailed in snow, 1929

Quand on développe une application web, la sécurité est toujours une problématique à prendre au sérieux. Négligez-la et vous pouvez être sûr qu'un jour ou l'autre, un petit malin se fera le plaisir de vous montrer vos failles. Une attaque simple mais très répandue est l'injection XSS (ou Cross-site scripting). Le principe est d'envoyer du code HTML dans un site web pour qu'il soit interprété par le navigateur d'un autre utilisateur. Par exemple, on peut poster la ligne suivante sur un forum pour essayer d'ennuyer les autres utilisateurs :

  1. <script>alert('All your base are belong to us!');</script>

Cette attaque n'est toutefois pas à prendre à la légère. Elle permet par exemple de voler les cookies d'un utilisateur et donc sa session, ou encore de lui faire des actions indésirables sur le site attaqué.

Il est donc nécessaire de se protéger de cette attaque et, rassurez-vous, Ruby on Rails a tout ce qu'il faut pour faire ça simplement. Jusqu'à maintenant, la méthode pour faire ça consiste à indiquer à Rails les chaînes de caractères qui contiennent du contenu manipulé par l'utilisateur et qui pourraient donc être dangereuses. Dans le cas le plus fréquent, une telle chaîne ne doit pas du tout contenir de balise HTML, et on peut alors utiliser le helper h qui transforme les caractères dangereux en entités HTML. Exemple :

  1. Hello <%=h @name %>

Dans le cas contraire où l'utilisateur a le droit d'entrer du texte HTMl enrichi avec des balises HTML, il convient de limiter les balises et attributs autorisés. Le helper sanitize permet de faire ça :

  1. Biographie : <%=sanitize @bio %>

Cela fonctionne très bien, mais il y a toujours le risque d'oublier un h ou un sanitize, ce qui laisserait une porte pour un attaquant. C'est pourquoi il existe des plugins Rails qui favorisent l'approche inverse, à savoir indiquer quelles sont les chaînes de caractères qui sont sûres et d'échapper tout le reste. C'est également l'approche que Rails 3 offrira lors de sa sortie en février 2010.

Dans Rails 3, les chaînes de caractères auront un attribut html_safe, qui indiquera si la chaîne est sûre. Par défaut, l'attribut vaudra false, et cette chaîne sera échappée lors du rendering.

Bien entendu, votre page HTML contient des balises et il est donc nécessaire de pouvoir construire ces balises sans qu'elles soient échappées. Tout d'abord, cette protection ne vise que des contenus venant de l'utilisateur, il est donc inutile d'échapper le contenu "en dur" des vues : seul ce qui se trouvent entre <%= et %> est concerné. Dans l'exemple suivant, le nom apparaîtra bien en gras :

  1. Hello <strong><%= @name %></strong>

Une autre source de contenus légitimes est la génération de code HTML par les helpers de Rails. Heureusement, ces helpers génèrent des chaînes de caractères marquées comme sûres après avoir échappé leurs entrées. Exemple :

  1. <%= tag(:p, "<script>alert('hello');</script>") %>  # => "<p>&lt;script&gt;alert('hello');&lt;script&gt;</p>"

Enfin, il vous reste la possibilité de marquer vous-mêmes les chaînes comme étant sûres. Pour cela, vous pouvez utilisez raw quand vous êtes dans une vue, ou appeler html_safe sur la chaîne si vous êtes dans un helper. Exemple :

  1. <%= raw @site_title %>
  1. def evil_js
  2.   "<script>alert('This site is evil. Mwahahah!');</script>".html_safe
  3. end

Si vous souhaitez en savoir plus, je vous conseille la lecture de SafeBuffers and Rails 3.0 de Yehuda Katz.

AF83 sort une gem que nous utilisons dans nos projets de sites communautaires. Has_media est une bibliothèque pour ActiveRecord, pour gérer les médias dans les modèles avec une simple déclaration :


class User < ActiveRecord::Base
has_one_medium :avatar, :only => :image
end

On ajoute avec cette ligne un "champ" image pour un utilisateur. Il ne reste plus qu'à ajouter un file_field :avatar dans votre formulaire pour que l'image soit associée à l'utilisateur. L'upload est géré par carrierwave. Les méthodes de classe has_one_medium ou has_many_media ajoutent automatiquement les getter et setter pour l'avatar d'un utilisateur.

Les validations sont faites automatiquement selon le type de média défini par l'option :only => :image.

Cas d'utilisation :

# Créer la migration
./script/generate has_media


# Ajouter la gem dans config/environment.rb
config.gem 'has_media'


# Changer les options de has_media dans config/initializers/has_media.rb
HasMedia.directory_path = "media" # Placer les médias dans Rails.root, 'public', 'media'
HasMedia.directory_uri = "/media"
HasMedia.errors_messages = {:type_error => I18n.t('has_media.errors.type_error')}


# Pour le modèle voir plus haut et sur le formulaire
<p>
<%= f.label :avatar %>
<%= f.file_field :avatar %>
</p>
</code>

HasMedia ne gère pas les thumbnails (AF83 utilise une autre application pour cela), mais c'est facilement faisable avec carrierwave.

Plus d'informations : http://github.com/AF83/has_media
Installation : gem install has_media

Pour un de nos projets web, nous allons changer la charte graphique. Le projet en question est codé avec le framework Ruby on Rails, ce qui implique de passer sur chacun des fichiers dans app/views pour vérifier le markup, de modifier les feuilles de styles et de s'assurer que le tout est cohérent sur toutes les pages du site. Comme le site est conséquent, cela risque de ne pas être tout simple. Aussi, ai-je écrit deux scripts pour nous aider.

Le premier script sert à extraire toutes les URL appelées depuis les fichiers de logs Rails :

Le second script permet d'ajouter des commentaires HTML au début et à la fin de chaque fichier dans app/views pour l'identifier depuis le code source de la page HTML générée :

Je pense que cela va nous aider dans notre approche, mais je me demande s'il n'existe pas d'autres trucs pour cela. Avez-vous déjà été confronté à cela ? Si oui, comment vous en êtes vous sorti ?

Ruby gems

af83 utilise Ruby on Rails pour certains de ses projets. De projet en projet, nous prenons des habitudes comme réutiliser certains gems. Je souhaite vous faire partager la liste de ces gems. Cette liste n'a rien d'extra-ordinaire. Ce sont principalement des gems très classiques mais qui méritent d'être mis en avant.

  1. Will Paginate est un plugin Rails pour gérer la pagination. Il est depuis longtemps la référence dans ce domaine et il continue de s'améliorer sans pour autant perdre sa simplicité. Indispensable. http://wiki.github.com/mislav/will_paginate/
  2. Authlogic est une solution complète pour l'authentification et la gestion des utilisateurs. C'est toujours assez délicat de gérer les mots de passe des utilisateurs, les activations de compte, les mots de passe perdus, mais ce gem apporte une manière propre de le faire en gardant une haute exigence de sécurité. http://rdoc.info/projects/binarylogic/authlogic
  3. Acts as state machine offre une solution très appréciable pour gérer des états sur les modèles, et les transitions entre ces états. Rails 3 offrira un module State Machine fortement inspiré de acts as state machine. En attendant, acts as state machine reste indispensable. http://github.com/rubyist/aasm
  4. Friendly_id est un gem bien pratique pour avoir des URL très parlantes. Il permet de créer des slugs et permalinks très facilement en vous évitant les surprises : historique de slugs, mots réservés et support d'unicode sont de la partie. http://norman.github.com/friendly_id/
  5. Thinking Sphinx est une bibliothèque pour connecter ActiveRecord au service de recherche fulltext Sphinx. Son DSL offre de nombreuses possibilités pour faire des recherches avancées sans difficultés. http://freelancing-god.github.com/ts/fr/
  6. HTML Entities est un moyen très simple d'encoder et décoder les entités HTML. http://htmlentities.rubyforge.org/
  7. FasterCSV est une bibliothèque pour manipuler des données au format CSV. Nous l'utilisons sur quasiment tous nos projets pour fournir des exports CSV des données présentes sur le site web. http://fastercsv.rubyforge.org/
  8. rspec est un framework incontournable pour spécifier le comportement de nos applications et nous assurer qu'il n'y ait pas de regressions. http://rspec.info/
  9. factory_girls permet de remplacer les fixtures de Rails, et d'avoir des données pour les specs qui soient faciles à maintenir au fur et à mesure des évolutions. http://github.com/thoughtbot/factory_girl
  10. Pour finir, af83 utilise également has_media, une bibliothèque maison pour la gestion des médias. http://github.com/AF83/has_media

Logo
Chaque semaine, je publie une liste de liens vers des billets de blog, des articles et des annonces qui me semblent intéressants et en rapport avec l’activité d’AF83. N’hésitez pas à proposez vos liens. Voici la sélection de cette semaine :
OS & Navigateurs

    Logo
    Chaque semaine, je publie une liste de liens vers des billets de blog, des articles et des annonces qui me semblent intéressants et en rapport avec l’activité d’AF83. N’hésitez pas à proposez vos liens. Voici la sélection de cette semaine :
    Campagne Microsoft

    Logo
    Chaque semaine, je publie une liste de liens vers des billets de blog, des articles et des annonces qui me semblent intéressants et en rapport avec l’activité d’AF83. N’hésitez pas à proposez vos liens. Voici la sélection de ces dernières semaines :
    Conditions d'utilisation

      Après le RailsCampParis, hier a eu lieu le Rails MashPit Paris. Ce fût l'occasion de mettre en pratique les techniques découvertes la veille.

      Une quinzaine de courageux sont venus, et chose assez rare pour un MashPit, quasiment tous savaient coder. La première épreuve (après le petit déjeuner) fût le choix des projets. Après deux tours de votes, trois équipes se sont lancés dans une journée de développement intensif.

      Un petit post depuis le RailsCamp Paris à la Cantine :