Le kit du bon développeur Rails, quelques gems à connaitre, partie 2

Publié le 1 février 2012 par Alexandre Salaun | outils

Cet article est publié sous licence CC BY-NC-SA

Il est toujours bon pour un développeur de connaître quelques gems qui vont lui permettre de développer les fonctionnalités de base d’un site ou d’une application. Cet article est la suite du kit du bon développeur rails publié il y a quelques semaines sur le blog. Nous avions pu explorer des sujets tels que le déploiement, l’authentification, les formulaires de recherche mais d’autres thèmes restent à voir, nous allons en explorer une autre partie dans cet article.

Internationalisation

Un site multi-langue entraîne forcément l’utilisation de I18n qui est présent dans Rails. En effet, afin de pouvoir traduire vos contenus il est nécessaire de n’avoir aucun texte en dur dans votre code. Cependant, il est parfois nécessaire de ne traduire qu’une seule partie de la page et dans ce cas il existe des gems pour vous faciliter la tâche.

I18n

I18n est donc utilisé dans Rails pour traduire tous vos textes. Vous pouvez par ailleurs obtenir plus d’informations sur la page I18n sur le site de RubyOnRails. Pour cela, Rails se base sur la langue définie pour I18n. Il vous est possible de la définir via la ligne de commande suivante :

I18n.locale = :fr # pour définir français comme langue

Il est également possible de définir une langue par défaut pour votre application dans le fichier config/environment.rb ou config/application.rb selon la version de Rails.

config.i18n.default_locale = :fr

Pour ce qui est de la traduction en elle même il vous suffit de créer des fichier (.yml ou .rb) par langues dans le répertoire config/locales de votre application. Il est également possible de prendre en compte d’autres fichiers en spécifiant où les trouver dans le fichier config/application.rb via la ligne suivante :

config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')]

Il devient ensuite très simple d’avoir une application traduite dans plusieurs langues. On peut via le controller par exemple spécifier la langue.

class ApplicationController < ActionController::Base
  before_filter :set_locale

  def set_locale
    I18n.locale = params[:locale]
  end
end

Afin d’utiliser vos traductions, il faut utiliser la méthode translate de I18n qui retourne le texte dans la langue spécifiée. Par exemple, dans une vue, si vous avez défini la langue à français vous pouvez reprendre l’exemple qui suit :

  <%= t("views.home_title") %>

Ce code vous affiche le texte défini, en français, pour la clé home_title dans votre fichier config/locales/fr.yml:

fr:
  views:
    home_title: "Page d'accueil"

Ce fichier vous permet également de définir les libellés des attributs des models ou les messages d’erreurs.

fr:
  activerecord:
    attributes:
      category:
        title: "Titre de la catégorie"

Il est parfois nécessaire de ne traduire qu’une seule partie de la page ou du contenu saisi en base et I18n n’offre pas ces possibilités, il existe donc des gems capables de le faire.

Globalize3

Globalize3 est une gem permettant de traduire du contenu dynamique (attributs d’un modèle). Elle succède à la gem Globalize. Il est possible d’obtenir des informations sur cette gem sur la page Github.

Pour installer cette gem, il vous suffit de l’ajouter à votre Gemfile puis de lancer la commande bundle install :

gem 'globalize3'

Ensuite, il faut spécifier dans le model les champs qui seront traduits :

class Category < ActiveRecord::Base
  translates :title, :description
end

Une migration est alors nécessaire afin de créer la table où seront stockées les traductions :

class CreateCategories < ActiveRecord::Migration
  def self.up
    create_table :categories do |t|
      t.timestamps
    end
    Category.create_translation_table! :title => :string, :description => :text
  end

  def self.down
    drop_table :categories
    Category.drop_translation_table!
  end
end

Attention, pour les projets utilisant Rails 3.1 ou plus, il ne faut pas utiliser la méthode change mais continuer à utiliser up et down.

Pour une utilisation “basique” de votre application, c’est-à-dire, en utilisant une seule langue par page, vous n’aurez rien à faire dans vos vues. En effet, les champs seront affichés dans la langue du site (I18n.locale) et vous allez donc avoir les contenus stockés en base affichés suivant la locale, ce qui est le but pour des sites multi-langues où l’on veut juste avoir le contenu traduit suivant la langue choisie par l’utilisateur.

Cependant, si vous souhaitez utiliser plusieurs langues sur une même page, ce qui est demandé dans certains cas, il vous faut utiliser les blocs définis par Globalize3. Dans les vues de votre projet Rails, ces derniers servent à traduire une partie de votre contenu dans une langue choisie auparavant :

<%
  my_locale = :fr
  # my_locale peut également être un helper ou une variable définie dans le controller.
%>

<% Globalize.with_locale(my_locale) do %>
  <% render :partial => "my_partial_with_locale" %>
<% end %>

On peut donc avoir le contenu des pages en anglais et uniquement la partie qui se trouve incluse dans le bloc Globalize traduite en français par exemple. Il est donc très simple d’utiliser plusieurs langues dans une même vue.

Gestion de fichiers

La gestion de fichiers est un autre point important lors de la création d’une application ou d’un site web. On peut avoir des images à stocker si on permet à l’utilisateur de les uploader par exemple. Différentes gems existent pour vous aider dans cette démarche.

Paperclip

