ruby on rails and Imbrication RESTfully des itinéraires de ressources avec des identifiants uniques




rails api gem (4)

Vous cherchez des routes peu profondes. Comme vous l'avez fait remarquer, l'idée d'avoir une route profondément imbriquée pour des choses comme des créations, des mises à jour est inutile puisque vous ciblez directement l'enregistrement désiré.

Je n'ai jamais vraiment fait le routage peu profond donc je vais passer sur l'épisode railscast où Ryan Bates l'explique probablement mieux que je pourrais: 139 Nested Resources .

Edit: Vous pouvez lire un peu plus sur les guides de routage 3.8.4 .

Dans mon application Rails, j'ai une relation has_many assez standard entre deux entités. Un Foo a zéro ou plus Bars ; une Bar appartient à exactement un Foo . Foo et Bar sont tous deux identifiés par une seule valeur d'ID entier. Ces valeurs sont uniques dans l'ensemble de leurs instances respectives.

La barre dépend de Foo: cela n'a aucun sens d'avoir une barre sans Foo.

Il existe deux façons de référencer RESTfully les instances de ces classes. Étant donné un Foo.id de "100" et un Bar.id de "200":

  1. Référence chaque Foo et Bar à travers leurs propres routes d'URL "top-level", comme ceci:

    • / foo / 100
    • / bar / 200
  2. Barre de référence en tant que ressource imbriquée via son instance de Foo:

    • / foo / 100
    • / foo / 100 / bar / 200

J'aime les routes imbriquées dans # 2 car il représente plus étroitement la relation de dépendance réelle entre les entités. Cependant, cela semble impliquer beaucoup de travail supplémentaire pour très peu de gain. En supposant que je connais un Bar particulier, je n'ai pas besoin d'être informé d'un Foo particulier; Je peux dériver cela du Bar lui-même. En fait, je devrais probablement valider le Foo routé partout où je vais (de sorte que vous ne pourriez pas faire / foo / 150 / bar / 200, en supposant que Bar 200 n'est pas assigné à Foo 150). En fin de compte, je ne vois pas ce que cela m'apporte.

Alors, existe-t-il d' autres arguments pour ou contre ces deux schémas de routage?

Point de clarification

Je suis surtout préoccupé par les mises à jour / spectacles / suppressions de RESTful à des barres particulières. Pour obtenir une liste de Bars pour un Foo spécifique (qui est généralement l'action "index" dans Rails), il est parfaitement logique d'avoir une route imbriquée telle que / foo / 100 / bar. La page de cette route pourrait tout aussi bien être liée à / bar / x que / foo / 100 / bar / x.


Answer #1

Personnellement, si chaque barre dépend d'un Foo, l'option # 2 a plus de sens. Par exemple, si Foo est un blog et Bar est un post, il est beaucoup plus logique d'accéder à un article particulier sur example.bloghosting.com/blog/1/post/2 than example.bloghosting.com/post/21 .

Faites-le avec la dernière version de Rails:

class Food < ActiveRecord::Base
    has_many :bars
end

class Bar < ActiveRecord::Base
    belongs_to :foo
end

Ensuite, dans le routeur Rails (/config/routes.rb):

map.resources :foos do |foo|
    foo.resource :bars
end

Pour plus d'informations, consultez Rails Routing à partir de la documentation de l'API Outside In et Rails .


Answer #2

Comme vous le savez déjà, chaque objet doit avoir une adresse unique. Je suggérerais que plus l'adresse est courte et facile, mieux cela vaudra pour toutes les personnes impliquées - votre code de routage, vos applications clientes, etc. Si vous pouvez identifier une barre par son identifiant unique, je ne le spécifierais probablement que dans l'URL.

Cependant, vous n'avez pas besoin de perdre l'information sémantique sur l'affectation du Bar à un Foo. Cela peut faire partie de la représentation.

En tant qu'amélioration, vous pouvez autoriser le client à adresser la barre 200 sous la forme / foo / 100 / bar / 200, puis rediriger vers l'adresse / bar / 200 / préférée, en utilisant, par exemple, une réponse 303 ("Voir autre").


Answer #3

L' imbrication peu profonde de Rails nous donne le meilleur des deux mondes: elle nous permet d'avoir des routes spécifiques à Foo où cela a du sens (créer, nouveau, index) et des routes uniquement pour la barre (montrer, éditer, mettre à jour, détruire).

Malheureusement, le nouveau routage DSL dans Rails 3 (que j'utilise) ne supporte pas encore le routage peu profond (à partir de la version bêta 3). Il semble être dans les travaux, mais ce n'est pas fonctionnel pour aujourd'hui.

Cependant, vous pouvez faire semblant en mappant la ressource deux fois, une fois imbriquée et une fois superficielle:

resources :foo do
  resources :bar, :only => [:index, :new, :create]    
end
resources :bar, :only => [:show, :edit, :update, :destroy]

Cela va me dépanner jusqu'à ce que l'option: shallow soit de nouveau opérationnelle.





routes