うちのいぬ Tech Blog

Tech Blog of Uchinoinu/My dog

Rails4.x で 少数点(. ドット)を含めたURLを使いたい場合

やりたいこと

GET http://domain.jp/api/2.1.1/users

とか

GET http://domain.jp/meats/score/21293.02

とか、少数点、というかドットが入った形のURLを使う方法についてです。

(そもそもドットの入った値はURLに入れないほうが良いのかもしれませんが...)

失敗例

config/routes.rbに以下の様に指定。

get 'meats/score/:score' => 'meats#score'

routing_specを書きます。

it "routes to #score" do
  expect(:get => "/meats/score/5.4").to route_to("meats#score", score: "5.4", format: "json")
end

rspecを叩くと

No route matches "/meats/score/5.4"

この様に No route matches 扱いになります。

Railsはデフォルトではparameterにdotを受け付けない

こちらに記載されている通り、ドットをparameterに含めることは許容されていないようです。

By default the :id parameter doesn't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within an :id add a constraint which overrides this - for example id: /[^\/]+/ allows anything except a slash.

対応 - Constraintsで、paremeterを正規表現で指定する

Constraintsの意味(抜粋)

something that limits your freedom to do what you want [= restriction]

日本語にすると制約とか制限とか

なので、この場合には、 Parameterに対する制約 ということになります。

constraintsの使用例

resources :photos, constraints: { id: /[A-Z][A-Z][0-9]+/ }

↑だと /photos/AB1 とかになります

手っ取り早くパラメータにドット(小数点)を許容する方法

get 'meats/score/:score' => 'meats#score', score: /[^\/]

スラッシュ / 以外を許容します

形式を限定して小数点(ドット)許容する

数字+ドット+数字 の場合

get 'meats/score/5.1' => 'meats#score', constraints: { score: /\d+\.\d+/ }

2.2.2.2.2.2.2.2 の様な感じの場合

get 'meats/score/5.1' => 'meats#score', constraints: { score: /\d+(\.\d+)*/ }

api/v2.1.1/foo とかの場合

(そもそもURLを使ったapiのバージョニングがいいかどうかは置いておいて...)

↓の様なconstrainsを使うといいかと思います。

, constraints: { api_version:  /v\d+(\.\d+)*/ }

References