Keyword - Tutorial

Fil des billets - Fil des commentaires

mardi 8 avril 2008

Sortir des conventions dans Rails - retour d'expérience.

Tout d'abord, sachez qu'il ne faut jamais outrepasser les conventions de Rails sans une excellente raison.

Toutefois, il arrive que l'on ai une excellente raison, le cas présenté dans ce billet sera celui (tiré d'une application réelle) d'une base de données assez mal conçue où les noms de tables sont tous au singulier et où, comble du massacre, les id d'une des tables sont sous forme de chaine de caractères.

Bien sur, cette base de données est utilisée par 18 autres applications dans la société et vous ne pouvez en aucun cas en modifier la structure (sinon ce serait trop facile).

Lire la suite...

mardi 28 août 2007

Tutorial : créer sa première application Ruby on Rails - Part3

Après une trêve due à de trop courtes mais bien agréable vacances, voici la suite de la création de notre application.

Dans ce tutorial, nous apprendrons à rajouter des tags à notre application.

Pour ce faire, je me suis largement inspiré d'un autre tutorial sur stoneageblog.com.

Lire la suite...

mercredi 1 août 2007

Tutorial : créer sa première application Ruby on Rails - Part2

Pour cette deuxième partie du tutorial, je vous propose de construire en quelques minutes l'interface d'administration de notre application, de lui ajouter un petit module de recherche et enfin de modifier la page d'accueil.

Commençons donc par l'interface d'administration :

Je ne reviendrais pas sur les méthodes index et show du controller admin puisque se sont exactement les mêmes que dans le controller snippets.

La méthode new est appellée au clic sur le lien new snippet, elle crée un objet snippet que la vue va nous permettre d'éditer.
La méthode create est appellée au clic sur le bouton "Create snippet", elle crée un objet snippet à partir des données passées en paramètres, le sauvegarde (insertion dans la BD) et nous redirige vers la page d'accueil du controller Admin.

  def new
@snippet = Snippet.new
end

def create
@snippet = Snippet.new(params[:snippet])
@snippet.save
redirect_to admin_path
end

La méthode edit est appellée au clic sur le lien edit snippet, elle crée un objet Snippet à partir de l'id passé en paramètre pour afficher les valeurs actuelles dans l'édition.
La méthode update est appellée au clic sur le bouton "Save Snippet", elle récupère l'objet Snippet à partir de l'ID, appelle la méthode update_attributes avec les paramètres passés par la vue pour mettre à jour notre Snippet dans la base, puis elle nous redirige vers la vue "Show" du Snippet édité.

  def edit
@snippet = Snippet.find(params[:id])
end

def update
@snippet = Snippet.find(params[:id])
@snippet.update_attributes(params[:snippet])
redirect_to admin_instance_path(params[:snippet])
end

La méthode Destroy supprime le snippet passé en paramètre et redirige vers la liste.

  def destroy
Snippet.find(params[:id]).destroy
redirect_to admin_path
end

Passons donc aux vues :

La vue index.rhtml du controller admin ressemble à celle du controller snippets à la différence près qu'elle rajoute un lien éditer et un bouton supprimer pour chaque snippet ainsi qu'un lien pour créer un nouveau snippet en bas de page.

La vue show est la même que celle du controller snippets à un lien près.

Les vues new et edit méritent plus de précisions :

<% form_for:snippet, :url => admin_url , :method=>:post do |f| %>
<%= content_tag :label , "Titre", {:for=
>
"titre"} %><br />
<%= f.text_field :titre %><br
/
>

<%= content_tag :label , "Texte", {:for=>"texte"} %><br />

<%= f.text_area :texte %><br
/
>

<%= submit_tag "Create Snippet"%>
<%end%>

