うちのいぬ Tech Blog

Tech Blog of Uchinoinu/My dog

How to use URL including dot (decimal point) in Rails 4.x

What I want to do

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

or

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

(You may say URL with parameter including dot is not good....)

How I failed

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

And start rspec

No route matches "/meats/score/5.4"

Like above, I got No route matches

Rails does not permit to use dot in URL without any configuration

As this article says、Rails does not permit it.

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.

Then how to resolve - Using constraints , set restriction as regular expression

Constraints mean....

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

constraint against parameter

example of constraints

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

Line above means /photos/AB1

Very easy way to use dot in URL

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

This permit any character except slash /

Permit to use dot with limited format

Number + dot + Number

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

like 2.2.2.2.2.2.2.2

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

like api/v2.1.1/foo

(You may say this is bad way of api versioning....)

You can use constraint below

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

References