Utiliser attachment_fu avec la sauvegarde en DB

Publié le 27/03/08 par Nicolas Jacobeus | 2 commentaires

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.

Références

2 Commentaires

Commentaire posté par aurels le 23/04/08

<%= image_tag avatars_path(@avatar) %>

Il y a un s en trop à “avatars_path”, non?

Commentaire posté par Nicolas Jacobeus le 24/04/08

Of course :) J’ai corrigé.

Ajouter un commentaire

Vous devez être identifié pour poster un commentaire. Identifiez-vous, ou inscrivez-vous si ce n'est déjà fait.