You are on page 1of 41

O.

Gutknecht 2006

Ruby
on
Rails

Une (courte) introduction

Olivier Gutknecht
O. Gutknecht 2006

(Ruby on) Rails ?

Un framework pour les applications Web


crit avec et grce Ruby
Invent par David Heinemeier Hansson
Souple, intgr, dynamique, lgant,
productif... agile
O. Gutknecht 2006

Ruby (on Rails) ?


Un langage de script objet, trs dynamique, trs souple, avec une syntaxe
lgante, qui reprend les bonnes ides de Smalltalk, Lisp, ou Perl

Quelques petites indications sur la syntaxe de Ruby, suffisantes pour ce qui va suivre

Le rajout dune fonctionnalit tracer class Essai < AutreClasse Dfinition dune nouvelle classe Essai
(dfinie autre part) dans cette classe. tracer :tout hritant de la classe AutreClasse
:tout indique un symbole ( voir un peu
comme une chane constante)
Dfinition dune nouvelle mthode
def exemple exemple
On cre un objet de classe Bonjour.
@message = Bonjour.new
@ dsigne une variable dinstance (nul amis = Copains.liste Quand un appel de mthode na pas
besoin de les dclarer avant) de paramtre, on omet dhabitude le ()

Envoie le message saluer lobjet for a in amis amis et a sont des variables locales (nul
@message (avec le paramtre a). besoin de les dclarer avant usage)
@message.saluer(a)
Envoyer un message sur un objet ou sur
une classe utilise la mme syntaxe. end
Ruby tant un langage trs dynamique, on end
a souvent tendance parler denvoi de end
message plutt que dappel de mthode.
O. Gutknecht 2006

Cette introduction ?

Un coup dil gnral


Les 3 piliers de Rails
Le Modle : ActiveRecord

La Vue : ActionView

Le Contrleur : ActionController

Dvelopper avec Rails


O. Gutknecht 2006

Pourquoi Rails ?
Prendre le meilleur des deux grandes faons de faire des applications Web

RAILS
Interactif, rapide, Trs structur, cadre
facile apprendre, les architectures,
peu de contraintes, infrastructures
trs souple Rails concilie souplesse de puissantes
dveloppement et attention porte
Peu structur, dur larchitecture des applications Complexe, lourd,
maintenir, pas de long matriser,
sparation entre difficile adapter,
logique et rendu multiples couches

Pour caricaturer: Pour caricaturer:


le monde PHP le monde J2EE
Un petit exemple
(fonctionnel)
pour commencer
Afficher tous les livres dune bibliothque stocks dans une
base de donnes quand lutilisateur navigue sur...
O. Gutknecht 2006

class Livre < ActiveRecord::Base


end

id titre auteur isbn


1 Lusage du monde Nicolas Bouvier 222889401
2 Le seigneur des porcheries Tristan Egolf 2070414736

class LivreController
< ApplicationController
def exemple

@etagere = Livre.find(:all)
end
end

<html><body>
<h1>Tous les livres...</h1>
<% for l in @etagere %>

<%= l.titre %>: <%= l.auteur %><br>
<% end %>
</body></html>

3 fichiers, 12 lignes de code, ralis sans trucage


(4 lignes de plus si lon compte le fichier configurant laccs la base de donnes)
O. Gutknecht 2006

Modle(s)
(des fichiers contenant des classes Ruby)
Reprsente les donnes de lapplication,
masque le dialogue avec la base

Contrleur(s)
(des fichiers contenant des classes Ruby)
Gre la logique de la navigation, choisit
quelles informations transmettre la vue

Vue(s)
(des fichiers rhtml : des pages HTML avec du code Ruby)
Permet dlaborer des modles de pages
web et dy inclure les donnes reues

MVC : un modle classique...


... pour les applications clientes, mais assez rarement mis en uvre dune
manire aussi lgante dans les systmes de dveloppement Web
O. Gutknecht 2006

Modle(s)

ActiveRecord

+
Ruby on
=
Contrleur(s)

ActionController
Rails
+
Vue(s)

ActionView

+
Outils supplmentaires
WebServices, Mail, Intgration AJAX...
Dfinir le
Modle
ActiveRecord
O. Gutknecht 2006

