Segment Constraints
Sometimes you may want to add some constraints on the dynamic segments in a route. This is where the constraints
option that we saw earlier, comes into the picture. You can add restrictions on the segment keys by providing a constraint.
The following route matches only those URLs where slug
is a word consisting of letters between a
to z
.
get '/posts/:slug', to: 'posts#show', constraints: { slug: /[a-z]+/ }
# or you can also use a shorthand
get '/posts/:slug', to: 'posts#show', slug: /[a-z]+/
Here's another example: you may want to restrict the id
to three digits. For this, you can pass the :constraint
option as follows:
get 'images/:id', to: 'images#show', constraints: { id: /\d{3}/ }
This route would match paths such as /images/293
, but not /images/xyz
.
The above route can be succinctly expressed by passing the segment key itself.
get 'photos/:id', to: 'photos#show', id: /\d{3}/
Custom Constraint Logic
For more powerful constraints, you can pass a lambda to :constraints
which receives the request
object.
get '/posts/:slug', to: 'posts#show', constraints: ->(req) { req.params[:slug].length < 10 }
Rails also allows you to extract the complex logic to a class that has a matches(request)
method on it. Put that class inside the app/constraints
directory, and Rails will pick it up without a hitch.
get '/posts/:slug', to: 'posts#show', constraints: SlugLength.new
# app/constraints/slug_length.rb
class SlugLength
def matches?(request)
request.params[:slug].length < 5
end
end
Don't forget to return a boolean result from the method, depending on whether the URL matches the pattern.
Alright, that's enough about the segment keys. Next, we'll tackle the named routes, which give you sweet helper methods to generate the URLs on the fly.
If you have any questions or feedback, didn't understand something, or found a mistake, please leave a comment below or send me an email. You can also subscribe to my blog to receive future posts via email.