Creer un file upload avec ActiveAdmin et rails

Bonjour à tous,

Comme beaucoup de développeurs, je me lance dans Ruby On Rails et ceci implique les grosses galère du départ. J’ai donc suivi les tutoriels officiels puis je me suis lancé dans la partie administration. Utilisant Rails 3, j’ai choisi de me pencher sur la solution ActiveAdmin qui me paraissait belle, complète et moderne, tout ce que j’avais besoin…

Tout fonctionné à merveille avec la doc officielle jusqu’au moment où j’ai voulu me lancer dans l’upload de fichier à partir du backoffice… Après de multiples lectures, messages et discussions, je suis arrivé à faire un upload de fichier propre. Je vais donc partager avec vous le bilan de cette galère…

Tout d’abord en Rails, pour l’upload de fichier, il existe plusieurs solutions, j’ai choisi pour ma part Paperclip qui se couple très bien avec Formtastic utilisé par Activeadmin.

Nous allons considéré que vous avez déjà installé Activeadmin, Paperclip et ImageMagick avec sucés et que ceux-ci fonctionnent correctement.C’est à dire que vous pouvez Ajouter, éditer, supprimer et visualiser les données de votre modèle dans votre base de donnée.

Nous allons prendre pour exemple mon modèle Event qui possède un champ “map”qui va être notre image uploadée :

class Event < ActiveRecord::Base

  has_attached_file :map, :styles => { :medium => "238x238>",
                                       :thumb => "100x100>"
                                     }
end

Comme nous indique la doc de Paperclip, nous avons rajouté dans notre modèle l’attribut has_attached_file. Dans notre cas, nous avons défini que l’image médium fait 238px et le thumb 100px

Une fois ceci effectuée, il faut faire le script de migration pour notre modèle. Pour cela, on ouvre notre Shell et on tape la commande suivante :

rails generate migration AddMapToEvents

Ceci vous retourne une ligne du style :

invoke  active_record
create    db/migrate/20110810140028_add_map_to_events.rb

Un fichier 20110810140028_add_map_to_events.rb a donc été créé dans le répertoire db/migrate de votre projet.

Ouvrez donc ce fichier, vous allez avoir quelque chose comme ceci :

class AddImageToEvents < ActiveRecord::Migration
  def self.up
  end

  def self.down
  end
end

Il faut donc le faire ressembler à ceci, selon la doc Paperclip :

class AddMapToEvents < ActiveRecord::Migration
   def self.up
    add_column :events, :map_file_name,    :string
    add_column :events, :map_content_type, :string
    add_column :events, :map_file_size,    :integer
    add_column :events, :map_updated_at,   :datetime
  end

  def self.down
    remove_column :events, :map_file_name
    remove_column :events, :map_content_type
    remove_column :events, :map_file_size
    remove_column :events, :map_updated_at
  end
end

Notez bien que :events est le nom de notre modèle, il est à adapté selon votre cas, de même pour le nom des champs, le :image est à adapter selon le nom du champ choisi pour l’image.

Il ne vous reste plus qu’à lancer la migration :

rake db:migrate VERSION=20110810140028

Notez de même que le numéro de version est celui qui a été généré au début de votre fichier de migration. Vous devrez alors obtenir un log similaire à celui-ci dans votre console :

==  AddMapToEvents: migrating ===============================================
-- add_column(:events, :map_file_name, :string)
   -> 1.0057s
-- add_column(:events, :map_content_type, :string)
   -> 0.0972s
-- add_column(:events, :map_file_size, :integer)
   -> 0.0209s
-- add_column(:events, :map_updated_at, :datetime)
   -> 0.0526s
==  AddMapToEvents: migrated (1.1767s) ======================================

Une fois ceci fait, il nous reste plus qu’à configurer l’upload de fichier, pour cela, nous allons éditer le fichier app/admin/.rb généré par ActiveAdmin pour la partie admin.

Au départ, il doit ressembler à ceci :

ActiveAdmin.register Event do

end

Nous allons donc modifier le formulaire d’édition et de création de notre objet :

ActiveAdmin.register Event do
  form :html => { :enctype => "multipart/form-data" } do |f|
      f.inputs "Details" do
        f.input :continent
        f.input :event_type
        f.input :name
        f.input :title
        f.input :content
        f.input :date_start, :as => :date
        f.input :date_end, :as => :date
        f.input :place
        f.input :map, :as => :file, :hint => f.template.image_tag(f.object.map.url(:thumb))
        f.input :userfull_info
        f.input :price
        f.input :phone, :as => :phone
        f.input :website, :as => :url
      end
      f.buttons
    end
end

Nous devons reprendre tous les champs de notre modèle pour pouvoir saisir toutes les données. La ligne qui permet de créer l’input avec la prévisualisation de l’image actuelle est bien évidemment celle-ci :

f.input :map, :as => :file, :hint => f.template.image_tag(f.object.map.url(:thumb))

Ainsi vous obtiendrez quelque chose comme ceci :

Lors de la sauvegarde du modèle, les fichiers iront par défaut dans :

:rails_root/public/system/:attachment/:id/:style/:filename

Lisez la doc de paperclip si vous voulez changer ce paramètre.

Pour accéder à l’image, il suffit d’appeler les méthodes suivantes :

  event.map.url()  (Image à la taille d'origine)
  event.map.url(:thumb) (Image à la taille Thumb)

Et voila, vous avez créé votre upload, j’espère vous avoir aider.
à Bientôt.