ActiveRecord
Les tables correspondront des Les colonnes sont exprimes en
classes Ruby attributs de la classe

livres
id titre auteur isbn
Les ranges sont reprsentes
1 Lusage du monde Nicolas Bouvier 222889401 comme des objets
2 Le seigneur des porcheries Tristan Egolf 2070414736

ActiveRecord est un ORM (Object/Relational Mapper) : il assure le lien entre le monde objet de
Ruby et le monde relationnel de la base de donnes

Cela couvre la fois la structure (comment reprsenter une table en une classe ?) et le
comportement : les problmes non triviaux de la gestion des caches, la validation des
donnes, loptimisation des requtes, la portabilit entre plusieurs moteurs de base de donnes...
O est linformation ?
Objectif : ne jamais avoir besoin de dupliquer la mme information deux endroits
diffrents (dans la structure de la base et dans le code)

Rails interroge la base de donnes Le dveloppeur respecte quelques


pour en dcouvrir la structure conventions de nommage
RAILS
Des indications peuvent tre ajoutes pour
guider Rails (validations, associations...)

Rails essaie de naviguer entre deux cueils classiques

Les moteurs Web o la structure des Les moteurs Web o la structure des
donnes nest jamais explicite et se donnes de la base doit tre
retrouve dissmine dans tout le code rexplicite dans des fichiers de
de lapplication configuration du moteur
O. Gutknecht 2006

Exemple
id titre auteur isbn
... ... ... ...

livres
SQL Rails

CREATE TABLE livres ( class Livre < ActiveRecord::Base


id int(11) NOT NULL auto_increment,
titre varchar(255), end
auteur varchar(255),
La classe de base de tous les
isbn varchar(13),
modles ActiveRecord
PRIMARY KEY (id));

Nul besoin de se rpter


Rails interrogera la base pour obtenir la structure de la table et enrichir la classe.

Tirer parti de conventions


Une colonne id sera suppose tre lindex principal.
Une classe Livre correspondra la table Livres (au pluriel).
Les colonnes titre, auteur, isbn deviendront des attributs de la classe.
O. Gutknecht 2006

Sous le capot
Ruby
class Livre < ActiveRecord::Base
end

