attachment_fu est le plugin de prédilection pour la gestion des fichiers téléchargés sur une application Rails. Pour stocker ces fichiers, le plugin propose 3 solutions, et nous allons ici étudier la moins documentée: le stockage en base de données.
Introduction
attachment_fu, développé par le célèbre Rick Olson (techno weenie) est un plugin qui vous permet de faciliter la gestion des fichiers téléchargés vers votre application via les formulaires. Il permet ainsi à chaque utilisateur, par exemple, de rajouter sa photo ou son logo sur sa page profil.
Pour ce faire, attachment_fu propose 3 méthodes de stockage:
- le système de fichiers: les fichiers sont simplement déposés dans un dossier de votre serveur, idéalement public afin qu’ils puissent ensuite être affichés sur votre site;
- Amazon S3: la plateforme de stockage distribuée (et payante) proposée par Amazon;
- la base de données: déjà utilisée pour vos autres données.
Le fichier README du plugin documente (relativement) bien les 2 premières solutions, mais ne donne pas beaucoup d’indications sur la dernière. Les avantages proposés par cette solution sont pourtant évidents:
- elle permet la centralisation de toutes vos données au même endroit ce qui est bien pratique pour la stratégie de backup;
- par rapport à la solution “système de fichiers”, elle évite d’avoir à faire des manipulations supplémentaires si vous déployez avec capistrano (vu que votre dossier d’application rails change à chaque mise à jour);
- elle est évidemment gratuite, contrairement à Amazon S3.
L’inconvénient majeur de la solution, à savoir sa lenteur, peut être circonvenu en utilisant un système de caching des fichiers (mais cela sort du cadre de cet article).
Installation du plugin et configuration
Vous aurez tout d’abord besoin de l’une des 3 librairies graphiques suivantes, au choix: RMagick, ImageScience ou minimagick. Ensuite, vous pouvez installer le plugin proprement dit, à partir de la racine de votre application:
script/plugin install http://svn.techno-weenie.net/projects/plugins/attachment_fu/
Nous choisissons de nommer “Avatar” le modèle qui stockera les fichiers téléchargés. Nous créons donc la migration suivante:
class CreateAvatars < ActiveRecord::Migration
def self.up
create_table :avatars do |t|
t.column :filename, :string
t.column :type, :string
t.column :content_type, :string
t.column :size, :integer
t.column :width, :integer
t.column :height, :integer
t.column :parent_id, :integer
t.column :thumbnail, :string
t.column :created_at, :datetime
t.column :db_file_id, :integer
end
create_table :db_files do |t|
end
execute 'ALTER TABLE db_files ADD COLUMN data LONGBLOB'
end
def self.down
drop_table :avatars
drop_table :db_files
end
end
Vous pouvez constater la présence dans la migration d’une table additionnelle nommée “db_files”; elle est imposée par attachment_fu si l’on désire un stockage via base de données. A noter que nous y utilisons un champ de type blob et non binary pour éviter la limite des 65536 caractères imposée par MySQL, ce qui nécessite malheureusement d’effectuer l’ajout de la colonne manuellement en SQL.
Le modèle proprement dit est comme suit:
class Avatar < ActiveRecord::Base
has_attachment :storage => :db_file,
:content_type => :image,
:max_size => 1.megabytes,
:thumbnails => { :thumb => "100×100>" }
validates_as_attachment
end
Enfin, pour afficher nos avatars dans l’application, nous utilisons la méthode show du contrôleur AvatarsController:
class AvatarsController < ApplicationController
def show
@avatar = Avatar.find(params[:id])
send_data(@avatar.current_data,
:type => @avatar.content_type,
:filename => @avatar.filename,
:disposition => 'inline')
end
end
Pour afficher un avatar dans vos vues, rien de plus simple:
<%= image_tag avatar_path(@avatar) %>
Bien entendu, il faudrait sans doute également ajouter les méthode create, destroy et compagnie à ce contrôleur ainsi qu’un formulaire d’upload pour que les utilisateurs puissent ajouter/supprimer leurs avatars, mais le fonctionnement n’est pas différent pour le stockage en DB par rapport aux autres techniques, et cela sort donc du cadre de cet article; reportez-vous par example à l’article de Mike Clark pour plus d’info à ce sujet.
2 Commentaires
<%= image_tag avatars_path(@avatar) %>
Il y a un s en trop à “avatars_path”, non?
Of course :) J’ai corrigé.