2009-08-11 9 views
7

Je ne reçois pas REST avec Ruby on Rails, et j'espère que quelqu'un ici pourra me mettre d'accord. Imaginez que je construis un site qui garde trace des Widgets et des utilisateurs qui possèdent ces Widgets. Je serais donc un UsersController et un WidgetsController, et je pourrais obtenir une liste des widgets ou des utilisateurs avec les actions de l'indice:Rails: comment modéliser des requêtes RESTful à travers des associations?

GET /users 
GET /widgets 

et je pourrais obtenir un utilisateur ou un widget spécifique avec les actions montrent:

GET /users/id 
GET /widgets/id 

Que je comprends.

Où je suis confus est ce que la demande de RESTful utiliserais-je pour récupérer une liste de Widgets appartenant à un utilisateur spécifique? Est-ce une requête envoyée au UsersController ou au WidgetsController? Laquelle des 7 actions RESTful utilise-t-elle?

Est-ce une de ces situations dans lesquelles je crée une action personnalisée? J'avais l'impression que les actions personnalisées sont supposées être rares, mais cela semble être un cas d'utilisation plutôt courant.

Merci!

+0

Vous devriez vraiment écouter les réponses de Darrel Miller - le formatage de l'URI n'a rien à voir avec REST. Vous devriez peut-être aussi regarder quelques sujets REST sur StackOverflow qui l'expliquent plus en détail, ou regarder la thèse de Fielding. – aehlke

+1

Ma question ne portait pas sur les jolies URL - il s'agissait du contrôleur Rails que j'utiliserais pour gérer la requête, et quelle action serait utilisée. –

Répondre

4

L'URL pour la liste des widgets appartenant à un utilisateur foo ressemblerait à ceci:

/users/foo/widgets 

Vous avez alors le choix de la façon de faire vos URL pour chacun de ces widgets. Ceci est possible:

/users/foo/widgets/bar 

Mais je préfère ceci:

/widgets/bar 

Vos itinéraires se présente comme suit:

map.resources :users, :has_many => :widgets, :shallow => true 
map.resources :widgets, :has_many => :users, :shallow => true 

(Ceci est de la mémoire, j'ai foiré un ou plus de détails)

La méthode de contrôleur qui gère /user/foo/widgets est le index action du WidgetController. Il teste l'existence du paramètre user_id et restreint les widgets renvoyés en fonction de cela. (Ou l'utilisateur récupère foo et met @widgets à @user.widgets.)

Mise à jour: Il y a un bon aperçu de routage imbriqué qui répond à ma question initiale dans le Rails Guides.

Mise à jour 2 Oh oui, je voulais aussi faire un lien vers documentation.

+0

Ah cela fait beaucoup de sens. Je n'étais pas au courant de l'option: shallow pour map.resources. Merci! –

+0

Spot sur, mais la relation ici est "has_and_belongs_to_many" car un utilisateur peut avoir de nombreux widgets, et un widget peut appartenir à de nombreux utilisateurs. – askegg

+0

Vous associeriez probablement has_many et has_many: par le biais de relations à quelque chose comme un 'UserWidget' (nom boiteux) au lieu d'un' habtm' j'aurais pensé. – wombleton

1

Vous trouvez le processus de conception difficile car vous essayez de concevoir votre site en fonction d'un espace URL lorsque vous devez concevoir vos documents de contenu à la place.

Voici un ensemble de types de supports squelettiques répondant à vos besoins.

Type de support: application/xml vnd.yourcompany.collections +

<Collections> 
    <Widgets href="http://yoursite.com/{9BCCD309-644C-4fb8-A35E-A8B5E6AC4AE8}"/> 
    <Users href="http://yoursite.com/{BE57DC2D-8FE7-45e3-9362-AF5F607D62B6}"/> 
</Collections> 

Type de support: application/xml vnd.yourcompany.Widgets +