a = Livre.new
a.titre = Lusage du monde
a.auteur = Nicolas Bouvier SQL gnr
a.isbn = 222889401X INSERT INTO livres ("isbn", "auteur",
a.save "titre") VALUES('222889401X', 'Nicolas
Bouvier', 'L''usage du monde')

b.find(1) SELECT * FROM livres WHERE (livres.id


puts b.auteur Affichera Nicolas Bouvier = '1') LIMIT 1

b.destroy DELETE FROM livres WHERE id = 1

Rien de magique
Les mthodes save ou find ne font que masquer le dialogue avec la base de donnes.
On peut aussi utiliser des mthodes find_by_auteur ou find_by_titre. Rails reconnatra les formes en
find_by_xxx et les traduira en requtes sur le champ correspondant : le dynamisme de Ruby en action.
O. Gutknecht 2006

Associations
usagers

class Usager < ActiveRecord::Base id nom adresse


has_many :emprunts ... ... ...
end
livres
class Livre < ActiveRecord::Base id titre auteur isbn
has_many :emprunts ... ... ... ...
end

emprunts
class Emprunt < ActiveRecord::Base
id usager_id livre_id sortie retour
belongs_to :usager
... ... ... ...
belongs_to :livre
end

Indicateurs et conventions
Ces marqueurs permettent de clarifier un modle complexe, de donner Rails de quoi
construire et optimiser les requtes SQL sous-jacentes, en supposant quelques conventions
dcriture (ici usager_id et livre_id pour reprsenter les associations dans la table).
O. Gutknecht 2006

Sous le capot (bis)


Rails SQL gnr
u = Usager.find_by_nom("Olivier Gutknecht") SELECT * FROM usagers WHERE (usagers."nom" = 'Olivier
Gutknecht' )
u.emprunts[0].sortie SELECT * FROM emprunts WHERE (emprunts.usager_id = 1)
u.emprunts[0].retour (rien)

u = Usager.find_by_nom("Enoch Root",
:include => :emprunts) SELECT usagers.id, usagers.nom, usagers.adresse,
emprunts.id, emprunts.sortie, emprunts.retour,
emprunts.livre_id, emprunts.usager_id FROM usagers
LEFT OUTER JOIN emprunts ON emprunts.usager_id =
usagers.id WHERE (usagers.nom = 'Enoch Root')
u.emprunts[0].sortie (rien)

Rails la tche doptimiser les requtes, cacher les rsultats

Au dveloppeur la responsabilit de donner suffisamment dindications sur


lusage voulu (par exemple ici le :include) pour guider Rails
O. Gutknecht 2006

Oui, mais si... ... ma base existait dj ?


lib2_book

bookID titre auteur isbn ... et toutes mes tables ont un prfixe ?
... ... ... ...
... et mes index ont un nom spcifique ?

... je dois faire une requte bien particulire ?

class Livre < ActiveRecord::Base ActiveRecord::Base.table_name_prefix = "lib2_"


set_primary_key "bookID" ActiveRecord::Base.pluralize_table_names = false
end

Livre.find_by_sql(SELECT * FROM livres WHERE auteur = Nicolas Bouvier)

Convention nest pas interdiction !


Il reste possible de prciser des comportements diffrents table par table, globalement, de revenir
des requtes construites la main, sans perdre les autres avantages de Rails.

Les conventions sont l pour faciliter le cas gnral, et non rendre impossible le cas particulier.
Mettre en place les
Contrleurs
ActionController
Serveur Web

Rails - Aiguillage Initial


LURL est dissque pour trouver le contrleur et sa mthode,
ainsi que la vue qui en fera le rendu final

views/livre/exemple.rhtml controllers/livre_controller.rb

<html> class LivreController < ApplicationController


<body> def exemple
<%= @info ... > @info = ...
</body> end
</html> end

Encore des conventions !


Cette faon daiguiller une requte permet de simplifier le travail du concepteur de l'application :
il y a juste respecter des rgles simples de nommage de fichiers et de mthodes.

L encore, il est possible de passer outre ces conventions, moyennant un peu de code supplmentaire.
http://exemple.com/usager/liste
http://exemple.com/usager/fiche/4212
Contrleur Action Paramtre

class UsagerController < ApplicationController



def liste


@usagers = Usager.find_all

end


def fiche


@usager = Usager.find(@params["id"])

end
end
app/controllers/usager_controller.rb

Paramtres
Une fois extraits le contrleur et l'action, le reste de l'URL - si prsent - sera vu comme des
paramtres supplmentaires stocks dans un dictionnaire et prt tre utiliss par le contrleur
On peut ainsi exploiter de la mme manire des requtes complexes POST ou GET (de la forme ?a=b)
O. Gutknecht 2006

Que trouver dans un


contrleur ?
La logique de lapplication...
... prparer des donnes pour une page, et le faire
diffremment pour un utilisateur identifi ou anonyme

... recevoir les rsultats dun formulaire HTML pour


enregistrer des donnes, et immdiatement rediriger
vers une autre page

... vrifier quun utilisateur est identifi et si non, le


rediriger vers la page idoine
O. Gutknecht 2006

Une navigation
http://exemple.com/usager/liste http://exemple.com/emprunt/nouveau/2 http://exemple.com/emprunt/creer/...

Contrleur: usager Action: liste Contrleur: emprunt Action: nouveau Contrleur: emprunt Action: creer
Paramtre: 2 (ID usager) Paramtres: Ubik (titre), 2 (ID usager)
obtention de la liste des utilisateurs
Obtient les informations sur lutilisateur et ses Rcupre les informations de formulaire,
emprunts courants, vrifie sil a le droit vrifie la validit (obtient lobjet livre), instancie
demprunter et enregistre un objet emprunt.
Vue: usager/liste.rhtml
Redirige ensuite vers un autre contrleur
Usagers

Olivier Gutknecht [Fiche] [Nouvel Emprunt] Vue: emprunt/nouveau.rhtml http://exemple.com/usager/fiche/2


Enoch Root [Fiche] [Nouvel Emprunt] Nouvel emprunt
Enoch Root
2 livres emprunts
Contrleur: usager Action: fiche
Snow Crash - le 12/02/45 (retard)
Quicksilver - le 02/05/06 Paramtre: 2 (ID usager)
Obtient les informations sur lutilisateur et ses
Nouvel emprunt: Ubik emprunts courants

Vue: usager/fiche.rhtml
Enoch Root - 12, Bletchley Park [Editer]
3 livres emprunts
Lenchanement dun contrleur lautre se Snow Crash - le 12/02/45 (retard)
fait suite des actions de lutilisateur, ou Quicksilver - le 02/05/06
Ubik - le 05/08/06
selon la logique dun contrleur
[Sommaire] [Emprunt] [Usagers] [Livres]
O. Gutknecht 2006

Quelques autres outils


Rails

class UsagerController < ApplicationController


On peut se servir des filtres rutilisables pour tout ou partie dun
before_filter :autoriser, :only => :nouveau contrleur, appliqus avant ou aprs le traitement de la requte
after_filter :compression
caches_action :liste Une politique de cache peut tre dfinie comme ici sur une action
prcise, mais aussi au niveau dune page complte ou dun fragment
def nouveau
if request.get? Rails transmet la requte complte au contrleur, on peut donc
@usager = Usager.new regrouper dans la mme action deux traitements diffrents, selon que
lon examine un GET ou un POST: typiquement pour gnrer un
else formulaire, ou en traiter le rsultat
@usager = Usager.new(params[:usager])
@usager.save Les cookies sont grs par Rails et transmis prt lusage au
cookies[:nom] = @usager.nom contrleur. La session de travail de lutilisateur est garde et
manipulable exactement de la mme manire
redirect_to :action => "liste"
end
end Mme ces aspects trs transversaux
sexpriment encore dans ce mme principe
def liste de contrleur/action
...
Crer des
Vues
ActionView
O. Gutknecht 2006

ActionView
Utilise le principe de gabarits de pages
HTML avec un peu de code inclus
(fichiers .rhtml)
Les donnes du contrleur sont
automatiquement transmises la vue
Les liens entre les pages, les formulaires
sexpriment l encore en tant que
contrleurs et actions
O. Gutknecht 2006

Inclure du code
<html><body>
<h1>Usager: <%= @usager.nom %> </h1>

<h1>Livres emprunts</h1>
<% for l in @usager.emprunts %>

<%= l.titre %>: <%= l.auteur %> <br>
<% end %>

</body></html>

<% ... %> <%= ... %>


Le code Ruby lintrieur de ce tag Le code Ruby lintrieur de ce tag
sera excut, mais le rsultat ne sera sera excut, et le rsultat sera inclus
pas plac dans la page HTML dans la page HTML

Parfait pour les tests, les boucles, et Parfait pour afficher les informations
tous les petits traitements transmises par le contrleur
O. Gutknecht 2006

Afficher linformation
<html><body>
<h1>Usager: <%= @usager.nom %> </h1>

<h1>Livres emprunts</h1>
<% for l in @usager.emprunts %>

<%= l.titre %>: <%= l.auteur %> <br>
<% end %>

</body></html>

Les variables commenant par @ sont celles dfinies dans le contrleur,


et Rails va automatiquement les rendre accessibles la vue.

On parcourt simplement ici les emprunts dun usager, mais ce qui est
manipul ici est bel et bien un modle ActiveRecord qui rend transparent
laccs la base de donnes, comme vu prcdemment
O. Gutknecht 2006

Gnrer un lien
Vue RHTML

Usager: <%= @usager.nom %> <br>


<%= link_to("Editer cette fiche", :action => "editer", :id => @usager) %><p>
<%= link_to("Liste des livres", :controller => livre, :action => liste)%>

HTML gnr

Usager: Olivier Gutknecht <br>


<a href="/usager/editer/1">Editer cette fiche</a> <p>
<a href="/livre/liste">Liste des livres</a>

Les outils de gnration de liens


Mme dans une vue, Rails permet de continuer travailler dans ce
Usager: Olivier Gutknecht
Editer cette fiche
mme univers de contrleur / action / paramtres.
Liste des livres On peut ainsi exprimer les liens un niveau plus abstrait et saffranchir de
la gestion des URL. Cela permet galement de simplifier lcriture (par
exemple, le contrleur courant peut tre omis).
O. Gutknecht 2006

Le priple dun formulaire


http://exemple.com/livre/editer/42
@params = {:id => 42,
:livre => {:titre => "1984",
@params = {:id => 42} :auteur => "George Orwell"}}

def editer def sauver


@livre = Livre.find(params[:id]) l = Livre.find(params[:id])
end l.update_attributes(params[:livre])
controllers/livre_controller.rb l.save
end
<%= form_tag :action => 'sauver', :id => @livre %>
controllers/livre_controller.rb
<%= text_field 'livre', 'titre' %>
<%= text_field 'livre', 'auteur' %>
<%= submit_tag "Sauver"%>
<%= end_form_tag %> Une belle coopration entre
views/livre/editer.rhtml
modle, contrleur et vue

text_field, form_tag... : ces mthodes


<form action="/livre/sauver/42" method="post"> spcialises (helpers) permettent de
<input name="livre[titre]" value=1984>
<input name="livre[auteur]" value=George Orwell> construire facilement des formulaires pr-
<input type="submit" value="Sauver"> remplis selon les donnes du modle et den
</form>
transmettre les modifications au contrleur
Code HTML gnre
sous une forme immdiatement exploitable.
Dvelopper
avec Ruby on Rails
O. Gutknecht 2006

Limportance des -cts


Structurer le plus possible lapplication
Mme via lorganisation du projet sur le disque

Encourager les bonnes pratiques


Migration de schmas, tests unitaires, nommage et
placement des fichiers

Faciliter un dveloppement rapide et itratif


Mode de dveloppement live, chafaudages

Les outils de Rails (gnrateurs de code, serveur de test) sont conus dans cet esprit.
O. Gutknecht 2006

application.rb

controllers livre_controller.rb

usager_controller.rb

livre.rb

app models

usager.rb

config editer.rhtml

views livre

doc nouveau.rhtml

bibliotheque log editer.rhtml

usager

public nouveau.rhtml

livre_controller_test.rb

tmp functional

usager_controller_test.rb

test integration

livre_test.rb

unit

usager_test.rb

Structure dun projet


La sparation de lapplication entre modles, vues, contrleurs, tests, plugins,
configurations, logs, etc. est immdiatement visible.
O. Gutknecht 2006

Guider le dveloppeur
Rails fournit de nombreux scripts permettant la gnration de squelettes de code. Tous ces
outils se basent sur les conventions de nommage et dorganisation de fichiers de Rails.

Script de gnration de projet Script de gnration de modle Script de gnration de contrleur


(structure de rpertoires, fichiers de (squelette de code applicatif, squelette de (Squelette de code applicatif, squelette du
configuration initiaux...) code de test, configuration du test...) code de test, rpertoire des vues...)

$ rails bibliotheque $ script/generate model usager $ script/generate controler usager


create exists app/models/ exists app/controllers/
create app/controllers exists test/unit/ exists app/helpers/
create app/helpers exists test/fixtures/ create app/views/usager
create app/models create app/models/usager.rb exists test/functional/
create app/views/layouts create test/unit/usager_test.rb create app/controllers/usager_controller.rb
create config/environments create test/fixtures/usagers.yml create test/functional/usager_controller_test.rb
[...] exists db/migrate create app/helpers/usager_helper.rb
create doc create db/migrate/002_create_usagers.rb
create log
create public/images
create public/javascripts
create public/stylesheets
create script/performance
create script/process
create test/functional
create test/integration Rails fournit par dfaut un certain nombre de gnrateurs de code (modle,
[...]
create test/unit
contrleur, webservice, mailer...) mais permet aussi dintgrer facilement un
create
create
tmp/sessions
tmp/cache
grand nombre de plugins: authentification, statistiques, graphes, outils AJAX...
create Rakefile
create README
O. Gutknecht 2006

Les chafaudages
Au dbut du dveloppement dune application Web, il est
frquent davoir besoin de crer/afficher/modifier/dtruire des
lments du modle (CRUD: Create/Read/Update/Delete)

Le gnrateur dchafaudages (scaffolding) de Rails produit


automatiquement un contrleur et des vues - simplistes - mais
immdiatement fonctionnelles pour un modle donn.

$ script/generate scaffold Livre


exists app/controllers/
exists app/helpers/
create app/views/livres
exists test/functional/
exists app/models/ Itrer, toujours
exists test/unit/
exists test/fixtures/ Rails incite avoir des tapes de
create app/models/livre.rb
create test/unit/livre_test.rb dveloppement rapproches, o
create test/fixtures/livres.yml
create app/views/livres/_form.rhtml lapplication reste le plus
create app/views/livres/list.rhtml
create app/views/livres/show.rhtml possible fonctionnelle
create app/views/livres/new.rhtml
create app/views/livres/edit.rhtml Lchafaudage (i.e. les diffrentes actions
create app/controllers/livres_controller.rb
create test/functional/livres_controller_test.rb du contrleurs et les vues) sera retir au
create app/helpers/livres_helper.rb fur et mesure, au profit du code
create app/views/layouts/livres.rhtml
create public/stylesheets/scaffold.css dfinitif.
O. Gutknecht 2006

En dveloppement
diter/complter les
Gnrer un squelette de code
contrleurs, modles ou vues

Ruby
ou
RHTML

Tester
lapplication
Corriger une erreur
En dveloppement, Rails fonctionne avec son
propre mini-serveur Web: WEBrick.

Dans ce mode, changer quelque chose dans


lapplication ne demande que deux choses
RAILS
pour tre pris en compte :
sauver le fichier, recharger la page Web. En traitant les requtes, Rails vrifiera que les fichiers
sont jour, et si besoin, rechargera dynamiquement le
code, sans avoir relancer lapplication ou le serveur
O. Gutknecht 2006

En dploiement
De nombreuses options possibles

Serveurs Web Lighttpd Apache1 Apache2 Mongrel

Serveurs
dapplication CGI FastCGI SCGI

Aide au dploiement
Capistrano
RAILS

Bases de sqlite MySQL PostgreSQL


donnes
supportes
Oracle SQL Server DB2 FireBird

Faciliter lexprimentation Assembler le puzzle


Rails permet de travailler dans des environnements (test, Il est tout fait possible de combiner ces solutions, par
production, dveloppement...) isols o les comportements exemple un serveur Apache pour dlivrer le contenu
de cache et les configurations de bases de donnes peuvent statique de lapplication, et un modproxy vers un lighttpd ou
rester distincts. un mongrel pour laspect dynamique
O. Gutknecht 2006

Les 2 cls de Rails

Ne pas se rpter !
Rails fournit au dveloppeur larchitecture et les outils ncessaires pour
viter de dupliquer inutilement du code. lui de jouer le jeu jusquau bout.

Plutt convention que configuration !


Rails part du principe que le comportement le plus courant doit tre celui qui ne
ncessite aucun code ou configuration, quitte pouvoir le changer sil ne convient pas.
O. Gutknecht 2006

Rfrences
PragmaticProgrammers OReilly Manning Publications

vo - PragmaticProgrammers vf - Editions Eyrolles OReilly APress

http://rubyonrails.org/books
O. Gutknecht 2006

Rfrences
http://www.rubyonrails.org/
Site officiel de Rails : documentation, weblog,
downloads, wiki et howtos, APIs, bugtracker...

http://www.railsfrance.org/
Site Rails francophone : forums, liens,
traductions, tutoriaux, actualit...

http://www.ruby-lang.org/
Site principal sur Ruby : FAQ,
documentation, tutoriaux, projets Ruby...

http://www.rubyforge.org/
Repository de projets Ruby Open
Source, base de donnes de projets
O. Gutknecht 2006
O. Gutknecht 2006

Rails - Une (courte) Introduction - v1.0.3

CC
Creative Commons
http://creativecommons.org/licenses/by-nc-nd/2.0/fr/

Vous tes libres de reproduire, distribuer et communiquer cette cration au public selon les conditions suivantes:

BY: Paternit : Vous devez citer le nom de l'auteur original.

Pas d'Utilisation Commerciale : Vous n'avez pas le


droit d'utiliser cette cration des fins commerciales.

Pas de Modification : Vous n'avez pas le droit de


=
modifier, de transformer ou d'adapter cette cration.

chaque rutilisation ou distribution, vous devez faire apparatre clairement aux autres les conditions contractuelles
de mise disposition de cette cration.

Si vous dsirez utiliser cette prsentation sous dautres conditions, merci de me contacter:
Olivier Gutknecht - olg @ no-distance.net

You might also like