Paperclip est une gem qui permet de gérer des fichiers suite à l’upload par un utilisateur. Il est possible d’obtenir des informations sur cette gem sur la page Github de Paperclip. Afin de pouvoir utiliser cette dernière il est nécessaire d’avoir installé imagemagick. Ensuite, pour installer Paperclip, il vvous suffit de l’ajouter dans votre Gemfile et lancer un bundle install :

gem "paperclip"

Dans le model, il faut spécifier le champ qui concerne le fichier à stocker :

class Category < ActiveRecord::Base
  has_attached_file :logo
end

Il est possible, si le fichier en question est une image de créer différentes versions du fichier, par exemple, stocker l’image dans différentes tailles :

class Category < ActiveRecord::Base
  has_attached_file :logo, :styles => { :large => "600x300>", :medium => "200x100", :thumb => "100x50>" }
  # dans ce cas l'image sera stockée quatre fois : l'image de base telle qu'elle est uploadée
  # ainsi que les trois formats définis ci-dessus
end

Ensuite, la migration vous permettra de créer les différents champs utilisés par Paperclip :

class AddLogoToCategory < ActiveRecord::Migration
  def self.up
    change_table :categories do |t|
      t.has_attached_file :logo
    end
  end

  def self.down
    drop_attached_file :categories, :logo
  end
end

Après avoir lancer un rake db:migrate vos champs sont donc en base et vous pouvez donc uploader un logo pour vos catégories dans votre formulaire de création ou d’édition :

<%= form_for @category, :html => { :multipart => true } do |f| %>
  <%= form.label :title %>
  <%= form.text_field :title %>

  <%= form.label :logo %>
  <%= form.file_field :logo %>
<% end %>

Par la suite, vous pourrez afficher les images en question dans les formats souhaités :

# pour afficher l'image telle qu'elle a été uploadée
<%= image_tag @category.logo.url %>

# pour afficher l'image en format 'medium'
<%= image_tag @category.logo.url(:medium) %>

Pour supprimer un fichier uploader, il suffit de mettre la valeur du champ en question à nil :

@category.logo = nil

Il est possible de faire fonctionner Paperclip avec le service de stockage d’Amazon S3 via une autre gem, aws-sdk.

D’autres exemples d’utilisation de Paperclip sont disponibles dans un Railscast de Ryan Bates.

Encore une fois Paperclip n’est pas la seule gem disponible afin de vous aider dans la gestion des fichiers.

Dragonfly

Tout comme Paperclip, Dragonfly est une gem permettant de gérer les fichiers dans votre application Rails. Des informations sont disponibles sur la page Github de Dragonfly.

Afin d’installer Dragonfly, il vous faut l’ajouter à votre Gemfile :

gem 'rack-cache', :require => 'rack/cache'
gem 'dragonfly', '~>0.9.10'

La gem rack-cache est nécessaire au fonctionnement de Dragonfly.

Ensuite, ajoutez la ligne suivante dans le fichier config/initializers/dragonfly.rb (qu’il vous faudra créer auparavant si il n’existe pas) :

require 'dragonfly/rails/images'

Vous pouvez maintenant créer la migration qui permettra de stocker le fichier :

class AddLogoToCategory < ActiveRecord::Migration
  def self.up
    add_column :categories, :logo_uid, :string
  end

  def self.down
    remove_column :categories, :logo_uid
  end
end

Puis, dans le model en question (dans notre cas Category), vous devez ajouter un image_accessor :

class Category < ActiveRecord::Base
  image_accessor :logo
end

Il vous est désormais possible d’uploader les logos de vos catégories via un formulaire, dans l’une des vues de votre projet :

<%= form_for @category, :html => { :multipart => true } do |f| %>
  <%= form.label :title %>
  <%= form.text_field :title %>

  <%= form.label :logo %>
  <%= form.file_field :logo %>
<% end %>

Afin de supprimer un fichier, vous pouvez utiliser une checkbox dans votre formulaire :

<%= f.check_box :remove_logo %>

Si cette dernière a pour valeur true alors le fichier sera supprimé.

Pour ce qui est de l’affichage d’une image, contrairement à Paperclip, on ne définit pas les formats d’une image lors de la sauvegarde mais lors de l’affichage.

# pour afficher l'image telle qu'elle a été uploadée
<%= image_tag @category.logo.url %>

# pour afficher l'image dans un autre format
<%= image_tag @category.logo.thumb("200x100").url %>

Dragonfly et Paperclip sont donc deux gems pour la gestion de fichier. Chacun peut choisir celui avec lequel il a le plus d’affinités et qu’il trouve le mieux adapté à ses besoins.

Conclusion

Ces deux articles offrent un bon tour d’horizon des solutions actuelles pour les besoins récurrents. Dans la dernière partie nous évoquerons les tests et les outils annexes.

Connaître ces gems peut s’avérer très pratique, c’est un gain de temps dans la plupart des cas, cela évite de repartir de zéro lors du développement de certaines fonctionnalités.

Au delà des gems présentées, il existe des gems pour presque toutes les fonctionnalités, il vous est donc facile de trouver celle qui est la plus adaptée pour vous.

De plus, la plupart des gems sont disponibles sur Github et il est donc très simple de remonter un bug ou de poser une question. En outre, ces gems sont utilisées par de très nombreux développeurs, on peut donc considérer qu’elles sont testées et approuvées par la communauté.

Il n’y a donc aucune raison pour ne pas utiliser les gems existantes plutôt que de développer soi-même des fonctionnalités de base.

L’équipe Synbioz.

Libres d’être ensemble.