La méthode form_for demande plusieurs paramètres. Le premier désigne le modèle en relation avec le formulaire crée (ici snippet). Le deuxième défini l'url d'action du formulaire. Le troisième la méthode d'envoi. A l'intérieur du bloc crée par form_for do ... end, les éléments seront automatiquement associés au modèle correspondant (regardez le paramètre name des champs dans la source générée pour mieux comprendre).

Vous l'avez peut être remarqué, les controllers comme les vues font un usage intensif de l'utilisation des routes automatiquement créees par Rails dans le cas d'une application REST (comme admin_path, admin_instance_path...).

J'ai volontairement choisi le nom admin pour ce controller pour vous montrer une petite spécifité de Rails.
Normalement, les noms des controllers sont au pluriel (comme Snippets) mais si l'on désire nommer son controller Admin (car c'est de l'administration et non pas des administrateurs que l'on parle), on fait face à un petit problème.
En effet, Rails se charge de mettre au singulier admin et nous propose admin, ce qui n'est pas faux, mais très génant puisque des routes devant être différentes ont désormais le même nom.
On doit donc dans ce cas, spécifier dans le fichier routes.rb le singulier que l'on utilisera grâce au paramètre :singular (j'ai pour ma part choisi admin_instance).

  map.resources :admin, :singular => :admin_instance

Il existe un autre problème dans notre application telle qu'elle est actuellement.

En effet, si vous editez ou créez un snippet en plaçant des retours à la ligne dans la description de celui-ci, vous remarquerez qu'à l'affichage, les retours chariots ont disparus.

La raison en est simple, à l'enregistrement, Rails enregistre le texte situé dans la textarea en utilisant le caractère de retour chariot normal à savoir "\n".

Ce comportement est parfaitement logique puisque si nous voulons fournir notre contenu dans différents formats (HTML, XML, PDF...), nous ne souhaiterions pas avoir de marquage HTML dans nos données.

Pourtant à l'affichage dans notre vue, on aimerait bien que ceux-ci soient interprétés et traduit en langage HTML. Rails fournit un moyen très simple d'y parvenir en utilisant la méthode simple_format d'ActionView.

Celle-ci remplacera par exemple les sauts de ligne par des <br /> et les doubles sauts de lignes par des paragraphes(<p> </p>)

On aura donc dans nos vues quelquechose comme :

<%= content_tag :p, simple_format(@snippet.texte) %>

Pour poursuivre cette deuxième partie du tutorial, je vous propose de commencer la mise en place d'un moteur de recherche très simple pour nos snippets.

Grâce à ce moteur, je souhaiterais afficher les snippets dont le titre ou le texte contient la recherche faite par l'utilisateur.

Commençons donc par créer la méthode associée dans notre modèle :

def self.find_by_titre_or_texte(search)
search ||= ""
self.find(:all,:conditions => ["titre ILIKE (?) OR texte ilike (?)","%"+search+"%","%"+search+"%"],:order => "id desc")
end

Le nom de la méthode est préfixé par self car celle-ci est une méthode du modèle Snippet et non pas une méthode applicable à une instance d'un Snippet.

La première ligne correspond à dire search = search si search existe et la chaine vide "" dans le cas contraire.

La méthode est assez triviale, elle effectue un find avec les paramètres all et conditions.
Le premier indique de récupérer tous les enregistrements (et non un seul).
Le deuxième défini les conditions de la requête, on y demande donc de vérifier si le titre ou le texte IS LIKE "%search%".
En SQL, les % désignent n'importe quelle chaîne de caractère et le I de ILIKE indique de ne pas tenir compte de la casse. Cette requête sera donc traduit en :
SELECT * FROM snippets WHERE titre ILIKE '%search%' or texte ILIKE '%search%' ;

Dans notre controller snippets, la méthode qui nous sert à afficher une liste de snippets est la méthode index.
Nous allons donc lui passer un paramètre search pour lui indiquer de n'afficher que les résultant correspondant à notre recherche.

Le paramètre search vaut par défaut la chaîne vide. De cette façon, la recherche donnera des conditions comme : titre ILIKE '%%' ce qui est vrai pour tous les titres.

