Développer une galerie web en rails, avec slideshow, resize des images, vignettes et RSS en 20 minutes, en mangeant un plat de sushis
On n’est jamais mieux servi que par soi-même, dit le proverbe. Aussi, afin de remplacer Photostack vraiment trop limité et brouillon ai-je décidé de développer ma propre galerie d’images, mais vite (et bien), car je n’ai pas vraiment que ça à faire.
En termes de fonctionnalités, je compte partir sur des bases simples, que j’améliorerai au fur et à mesure.
- De multiples galeries.
- La prise en charge du redimensionnement des images.
- La création automatique de vignettes.
- Un slideshow qui permette aux visiteurs de faire défiler l’ensemble d’une galerie sans aucun effort.
- Un flux XML pour du RSS ou de l’atom.
Pour le côté technique, j’ai dit vite – le temps d’avaler un plat de sushi – et propre. Cela exclue donc forcément PHP, au profit de Ruby on Rails. Maintenant, on fait comme dans la chanson, on monte sur les tables, on lève les bras bien haut, allez c’est parti !
Création de l’application
Nous commençons par créer une nouvelle application Rails.
powerbook:~/Documents/code$ rails imagiliapowerbook:~/Documents/code$ cd imagiliaEt pour fêter ça, j’attrape un premier sushi à l’oursin. Miam !
Ajout des galeries
Nous créons maintenant tout ce dont nous avons besoin ajouter, parcourir, modifier et supprimer des galeries.
powerbook:~/Documents/code$ script/generate scaffold_resource gallery name:string description:text status:boolean position:int created_at:date updated_at:dateNotre galerie possédera les attributs suivants :
- Un titre.
- Une description.
- Un état (en ligne / hors ligne).
- Une position.
Nous avons utilisé les fonctionnalités de génération automatique de Rails. Elles nous permettent maintenant de disposer de :
- Le formulaire de création et de modification de notre galerie /galleries/new.
- L’affichage HTML (sommaire) de notre galerie: /galleries/1.
- Un flux XML, for fun and profit : /galleries/1.xml
Aurais-je omis de dire que l’application est RESTful ? Oui ? Comme c’est dommage. Je vais donc noyer mon chagrin dans un second sushi, au saumon cette fois.
Ajout des images
Il nous manque le plus important : l’ajout et la visualisation des images. Comme précédemment, nous allons laisser Rails travailler pour nous et générer tout ce dont nous avons besoin, ou presque.
powerbook:~/Documents/code$ script/generate scaffold_resource picture gallery_id:int content_type:string filename:string thumbnail:string size:integer width:integer height:integer position:int title:string description:text status:boolean created_at:date updated_at:dateNos images auront pour attribut :
- Une galerie parente. Nous créerons le menu déroulant plus tard.
- Un nom de fichier.
- Une vignette.
- Un sushi aux oeufs de saumon.
- Un poids en ko.
- Une hauteur en pixels.
- Une largeur en pixels.
- Une position.
- Un titre.
- Une description.
- Un état (en ligne / hors ligne).
Gestion de l’upload et du redimensionnement
Pourquoi faire compliqué et réinventer la roue quand on peut faire simple et laisser les autres travailler pour soi ? Je vous propose donc d’installer le greffon attachment_fu, et de manger un sushi à l’anguille fumée avant qu’il ne soit complètement froid.
powerbook:~/Documents/code$ script/plugin install http://svn.techno-weenie.net/projects/plugins/attachment_fu/C’est fait, il ne nous reste plus qu’à lier les briques ensemble.
Dans app/model/gallery.rb
Nous spécifions la relation entre les galeries et les images : à une galerie correspond plusieurs images.
class Gallery < ActiveRecord::Base
has_many :pictures
endEt ligne 18 :
Il s’agit du champ correspondant à l’image que notre greffon s’attend à recevoir. Ne le décevons pas.
<%= f.file_field :uploaded_data %>Dans app/model/picture.rb
Nous appelons notre greffon avec toutes les informations dont il a besoin :
- Nous stockons nos images sur le disque local. Nous pourrions aussi le stocker sur le service S3 d’Amazone de manière totalement transparente.
- L’image fera maximum 500 ko.
- Elle sera redimensionnée en 600*450 pixels.
- La vignette fera 120*90 pixels.
class Picture < ActiveRecord::Base
belongs_to :gallery
has_attachment :content_type => :image,
:storage => :file_system,
:max_size => 500.kilobytes,
:resize_to => '600x450>',
:thumbnails => { :thumb => '120x90>' }
validates_as_attachment
endDans app/views/pictures/new.rhtml ligne 5
<% form_for(:picture, :url => pictures_path) do |f| %>
<% form_for(:picture, :url => pictures_path, :html => { :multipart => true }) do |f| %>Tout ça m’a donné faim. Et vous ?
Dans app/vews/galleries/show.rhtml
<% for image in @gallery.pictures %>
<p>
<%= link_to (image_tag(image.public_filename(:thumb), :alt => image.title), image.public_filename) %><br />
<%= image.title%>
<% image.description %>
</p>
<% end %>L’affichage plein écran et le slideshow
Une fois de plus, pas question de réinventer la roue quand d’autres le font pour moi. Nous nous en allons donc faire un tour du côté de chez Xuan et télécharger Splash Image, un script clica convi qui remplace avantageusement Lightbox sans nécessité 2go de RAM. Et pourquoi ne pas manger un sushi au thon tant qu’on y est ?
wget http://www.chez-xuxu.net/ressources/javascript/splash.image/splash.image.zip
Nous décompressons l’archive dans public/javascripts, et faisons les inclusions qui vont bien.
Dans app/views/layout/galleries.rhtml
<%= stylesheet_link_tag 'splash.image/splash.image.css' %>
<%= javascript_include_tag 'splash.image/splash.image.js' %>Dans app/vews/galleries/show.rhtml
Nous remplaçons la ligne précédemment ajoutée par celle-ci :
<%= link_to image_tag(image.public_filename(:thumb), :alt => image.title ), , {:rel => "splash.image|groupe1"}, image.public_filename %>Elle nous permet de grouper les images de cette galerie et de les faire défiler en pleine fenêtre comme si de rien n’était.
Conclusion
Voilà, c’est fini, ou presque. Il ne me reste plus qu’à ouvrir mon plat de maki et à nettoyer tout ça. Certes, ce n’est pas bien joli, mais ça marche. Je vais faire un peu de nettoyage dans le code, rajouter une feuille de style correcte, et mettre les sources sur un subversion afin que vous puissiez récupérer tout ça. Merci beaucoup à Bastien pour m’avoir montré le plugin upload_fu et avoir supporté mes blagues vaseuses toute la journée.
Vendredi, nous ajouterons une authentification basique, l’upload de masse depuis un système de fichier ou un ftp, les jolies URL search engine friendly et les tags le temps de nous siffler une ou deux pintes de Guiness que vous aurez eu la gentillesse de m’offrir par SMS comme il se doit.
[Edit] J’ai mis une démonstration du résultat final en ligne. Elle est accessible sur 20 minutes gallery et la démonstration est totalement fonctionnelle.

