Ruby on Rails | Mise à jour 08-2014 |
|
La description qui suit est succinte et ne couvre pas toutes les subtilités et possibilités de Rails (entre autres les procédures de test). Elle permet néanmoins d'en comprendre le fonctionnement et d'éclairer un peu l'aspect parfois "magique" de ce framework. En bas de page, des liens orientent vers des sites plus complets, avec des explications très détaillées sur les mécanismes de Rails. D'autre part, une application de bibliothèque est fournie et commentée. Elle illustre l'utilisation du framework par des exemples concrets. L'étude des exemples des tutoriels est un bon préalable à l'apprentissage de ce logiciel, même si leur simplicité et leur utilisation standard du framework masquent un certain nombre de choses automatiques. Rails est donc un framework de développement Web. Il obéit au modèle de programmation MVC : Modèle - Vue - Contrôleur. Ces trois éléments ont des attributions particulières bien séparées, ce qui clarifie la conception et l'écriture des applications. Le modèle Le modèle définit les tables de la base de données et les relations entre elles. Il est indépendant des bases utilisées. C'est lui qui permettra, grâce à l'ActiveRecord, les lectures des tables et des automatismes comme la recherche automatique d'enregistrement liés, et aussi les différentes opérations de mise à jour (ajout, modification, suppression). On y définit aussi des contrôles automatiques sur les champs des tables, qui seront automatiquement exécutés lors de la mise à jour de la base. Si la mise à jour échoue, les erreurs éventuelles créeront des messages appropriés qu'il sera possible de récupérer pour les afficher. Exemple de liens, dans une bibliothèque un auteur a écrit des livres. Quand les liens sont correctement définis, on peut accéder aux livres de cet auteur juste en lisant la table des auteurs, sans autre code d'accès. La vue La vue est le composant qui définit la présentation des données fournies par le modèle. On y trouve du code html pur et aussi du code spécifique qui utilise des helpers standard pour générer du code html (formulaire, bouton, champ en lien avec la base, ...). Le contrôleur Il reçoit des requêtes sous forme d'url, soit directement tapées dans le navigateur, soit par des demandes issues de la vue (lien ou bouton). En fonction de l'url, il exécute une action, constituée de code écrit en Ruby. La transaction peut contenir des données, qui seront utilisés pour déclencher des requêtes (lecture, écriture) vers le modèle et orienter les données vers la prochaine vue appropriée. Il faut ajouter à ces composants le mécanisme de routage qui lie une url à une action d'un contrôleur. le fonctionnement peut donc se résumer ainsi :
Rails travaille autour de trois principes :
L'arborescence d'un projet rails est un peu complexe. Chaque répertoire et sous-répertoire contient des fichiers dont la fonction est bien définie : les vues ne sont pas mélangées avec les contrôleurs ... Je ne cite ici que les plus courants que l'on doit renseigner. Le premier porte le nom de l'application. Il contient de nombreux répertoires et fichiers qui composent un environnement complet de développement et d'exécution. Seuls sont décrits ci-dessous ceux qui constituent l'application. app Contient les principaux composants de l'application, dans l'ordre alphabétique :
config Fichiers de configuration de l'application.
Contient les bases de données des différents environnements (développement, test) selon leur nature (sqlite par défaut, mysql, ...) et leur description.
Rails propose plusieurs outils pour parvenir à nos fins. Création de l'application La première étape est de créer l'arborescence de l'application. Se positionner dans le répertoire dédié aux applications rails et taper la commande rails new biblio. On dispose maintenant dans le répertoire biblio de l'arborescence définie précédemment. Se positionner dans ce répertoire. Création de la base de données Par défaut, Rails propose de travailler avec sqlite. Il n'est alors pas utile de modifier la configuration. C'est le choix adopté. Pour créer la définition de la table des auteurs, taper la commande rails generate model auteur autabr:string{10} autnom:string{30}. Celle-ci génère deux fichiers : le modèle app/models/auteur.rb et le fichier de migration db/migrate/aaaammjjHHMMSS_create_auteurs.rb Puis lancer la commande rake db:migrate pour créer la table dans la base. Si elle échoue, il peut être nécessaire de la lancer comme suit : bundle exec rake db:migrate A ce stade, Rails a déjà mis en oeuvre des automatismes :
Il est possible de supprimer ces automatismes au prix de quelques manipulations un peu délicates. L'avantage de conserver le standard est que les définitions des tables sont plus simples, lorsque l'on veut définir les associations entre elles. En effet, dans le modèle Auteur, on dit simplement has_many :"livres". Dans le modèle Livre, on indique belongs_to :auteur. Noter le pluriel et le singulier. Ceci suppose que dans la table des livres on ait défini un champ auteur_id qui représente la clé étrangère de l'auteur. Il est possible d'utiliser des noms différents pour les ids, les relations sont un peu plus difficiles à définir (il faut intervenir manuellement dans les fichiers modèles et dans les fichiers de migration). Utilisation de la base Dans le répertoire de l'application, lancer la console par rails console --sandbox (sandbox indique que les données seront perdues en fermant la session). a=Auteur.new crée une instance vide du modèle Auteur Réponse : # < Auteur id: nil, autabr: nil, autnom: nil, created_at: nil, updated_at: nil > On voit donc une instance vide, dont il faut renseigner les valeurs, sauf celles qui sont automatiques. a.autabr="ABR" a.autnom="Nom" a.save a Réponse : # < Auteur id: 15, autabr: "ABR", autnom: "Nom", created_at: "2014-08-17 12:17:23", updated_at: "2014-08-17 12:17:23" > b=Auteur.create(:autabr => "ABR 2", :autnom => "Nom du 2"). Cette commande est équivalente à new ... save. Pour retrouver les auteurs, taper Auteur.find(:all). Pour obtenir le n° 15, taper Auteur.find(15) Pour modifier cette ligne : a=Auteur.find(15) puis a.autnom="Nom 1" et enfin a.save. Procéder de la même façon pour créer des livres, en n'oubliant pas d'affecter au champ auteur_id l'id d'un des auteurs créés. Ensuite, en recherchant un auteur ( a=Auteur.find(15) ), on peut lister ses livres avec a.livres. Find propose d'autres critères de sélection (par nom de champ, critères multiples ...). Voir la documentation complète pour plus de détails. Création d'un contrôleur Lancer la commande rails generate controller ctl action1 action2 Ceci crée plusieurs éléments :
Démarrer le serveur rails par rails server Dans le navigateur, taper localhost:3000/ctl/action1 Création d'un scaffold Un scaffold est un ensemble qui permet en une seule étape de générer une application de mise à jour d'une table (contrôleur, vues, modèle, routage). La syntaxe est rails generate scaffold Table zone1 puis rake db:migrate pour créer la table. Le modèle s'appelle Table, le contrôleur tables et les vues sont dans le répertoire tables. Elles ont le même nom que les actions du contrôleur. Le code de l'application est minimal, avec beaucoup de comportements par défaut. Evidemment, la présentation générée n'est pas très ergonomique, mais donne une base de développement qui fonctionne. Un scaffold ne peut gérer qu'une table et ne peut donc servir à des applications trop complexes. |
L'exemple proposé ici est une classique application de bibliothèque. Il est organisé autour de 3 tables : des auteurs, des catégories et des livres. Un livre appartient à un auteur et est défini par sa catégorie. L'écran est structuré également de manière classique, avec un bandeau horizontal pour le titre, un bandeau vertical à gauche pour le menu et une partie centrale recevant les différents formulaires. Eux-mêmes sont organisés toujours de manière identique : un titre, un corps et un pied de page regroupant les boutons d'action. Il existe deux types de formulaires :
Exemples de pages :
Afin de bien appréhender le fonctionnement de rails, en ne bénéficiant pas des automatismes qu'il propose, j'ai choisi de m'écarter du standard sur plusieurs points :
Ce chapitre liste les fichiers de l'application avec une explication succinte de leur conception et de leur contenu. De plus amples informations figurent à l'intérieur. La base de données Les structures sont créées par les fichiers du répertoire db/migrate. Dans l'ordre des noms, on crée les auteurs, puis les livres, en respectant les standard de nommage des champs. Ensuite, on crée les catégories, avec des noms de champs personnalisés, puis on met à jour la description des livres en ajoutant une nouvelle clé étrangère. Dans le répertoire app/models se trouvent les modèles des tables dans lesquels on décrit les clés primaires et les associations entre tables. On constate, lorsqu'on utilise des noms de champs standard, que certaines définitions sont automatiques; si on s'éloigne de ce standard, il faut tout spécifier. Noter également l'utilisation du singulier et du pluriel dans la dénomination des tables, des modèles, des associations. S'en écarter nécessite des paramètres supplémentaires. Les routes Les routes sont contenues dans le fichier routes.rb du répertoire config. Différentes syntaxes équivalentes permettent de donner à des url (controleur/action) des noms plus parlants et qui masquent les noms techniques. Ainsi la ligne match "valider_ajout_dun_auteur" => "auteurs#ajoutvalid", :via => :post renvoie sur l'action ajoutvalid du contrôleur auteurs, avec le verbe html POST, qui envoie les données du formulaire. Au lieu de donner le nom technique de l'url, le programme l'invoque en l'appelant valider_ajout_dun_auteur_path. A contrario, la ligne get "auteurs/ajout",sans renommage, est disponible via la variable automatique auteurs_ajout_path. Les feuilles de style Les feuilles de style sont contenues dans le répertoire app/assets/stylesheets. Une feuille de nom application.css fournit des informations de compilation pour les autres feuilles d'extension .scss. Par défaut, toutes les feuilles scss, quel que soit leur nom, sont automatiquement prises en compte. On en constitue une par contrôleur pour des raisons de commodité, mais on pourrait tout mettre directement dans la feuille application.css., ou trouver toute autre organisation. Les layouts Les layouts, qui sont des gabarits pour les vues, sont dans le répertoire app/views/layouts. Il sont utilisés pour toutes les vues, qui ne doivent plus fournir que leurs spécificités qui s'intègrent par une commande "yield" dans le gabarit. On peut aussi créer des "partials" qui sont des morceaux de code des vues, et que l'on peut insérer dans n'importe quelle vue par la commande "render", sans avoir à recopier tout le code commun. On trouve donc :
Les helpers Les helpers sont des modules qui définissent des fonctions que l'on peut glisser dans une vue ou un contrôleur. L'application possède un helper, chaque contrôleur aussi. Le fichier app/helpers/application_helper.rb contient une fonction qui retourne le titre de la page, en fonction du contrôleur et de la dernière action exécutée. Ainsi, le code est minimal dans chaque vue et centralisé dans un seul fichier, plus facilement exploitable et maintenable. Les helpers auteurs, categories et livres contiennent une fonction qui a pour but d'orienter le formulaire vers l'action suivante; par exemple quand on est sur la page d'ajout d'un auteur, la validation du formulaire doit le diriger vers l'action de validation des données. Comme la vue appelée modif est commune à l'action d'ajout et à celle de modification; il faut indiquer dans le formulaire quelle url doit être utilisée lors de sa validation. Ceci est nécessaire car le principe REST n'a pas été adopté, il faut donc faire le travail soi-même. Cette fonction calcul_action qui porte le même nom dans chaque contrôleur aurait pu aussi bien être écrite dans application_helper.rb, comme pour le titre des écrans. Les vues Les vues sont rangées dans le répertoire app/views, un sous-répertoire par contrôleur. Elles décrivent seulement les spécificités d'une action, la partie commune aux pages étant gérée par un layout. Pour le contrôleur livres, on trouve trois vues au comportement différent. La vue liste Elle se compose d'une boucle qui balaie une liste des livres, établie par le contrôleur, et génère le code html ligne à ligne. La vue modification Elle est utilisée pour l'ajout et la modification. Elle crée un formulaire via le helper intégré form_for. On lui associe une instance de la table que l'on veut gérer, instance créée dans le contrôleur avant d'afficher la vue. Ensuite, par des helpers text_field, on établit le lien entre le champ à l'écran et le champ de la table. Pour les livres, on veut aussi afficher une liste déroulante de choix des auteurs. On utilise alors le helper fields_for qui accède à une instance de la table auteurs. La liste déroulante est définie par le helper select. La vue recherche Là aussi un formulaire est créé, mais il n'est pas attaché à une table. C'est le helper form_tag qui est utilisé, au lieu de form_for. Les champs qu'il s'agit de mettre à jour sont des cookies qui serviront dans la liste des livres à opérer des sélections au niveau du contrôleur. On utilise dans toutes les vues d'autres helpers, comme link_to pour définir des liens. Les contrôleurs Les contrôleurs sont dans le répertoire app/controllers. Ils comportent en général les actions suivantes :
Rails propose un outil de déboggage que je n'ai pas encore testé. Le principal souci rencontré pendant la mise au point des programmes concerne la structure des paramètres passés entre les vues. La solution que j'utilise est de se servir du champ d'erreur placé dans chaque vue pour afficher le contenu du tableau associatif params reçu par l'action, d'afficher la vue par un render, puis de sortir de l'action. C'est assez rudimentaire mais permet de visualiser ce tableau et de comprendre les imbrications qu'il comporte. |
Disponible gratuitement en téléchargement sur le site railsinstaller.org. Il fournit une version de Ruby et une version de Rails. Il est préférable pour éviter tout problème d'installation de prendre la package complet.
Ces sites proposent des cours et documentations sur le framework. Ruby on rails tutorial, par Michael HARTL developpez.com, initiation Codelearn RailsGuides |