Les paramères en GET sont passés en ajoutant ?param1=value1&param2=value2&param3=value3 à l'adresse demandée.
Nous appelerons donc snippets?search=rails pour récupérer tous les snippets traitant de rails.
(ex : http://depot.blogbangbang.com/snippets?search=rails).

J'ai également ajouté un formulaire de recherche simpliste dans le layout afin de pouvoir faire une recherche de partout.

        <% form_tag'/snippets', :method=>:get do -%>
<%= text_field_tag 'search' %
>

<%= submit_tag 'Search' %>
<%end-%>
Celui ci appelle donc l'URL snippets en get, et le paramètre de recherche est nommé search comme le paramètre récupéré dans notre controller.

En guise de conclusion de cette deuxième partie, nous allons corriger un autre défaut de notre application.
Vous avez peut être constater qu'à la fin de la première partie, l'adresse : depot.blogbangbang.com amenait à la page d'accueil d'une application RubyOnRails.
Il serait préférable de remplacer ce comportement par défaut par la page d'accueil de notre application, à savoir la page snippets.

Pour celà rien de plus simple, ne sortez surtout pas l'artillerie lourde et les ré-écriture d'URL..., rails s'occupe de tout (oui encore :-D)

Nous lui signifions une seule chose dans le fichier routes.rb

map.connect '', :controler => "snippet"

Supprimons également le fichier index.html dans le dossier public. Et voilà c'est tout ! Grâce à cette ligne, rails sait que si l'url demandé est vide (''), il doit rediriger vers le controlleur snippets qui par defaut éxécutera l'action index.

Voilà, nous arrivons au terme de ce deuxième tutorial, j'espère que vous commencez à saisir la puissance du framework RubyOnRails et le plaisir que peut avoir un développeur à coder grâce à celui-çi.

Dans le prochain épisode, nous ajouterons des tags à nos snippets afin de les trier plus facilement.

Archive pour voir l'état actuel de l'ensemble des fichiers.

lundi 23 juillet 2007

Tutorial : créer sa première application Ruby on Rails - Bilan1

Après ce premier billet de cette série de tutoriaux, voici l'heure du premier bilan.

Commençons par un bilan "comptable" :

Le premier article à été assez bien accueilli puisque la fréquentation de blog à frôlé les 100 visiteurs uniques vendredi dernier grâce notamment à une petite auto promotion sur railsfrance et blogasty (sans les visites par le flux RSS que je ne suis pas en mesure de calculer puisque je ne suis toujours pas inscrit à un service comme feedburner, maintenant ce sera fait on verra le résultat ces prochains jours ;) )

Toutefois, ces articles me prennent un temps fou à écrire et j'avoue que je m'attendais à un peu plus de retour en matière de commentaires notamment.
Alors, certains diront que j'insiste mais si vous pensez suivre cette série de tutoriaux, laissez moi un petit commentaire, ça motive ;)

Faisons maintenant le point sur ce que nous avons appris :

On aura tout d'abord remarqué qu'une application rails peut s'exécuter par défaut sur trois environnements : development, production et test.
Ces trois environnements permettent d'obtenir des comportements différents de l'application ainsi que des bases de données différentes.

On peut donc choisir d'afficher toutes les erreurs, d'insérer des données "virtuelles"... dans l'environnement de développement pour tester de nouvelles "features" pendant que l'environnement de production continuera a tourner a merveille.
L'environnement de test est un peu a part puisque les données n'y sont pas conservées à l'arrêt de celui ci, il est donc réservé comme son nom l'indique, à la phase de tests

On a également découvert le mécanisme de migrations de rails. Celui ci permettra au fur et à mesure de l'avancée de notre projet, d'ajouter des colonnes, des tables... en ayant toujours la possibilité de revenir facilement en arrière et de conserver l'intégrité de nos données.