Commentaires
Trackbacks
Les trackbacks sont fermés pour cause de spam.
Passionné d'informatique depuis l'âge de six ans, je travaille en tant que responsable qualité chez blueKiwi Software, éditeur spécialiste des outils collaboratifs en entreprise. Ma double formation en sciences politiques et en informatique me permet de porter un regard particulier sur les problématiques abordées par mon poste.
Chris about 2 hours later:
waw
Olivier a.k.a. Zorky about 12 hours later:
Respect ! …et j’ai bien ris aussi avec les p’tites ruptures de sushis ;)
Y a-t-il une URL pour voir le résultat de tes travaux ?
Samuel MARTIN about 17 hours later:
Super intéressant, est-ce aussi facile sous Symfony ?
“l’upload de masse depuis un système de fichier” -> j’attends l’implémentation avec impatience.
et comme Oliver, y a t’il une URL pour voir le résultat ?
Frederic de Villamil about 19 hours later:
Chris : il n’y a rien d’extraordinaire hein…
Olivier : non, pas pour l’instant, je n’ai pas fait de CSS potable pour montrer quelque chose. Peut-être en fin de semaine si j’ai le temps.
Samuel : en ce qui concerne cacophony, même pas en rêve. Quant à l’upload de masse, ça doit prendre 5 lignes de code, pas plus.
J’ai oublié de préciser qu’avec deux lignes de plus, on pouvait faire l’upload sur le service S3 d’Amazon. Cf la doc du plugin d’upload.