<Widgets> 
    <Widget href="http://yoursite.com/{4A7B5583-5D09-4cf3-9781-1084977769C0}"/> 
    <Widget href="http://yoursite.com/{0D6A72E8-6088-462c-A97A-70BC43E25475}"/> 
</Widgets> 

Type de support: application/vnd.yourcompany .Users + xml

<Users> 
    <User href="http://yoursite.com/{6321D95E-7EDB-46b8-9430-AB57EA067B06}"/> 
    <User href="http://yoursite.com/{0D6A72E8-6088-462c-A97A-70BC43E25475}"/> 
</Users> 

type de support: application/xml vnd.yourcompany.Widget +

<Widget> 
    <Property1>99</Property1> 
    <Property2>A Description</Property2> 
    <UsersOfWidget href="http://yoursite.com/{26995C10-CA1D-4f1f-9065-2246A8426DA7}"/> 
</Widget> 

Type de support: application/xml vnd.yourcompany.User +

<User> 
    <Name>Joe Smith</User> 
    <WidgetsOwnedByUser href="http://yoursite.com/{D718A2E6-6ADD-4d6e-A1E7-6DA68EDE0BD3}"/> 
</User> 

Il est évident que cet ensemble de types de médias est une des nombreuses solutions possibles à votre problème. Le problème sur lequel je veux attirer votre attention est que l'URL est en grande partie non pertinente. La manière dont les documents interagissent est importante. Lorsque vous regardez de cette façon, il n'est pas difficile de faire la distinction entre les widgets utilisés par un utilisateur et les utilisateurs qui utilisent un widget.

Maintenant, comment vous mapper cela à un ensemble de contrôleurs Rails est un tout autre problème. Le problème n'est pas qu'il est difficile de concevoir une solution RESTful, c'est juste que Rails ne semble pas cartographier très naturellement. Pas que j'ai beaucoup d'expérience avec Rails, alors prends ça pour ce que ça vaut. Je crois que vous devriez avoir un contrôleur par ressource et le fait que Rails essaye de serrer la liste d'une ressource et la ressource elle-même dans un contrôleur simple est une erreur. Les clients et le client sont deux ressources différentes à mon avis.

Édition: Ensemble possible d'URL pouvant lier ces ressources.

/Widgets 
/Users 
/Widget/1 
/User/99 
/Widget/1/UsersOfWidget 
/User/99/WidgetsOwned 

Je créer un contrôleur pour chacun de ces points de terminaison.

+1

Merci pour votre réponse, mais j'ai NFI de quoi vous parlez. Vous ne semblez même pas mentionner les widgets appartenant aux utilisateurs? Je cherchais une réponse comme "vous devriez créer une action personnalisée sur votre contrôleur" ou "vous devriez utiliser l'action index sur votre contrôleur Widgets et y faire XYZ". –

+0

:-) J'ai changé le nom de certains des éléments dans les deux derniers documents pour essayer de clarifier. Une convention que j'utilise dans les documents XML renvoyés par les interfaces RESTful est que si un élément a un href alors je peux suivre ce lien pour récupérer une représentation complète de cette ressource. Désolé, je n'avais pas réalisé que c'était si flou. Je suppose que j'ai passé trop de temps à regarder des documents comme celui-ci. –

+1

Je savais que vous étiez à la recherche d'un «comment ça marche dans Rails», mais ce que je veux savoir, c'est que penser en termes d'URL et d'actions sur les contrôleurs va rendre la tâche difficile problèmes dans la conception des interfaces RESTful. Je vais vous montrer les URL que j'utiliserais pour modéliser ce problème, à partir de cela il peut être évident de le faire dans Rails. –

1

Je pense que Darrel essaye de vous informer sur REST en général, car il dit que s'inquiéter trop de la conception d'URL pourrait être un signe que vous ne concevez pas vraiment RESTfully. Par exemple, comme le montre Darrel, votre représentation d'utilisateur pourrait porter les liens vers les widgets qu'il possède (ou un lien vers une URL qui effectue une recherche pour ces widgets propres à l'utilisateur).

Questions connexes