Enfin, nous avons découvert quelques une des méthodes d'ActionView, la classe qui rend l'écriture de vues encore plus simple :

Je sais que certains d'entre vous ont été "choqués" part le fait que les vues ne contenait pas la moindre miette d'HTML, sachez que cela n'est en rien une obligation et qu'il est tout a fait possible d'écrire vos vues en HTML en insérant le code ruby seulement pour les données, mais cela reviendrait à se priver d'un mécanisme vous permettant d'être pratiquement certains d'écrire du code valide XHTML, et qui s'avère à la longue bien plus clair qu'un audacieux mélange entre langage à balise et langage de script.

Enfin je reviendrais ici sur un détail évident après quelques heures de codage mais qui ne l'est donc pas pour les vrais novices, sachez donc que dans les vues, les balises <% %> entoure un code ruby sans rendu tandis que les contenus placés entre <%= %> seront eux automatiquement affichés par rails.
Enfin le signe "-" placé après le tag d'ouverture ou avant le tag de fermeture indique que rails ne doit pas imprimé des caractères d'espaces ou de retour charriot situé après ou avant le tag (cela n'aura la plupart du temps d'influence que sur la présentation des sources.)

Je vous dis désormais à bientôt pour la deuxième partie du tutorial, l'interface d'administration.

jeudi 19 juillet 2007

Tutorial : créer sa première application Ruby on Rails - Part1

Allez, cette fois, c'est parti !
Si vous n'avez pas encore installé ruby on rails et radrails je vous invite a suivre ce tutoriel.

Pour ce premier tutorial, nous allons créer une version très simplifiée de notre application.

Celle-ci s'appellera Depot, nous devons donc créer les bases de données depot_development, depot_test et depot_production sous notre système de bases de données préféré, pour moi ce sera Postgresql mais les fan de Mysql peuvent l'utiliser (avec l'outil Phpmyadmin par exemple).

Lire la suite...

Tutorial : créer sa première application Ruby on Rails - Intro

Je les avais promis depuis très longtemps, les tutoriaux sur Ruby on Rails arrivent enfin sur ce blog.

Il me fallait une application à la fois très simple (pour pouvoir l'expliquer correctement) mais néanmoins assez etoffée pour tenir quelques tutos.
Ce que je vous propose, c'est donc de créer un site qui contiendra un dépot de code (ou snippets).
Ce dépot peut servir à recopier rapidement un petit bout de code qui vous a été utile et que vous aimeriez retrouver facilement.

Un exellent exemple de ce genre de dépot est Snipeet, propulsé par Symfony un "équivalent" PHP de rails, dont vous pouvez consulter un exemple sur le site snippets.prendreuncafe.com[1].

Dans cette série de tutoriaux nous allons donc créer une application comme Snipeet qui contiendra, au fur et à mesure, la gestion des tags, la recherche, un système de votes...
On pourra bien sur immaginer d'autres fonctionnalités en fonction de vos retours (si tant est qu'il y en ait).

Pour cette application, j'ai choisi d'utiliser un modèle d'architecture REST.
Je ne reviendrais pas ici sur les spécificités de cette architecture mais je vous invite à lire les articles ou diaporamas suivants :

  • L'incontournable wikipedia fr
  • Biologeek qui explique le principe avant de s'attaquer à la réalisation avec Django
  • Un diaporama résumant très bien son implémentation dans Ruby on Rails

Sachez enfin que cette série de tuto, à évidement pour but de partager les quelques connaissances que j'ai acquis après quelques mois de développement en Ruby on Rails mais également d'améliorer mon niveau avec ce framework.

J'apprenderais donc parfois en même temps que vous et je vous invite à critiquer mes choix, mon code quand vous trouverez à redire (ce qui ne manquera pas d'arriver).

Ca vous tente ? Alors suivez moi

[1] Vous êtes également invité à vous rendre sur le blog, tout aussi excellent.