Petit problème en REST

Bonjour

Je m’intérese comme vous tous à REST.

J’ai une question simple mais je n’ai pas trouvé de réponse …

La plupart de mes actions dans mes controller charge généralement
avant d’afficher la vue, plusieurs ressources.
Je fais plusieurs find :

@user=User.find(1)
@msgs=User.msgs.find(:all)

Par exemple, sur une page j’affiche le profile d’un utlisateur et la
liste de ses messages.

Comment ce genre action peuvent être écrite en respectant
l’architecture REST.

je vais avoir deux controller différent pour chaque resource (user,
msg)

Mais dans mes actions compliquées, je ne peux pas utiliser les actions
REST car je ne peux pas appeler une action depuis une autre action ?

Je vous remercie par avance de votre retour d’expérience sur ce genre
de cas banal dès qu’on sort de l’exemple classique :wink:

Antoine

Bonjour,

La difficulté est en effêt de sortir de l’exemple CRUD simpliste.

Je pense que tu trouvera quelques éléments de réponse dans mon post (
http://blog.lachaise.org/?p=3), avec en prime un plugin qui peut faire
gagner pas mal de temps quand on veut coller à REST.

Philippe.

J’ai lu avant d’écrire mon post…

Je ne suis pas sur d’avoir saisi la solution dans ton post, comment tu
fais ?

Par ailleurs, si d’autres personnes ont des retours sur la question je
suis preneur :slight_smile:

antoine

On 16 déc, 13:55, “philippe lachaise” [email protected]

On Dec 16, 2007 5:58 PM, Antoine [email protected] wrote:

Comment ce genre action peuvent être écrite en respectant
l’architecture REST.

Tu fais ton @user = User.find(params[:id]) et après dans ta vue tu
appelles les msgs de ton user @user.msgs, tu peux même le faire dans
ton controleur avec @[email protected] je ne vois pas où est le problème
:?
Tu peux toujours mettre ton @msgs dans ton format html pour économiser
genre:
format.html{@[email protected] etc} si t’en as besoin uniquement dans la
vue html.

Mais dans mes actions compliquées, je ne peux pas utiliser les actions
REST car je ne peux pas appeler une action depuis une autre action ?

utiliser une action depuis une autre action? Je ne vois pas trop ce
que tu veux dire en général les actions sont utilisées par les vues
c’est tout. Tu peux écrire des fonctions dans tes models à appliquer
durant les actions (avec les filtres after before etc par exemple).

En gros le REST ça permet de bénéficier d’une API prévisible donc dans
ton cas permettre de faire des Get /users/:id et Get /msgs/:id ou Get
/users/:id/msgs (voir le poste de Philippe pour ce cas). Si tu peux
faire ça dans ton appli c’est bon t’es RESTful et dans tes vues t’as
parfaitement le droit de faire appelle à d’autres models pour les
afficher ou même les updater.

Je ne suis pas sur d’avoir saisi la solution dans ton post, comment tu
fais ?

Vu que j’ai mis un certain temps avant d’en arriver à ce que j’expose il
n’est pas étonnant à ce que ça ne soit pas instantanément lulmineux :wink:

Puis les chose le plus simples sont pas toujours faciles à exposer ; je
pense que mon post n’est pas 100% clair et j’envisage de le revoir après
une
seconde phase de maturation du plugin (BTW, il évolue chaque jour).

Pour aller à l’essentiel, je recense les as de figure (par la pratique)
et
j’utilise la métaprogrammation pour matcher le besoin de tel ou tel
controlleur à du code généré via des paramères.

Dans le cas de base, qui correspondrait au tien, le controller
Users::MsgsController verrait ses méthodes CRUD générées par
“restful_methods”, les variable d’instances @user, @msgs (index) et @msg
(show) étant déduites du nom du controller.

Cas plus subtil (mais qui se présente vite), si je veux regagner un
degré de
liberté tout en restant “nested” à 2 niveaux (au delà c’est vite la
pagaille) je peux forcer le nom du modèle parent à être distinct de
celui
déduite :

:parent_model => :msg_category # (exemple au pif)

Du coup j’aurais le variables :
@msg_category, @user, @msgs (index) et @msg (show)

Avec des URL du genre : /users/1/msg/4?msg_category_id=7

Hope it helps :slight_smile:

Antoine a écrit :

Mais dans mes actions compliquées, je ne peux pas utiliser les actions
REST car je ne peux pas appeler une action depuis une autre action ?

Moi je pense que tu peux. Comme dit Patrick A., l’important pour
être Rest c’est l’url qui va permettre d’arriver à la méthode de ton
controlleur, ainsi que le verbe HTTP associé. une fois que t’est dans la
méthode tu fait ce que tu veux, même appeler une autre méthode du même
controlleur.
Par contre pour appeler une méthode d’un autre controlleur, je vois pas
d’autre solution que redirect_to, mais je suis novice donc je me trompe
peut-être.
Si c’est juste pour afficher un contenu ou partiel, là tu peux le faire
avec render sans problème.

Je ne sais pas si ton problème n’est pas en fait celui des routes
imbriquées.
Pour ton cas dans configuration/routes.rb, il faudrait écrire
map.resources users do |user|
user.resources messages
end

Si tu n’es pas déjà sur 2.0, sinon tu as une syntaxe avec :has_many.
Ca te génère les routes qui vont bien, et puis aussi des helpers très
pratique, genre
users_path, user_path(@user), edit_user_path(@user),
new_user_path(@user).
et les même en remplaçant path par url (dans ce cas tu as l’url complète
et non juste le chemin depuis la racine de l’appli).

Pour tester tes routes si t’es pas déjà sous rails 2.0:
script/console
rs=ActionController::Routing::Routes
puts rs.routes

Je ne sais pas si tu connais BEAST, mais ce forum open source en rails
est une très bonne source d’inspiration.
Donc tu peux le télécharger et le décortiquer, à loisir en le comparant
à tes besoins. Il ne fait pas plus de 500 lignes, et on y trouve des
forums, des topics, des utilisateurs, des modérateurs, des admins et des
messages. Tout ça en restful.
Donc à exporter sur ta machine via svn:
http://svn.techno-weenie.net/projects/beast/

Bravo Jean-Baptiste, c’est le genre de clarification dont il y a grand
besoin en ce moment où beaucoup de gens (même en dehors de Rails)
tatonnent
autour de REST.

Le problème de Restful c’est sa nature lumineusement simple, mais dont
la
mise en pratique découvre beaucoup de non-dit.

CRUD = REST est une simplification utile dans la démarche de
compréhension
mais on n’arrive a rient avant de la dépasser.

Il peut être utile de prendre de la hauteur par rapport à notre petit
monde
de codeurs et d’assayer d’envisager ce pattern sous d’autre éclairages :

Ceux qui, lorsqu’ils ne codent pas, font de la musique ou bien écrivent
des
vers (ou peignent ou cuisinent :wink: savent qu’on fait de belles choses
lorsqu’on a assimilé des règles rigides et qu’on a découvert comment
tricher
utilement.

L’avantage de la règle d’apparence naïve est qu’elle permet facilement
de ne
pas trop s’égarer et d’éviter la tentation de réinventer trop de roues.

Mais comme elle est toute simple, ses limites sont également faciles Ã
percevoir (CRUD et après je fais quoi ? Mais rien. Rien du tout !).
Ainsi on
se rend assez vite compte lorsqu’il faut vraiment s’aventurer en dehors
du
cadre. La solution n’est pas subtilement cachée dans une API absconce,
il
faut aller la trouver, c’est aussi simple que ça.

Ca donne quoi alors en REST ?

Mon expérience,c’est qu’on s’accroche d’abord le plus possible à la
logique
CRUD, avec la plupart du temps des ressources imbriquées sur DEUX
niveaux
seulement. Ca permet déjà pas mal de choses pour tout ce qui est de
nature
hiérachique.

Et quand ça coince, on commence à abatardir le modèle en s’éloignant du
REST
pur pour flirter un peu avec un style RPC (i.e. d’autres méthodes que
les 7
méthodes sacrées :wink:

Et, comme le souligne Jean-Baptiste, l’API REST de notre appli n’a pas Ã
se
calquer servilement sur les modèles Rails (SGDB).
Une relation entre deux ressources peut très bien être de nature
belongs_to/has_many vue de l’exterieur et n’avoir aucun rapport avec ce
qui
se passe, dans l’appli, au niveau des modèles.

L’énoooorme avantage de coller, tant que faire se peut, au modèle idéal
c’est que, a mesure que ça devient une seconde nature, tous les autres
aspects de l’appli sont naturellement conçus en pensant Restful et d’un
coup
tout s’enclique.

Par Exemple, j’avais besoin d’une mécanique de Breadcrumbs souple et
robuste
pour la navigabilité de mon site qui présente beaucoup de cheminements
possibles. Et bien, ça s’emboite à merveille avec Restful !
(publication du code à la rentrée).

Dernière pensé donc, avant de coucher le pingouin jusqu’à l’année
prochaise
: REST = CRUD est la règle, il faut apprendre à ne PAS la respecter :wink:

So you want to write a fu-u-gue ?

Bonne fêtes à ceux qui s’attardent encore ici :slight_smile:

Philippe.


Web development is coming of age with Ruby on Rails
blog.lachaise.org

Merci beaucoup Sébastien pour le lien vers le projet BEAST, je vais le
décortiquer…

Bonne journée,

Antoine

Bonjour à tous,

Je vais essayer de réagir en quelques lignes à cette question que
beaucoup se posent en s’intéressant à REST :

  • Quel est le lien entre CRUD et REST?

La première chose à préciser : REST EST DIFFERENT DE CRUD.

En effet, REST n’a pas de corrélation directe avec la base de donnée.
REST est un style d’architecture, une manière d’organiser le code, les
URLs et de manière générale l’application web que vous développez, EN
NON PAS un manière d’accéder aux enregistrement de votre base de
donnée.

Dans les nombreux exemples à propos de REST on parle bien de CRUD,
oui. Il y a bien une analogie entre les deux. Mais il est important de
comprendre que les ressources RESTful et les objets du modèle (=
tables dans la db) ne sont pas systématiquement liés.

Pour faire référence au problème d’Antoine, ce n’est pas parce qu’on
accède à la ressource User qu’on ne peut pas afficher les messages qui
lui sont liés. Ce n’est pas non plus parce qu’on a des objets messages
dans la db qu’on aura les 7 actions restful pour cet objet.

Dans les cas des “User” et des “Messages”, on peut imaginer que les
messages ne soient lisibles uniquement sur la page du “User”, nous
n’avons donc pas besoin des actions “index” ni “show” dans le
contrôleur “message”.

Imaginons, que le formulaire pour créer des messages soit présent dans
la vue de “User” et que les messages soient éditables en in-place
toujours depuis cette vue. Il n’y aura plus d’action “new” et “edit”
dans le contrôlleur.

Seules resteront les actions “create”, “update” et “delete”. Elles
interagiront bien avec le modèle correspondant (“Message”) dans la db.
Il y a donc bien une corrélation (d’où l’analogie de REST avec CRUD).
Mais cette corrélation n’est pas exclusive. Si on voulait tagger le
message à sa création, ou pourrait créer l’objet Tag et l’associer à
Message dans l’action new du contrôleur “Messages”.

Pour récapituler : On peut trouver des analogies entre REST et CRUD
mais il ne faut pas confondre les deux. La philosophie de REST n’est
pas de mapper la base de données mais de créer une structure pour la
création, l’accès, la mise à jour et la suppression de l’information.

On pourrait encore en parler beaucoup et j’écrirai probablement sur le
sujet d’ici peu sur Frailers.net. N’hésitez pas à réagir en
m’indiquant si ces quelques considérations on éclairé votre démarche
RESTful. :slight_smile:

Jean-Baptiste

www.frailers.net