A forma original desta resposta é muito diferente e pode ser encontrada aqui . Apenas prova de que há mais de uma maneira de esfolar um gato.
Atualizei a resposta desde então para usar namespaces e redirecionamentos 301 - em vez do padrão 302. Agradecemos a pixeltrix e Bo Jeanes pela solicitação sobre essas coisas.
Você pode usar um capacete muito forte, porque isso vai surpreender sua mente .
A API de roteamento do Rails 3 é super maliciosa. Para escrever as rotas para sua API, conforme seus requisitos acima, você precisa apenas disso:
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
Se sua mente ainda estiver intacta após esse ponto, deixe-me explicar.
Primeiro, chamamos de namespace
que é super útil quando você deseja um monte de rotas com escopo definido para um caminho e módulo específicos com nomes semelhantes. Nesse caso, queremos que todas as rotas dentro do bloco namespace
tenham o escopo definido para os controladores dentro do Api
módulo e todas as solicitações de caminhos dentro dessa rota serão prefixadas api
. Pedidos como /api/v2/users
, você sabe?
Dentro do espaço para nome, definimos mais dois espaços para nome (woah!). Desta vez estamos definindo o namespace "v1", de modo que todas as rotas para os controladores aqui vai estar dentro do V1
módulo dentro do Api
módulo: Api::V1
. Ao definir resources :users
dentro dessa rota, o controlador estará localizado em Api::V1::UsersController
. Esta é a versão 1, e você chega lá fazendo solicitações como /api/v1/users
.
A versão 2 é apenas uma pequena pouco diferente. Em vez de o controlador atender Api::V1::UsersController
, ele está agora Api::V2::UsersController
. Você chega lá fazendo pedidos como /api/v2/users
.
Em seguida, a match
é usado. Isso corresponderá a todas as rotas da API que vão para coisas como /api/v3/users
.
Esta é a parte que eu tive que procurar. A :to =>
opção permite que você especifique que uma solicitação específica deve ser redirecionada para outro lugar - eu sabia disso -, mas não sabia como redirecioná-la para outro lugar e passar uma parte da solicitação original junto com ela .
Para fazer isso, chamamos o redirect
método e passamos uma string com um %{path}
parâmetro interpolado especial . Quando chega uma solicitação que corresponde a esta final match
, ele interpola o path
parâmetro no local %{path}
dentro da string e redireciona o usuário para onde eles precisam ir.
Finalmente, usamos outro match
para rotear todos os caminhos restantes prefixados /api
e redirecioná-los para /api/v2/%{path}
. Isso significa que solicitações como /api/users
irão para /api/v2/users
.
Eu não conseguia descobrir como obter /api/asdf/users
para corresponder, porque como é possível determinar se isso é suposto ser um pedido para /api/<resource>/<identifier>
ou /api/<version>/<resource>
?
Enfim, foi divertido pesquisar e espero que ajude você!