La forme originale de cette réponse est très différente et peut être trouvée ici . Juste la preuve qu'il y a plus d'une façon d'écorcher un chat.
J'ai mis à jour la réponse depuis pour utiliser les espaces de noms et utiliser les redirections 301 - plutôt que la valeur par défaut de 302. Merci à pixeltrix et Bo Jeanes pour les invites sur ces choses.
Vous voudrez peut-être porter un casque vraiment solide, car cela va vous épater .
L'API de routage Rails 3 est super méchante. Pour écrire les routes de votre API, conformément à vos exigences ci-dessus, vous avez juste besoin de ceci:
namespace :api do
namespace :v1 do
resources :users
end
namespace :v2 do
resources :users
end
match 'v:api/*path', :to => redirect("/api/v2/%{path}")
match '*path', :to => redirect("/api/v2/%{path}")
end
Si votre esprit est toujours intact après ce point, laissez-moi vous expliquer.
Tout d'abord, nous appelons namespacece qui est très pratique lorsque vous voulez un tas de routes étendues à un chemin et un module spécifiques portant le même nom. Dans ce cas, nous voulons que toutes les routes à l'intérieur du bloc pour notre namespacesoient étendues aux contrôleurs dans le Apimodule et toutes les demandes aux chemins à l'intérieur de cette route seront préfixées avec api. Des demandes telles que /api/v2/users, tu sais?
Dans l'espace de noms, nous définissons deux autres espaces de noms (woah!). Cette fois , nous définissons l'espace de noms « v1 », donc tous les itinéraires pour les contrôleurs ici seront à l' intérieur du V1module à l' intérieur du Apimodule de : Api::V1. En définissant à l' resources :usersintérieur de cette route, le contrôleur sera situé à Api::V1::UsersController. C'est la version 1, et vous y arrivez en faisant des requêtes comme /api/v1/users.
La version 2 est seulement un petit différent bits. Au lieu que le contrôleur le servant soit à Api::V1::UsersController, il est maintenant à Api::V2::UsersController. Vous y arrivez en faisant des demandes comme /api/v2/users.
Ensuite, a matchest utilisé. Cela correspondra à toutes les routes d'API qui vont à des choses comme /api/v3/users.
C'est la partie que je devais rechercher. L' :to =>option vous permet de spécifier qu'une demande spécifique doit être redirigée ailleurs - je le savais bien - mais je ne savais pas comment la faire rediriger vers un autre endroit et transmettre un morceau de la demande d'origine avec elle .
Pour ce faire, nous appelons la redirectméthode et lui passons une chaîne avec un %{path}paramètre interpolé spécial . Lorsqu'une requête correspond à cette finale match, elle interpole le pathparamètre à l'emplacement de l' %{path}intérieur de la chaîne et redirige l'utilisateur vers où il doit aller.
Enfin, nous en utilisons un autre matchpour acheminer tous les chemins restants préfixés par /apiet les rediriger vers /api/v2/%{path}. Cela signifie que les demandes comme /api/usersiront à /api/v2/users.
Je ne savais pas comment faire /api/asdf/userscorrespondre, car comment déterminer si cela est censé être une demande à /api/<resource>/<identifier>ou /api/<version>/<resource>?
Quoi qu'il en soit, c'était amusant de rechercher et j'espère que cela vous aidera!