1. ホーム
  2. ruby-on-rails

[解決済み] RailsルーティングのAPIバージョン管理

2022-05-14 09:48:13

質問

StripeのようにAPIをバージョンアップしようとしています。以下は、最新のAPIバージョンが2であることを示します。

/api/users は301を /api/v2/users

/api/v1/users バージョン1のユーザインデックスを200件返します。

/api/v3/users は 301 を返します。 /api/v2/users

/api/asdf/users は 301 を /api/v2/users

つまり、基本的にバージョンを指定しないものは、指定したバージョンが存在しない限り最新のものにリンクし、それにリダイレクトするようにします。

今のところこんな感じです。

scope 'api', :format => :json do
  scope 'v:api_version', :api_version => /[12]/ do
    resources :users
  end

  match '/*path', :to => redirect { |params| "/api/v2/#{params[:path]}" }
end

どのように解決するのですか?

この回答の原形は全く異なるものであり、ここにあります。 . 猫の皮を剥ぐ方法は1つではないという証拠です。

名前空間を使用し、デフォルトの302ではなく301リダイレクトを使用するように、回答を更新しました。これらのことを促してくれた pixeltrix と Bo Jeanes に感謝します。


をつけるといいかもしれません。 本当に のヘルメットをかぶったほうがいいかもしれません。 <強い あなたの心を吹き飛ばす .

Rails 3のルーティングAPIは超優秀です。上の要件に従ってAPIのルートを書くには、これだけが必要です。

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

ここまで来てもまだ心が残っているのなら、説明しましょう。

まず namespace を呼び出します。これは特定のパスとモジュールにスコープされた、似たような名前のルートがたくさん欲しいときにとても便利です。この場合、ブロック内のすべてのルートを namespace のブロック内のすべてのルートを Api モジュール内のコントローラにスコープされ、 このルート内のパスへのすべてのリクエストのプレフィクスとして api . のようなリクエストは /api/v2/users というようなリクエストもあります。

名前空間の内部では、さらに2つの名前空間を定義しています(woah!)。今回は "v1" 名前空間を定義しているので、ここのコントローラ用のルートはすべて V1 モジュールの中にあります。 Api モジュールの中に Api::V1 . を定義することで resources :users を定義することで、コントローラは Api::V1::UsersController . これはバージョン 1 で、次のようなリクエストをすることでそこに到達します。 /api/v1/users .

バージョン 2 はあくまで の小さな が少し違うだけです。それを提供するコントローラは Api::V1::UsersController にあるのではなく、今は Api::V2::UsersController . のようなリクエストをすることで、そこに到達することができます。 /api/v2/users .

次に match が使われます。などに向かうすべてのAPIルートにマッチします。 /api/v3/users .

ここが調べるのに苦労した部分です。その :to => オプションは特定のリクエストを別の場所にリダイレクトするよう指定することができます -- それだけは知っていました -- しかし、別の場所にリダイレクトさせ、オリジナルのリクエストの一部を一緒に渡す方法を知りませんでした。

これを実現するために、私たちは redirect メソッドを呼び出し、文字列を特別に補間した %{path} パラメータで文字列を渡します。この最終的な match にマッチするリクエストが来た場合、それは path パラメータを %{path} の中の文字列に変換し、ユーザが行くべき場所にリダイレクトします。

最後に、別の match で始まる残りのすべてのパスをルーティングするために /api にリダイレクトし /api/v2/%{path} . これは、以下のようなリクエストを意味します。 /api/users のようなリクエストは /api/v2/users .

を取得する方法が分かりませんでした。 /api/asdf/users へのリクエストであるかどうかをどのように判断するのでしょうか? /api/<resource>/<identifier> へのリクエストなのか /api/<version>/<resource> ?

とにかく、これは調べるのが楽しかったですし、あなたのお役に立てれば幸いです。