ActionController : Monsieur Circulation
Par jblanche le mercredi 30 juillet 2008, 23:10 - tout public - Lien permanent
Dans Rails, ActionController fait la circulation, il va à chaque requête, appeler les modèles nécessaires pour récupérer les données, puis appeler la méthode render pour afficher une vue, un XML... et vous renvoyer le tout.
La politique Rails veut que les controllers soient légers.
"Skinny Controller, Fat Model"
Jamis Buck, 37signals employee
Et ça tombe bien Rails fourni tout ce qu'il faut pour vous simplifier la vie...
Imaginez par exemple que vous vouliez une interface de gestion de nos étudiants précédemment crées.
Si nos souhaits se limitent à l'ajout, modification, suppression, le scaffold de Rails ferait l'affaire,
mais on va ici partir "from scratch" pour vous montrer à quel point tout ceci est aisé.
On créera alors un Controller StudentsController
script/generate controller Students
Rails2.1 permet de faire très facilement des controllers dit "Restful".
Si vous ne savez pas ce dont il s'agit je vous invite à lire l'excellente traduction de Biologeek d'un article de Softies on Rails :
Pour ne plus être en REST, comprendre cette architecture
et/ou celle-ci de pompage.net :
Comment j'ai expliqué REST à ma femme
Si vous avez lu et compris, vous aurez retenu qu'avec REST on utilise tous les verbes du protocole HTTP et qu'on parle de ressources plutôt que de pages web ou d'images...
Les ressources, dans notre cas, ce sont des étudiants et voici quelques URLs qui vont nous intéresser
GET /students :action=>"index"
POST /students :action=>"create"
GET /students/new :action=>"new"
GET /students/:id/edit :action=>"edit"
GET /students/:id :action=>"show"
PUT /students/:id :action=>"update"
DELETE /students/:id :action=>"destroy"
Vous aurez compris que pour afficher un utilisateur on fera /students/:id, mais et c'est là où REST intervient, on utilisera la même adresse pour le supprimer et le modifier.
En effet une ressource = une URI, donc un utilisateur => "/students/:id"
Par contre, le type de requête HTTP, respectivement GET, DELETE ET PUT nous informera sur ce que l'on souhaite faire.
Avec Rails, les actions appelées sont les méthodes publiques des controllers, écrivons donc la méthode qui va afficher un utilisateur
def show
@student = Student.find(params[:id])
end
Et voilà...
Quoi c'est tout :D
Oui, pour l'instant cela peut suffire, en effet Rails a récupéré notre ressource (l'utilisateur désiré) grâce au find et par défaut, il va appeler la méthode render avec la vue correspondante (show) dans le dossier des vues.
Cette dernière aura accès aux variables d'instance de notre classe et donc à l'objet @student et toutes ses propriétés.
Essayons maintenant d'écrire la méthode nécessaire à la modification (update) d'un utilisateur.
def update
@student = Student.find(params[:id])
@student.update_attributes(params[:student])
redirect_to @student
end
Dans la première ligne, je récupère l'étudiant à créer.
Dans la seconde j'update ses attributs (donc propriétés) avec les paramètres passés par le formulaire.
Dans la dernière je redirige l'utilisateur vers le student modifié (cela appellera la méthode show précédemment créée)
En réalité il faudrait gérer le fait que la sauvegarde se soit ou non bien passée, cela donnerait donc :
def update
@student = Student.find(params[:id])
if @student.update_attributes(params[:student])
redirect_to(@student)
else
render :action => "edit"
end
end
C'est presque la même chose sauf que si la sauvegarde n'a pas fonctionné, on revient sur la page d'édition.
Voilà pour la version HTML, mais si vous avez compris REST, vous savez que l'on aimerait pouvoir
avoir d'autre représentation de notre ressource qu'une page web !
Pourquoi pas par exemple, une représentation XML que l'on pourrait passer à un webservice distant ou je ne sais quel autre usage.
Ré-écrivons notre méthode show dans ce but
def show
@student = Student.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @student }
end
end
Et voilà, notre controller répondra désormais à la demande générée.
Si vous lui demandez du HTML, celui là réagira comme précédemment, si vous le voulez en XML, il exécutera la ligne :
format.xml { render :xml => @student }
et renverra donc notre objet student converti en XML.
Vous voulez discuter avec une application Flash/Flex/AIR..., installez RubyAMF (l'équivalent Ruby de AMFPHP) et il vous suffira de rajouter :
format.amf { render :amf => @student }
Et voilà vous avez côté ActionScript votre objet tout chaud sans nécessité de désérialisation.
Et vous n'avez presque rien eu à faire côté Rails et finalement, c'est normal, la logique et la ressource sont les mêmes, seul le rendu change !
Comme vous pouvez le voir, ActionController se débrouille donc très bien pour faire la circulation entre la vue et les modèles.
Une des rares autres tâches qui incombe au controller est le contrôle des accès, si vous souhaitez vérifier que l'utilisateur connecté peut accéder à telle ou telle ressource, c'est à lui de s'en charger.
Imaginons dans notre exemple, que les étudiants puissent consulter les informations les concernant, mais que seul l'intendance puisse les éditer, ajouter, supprimer.
Ajoutons à notre controller la ligne suivante :
before_filter :authenticate , :exept => [:index, :show]
Cela signifie qu'avant toutes les méthodes sauf index et show,
on exécutera la méthode authenticate et que l'on ne fera la suite que si cette méthode renvoi true.
On peut donc rajouter à la fin de notre controller la méthode authenticate :
private
def authenticate
authenticate_or_request_with_http_basic do |username, password|
username == "foo" && password == "bar"
end
end
On notera que la méthode a été placée après le mot clé private afin de signifier que celle-ci n'est pas une action exécutable par le navigateur.
Notre action va ouvrir une boite de dialogue (si l'utilisateur n'est pas encore authentifier)
nous demandant notre login et mot de passe et renverra true si et seulement si ceux-ci sont "foo" et "bar"
N.B. : Evidement, en réalité, cette vérification s'effectuerait en base de donnée
Et voilà, désormais seul les personnes connaissant les logins et mot de passe ont accès à l'intégralité de l'application.
Ce sera tout pour ce soir, nous avons désormais vu comment écrire du Ruby, puis, comment fonctionnent les parties Model et Controller de Rails.
Il ne nous reste donc plus qu'une partie à aborder : les vues.
A bientôt pour ce dernier chapitre.
Commentaires
Ouawwwe
Ca a vraiement l'air puissant !
(j'ai même découvert ce que veut dire REST)
Quand j'aurai du temps : je rubyserai sur les rails
Merci pour cette introduction à Ruby et Rails.
Je vois enfin toute la puissance du frameworks !
Je monte dans le prochain train pour être moi aussi sur les rails -_^ !
Fil des commentaires de ce billet