Search code examples
regexrubyroutesroda

Ruby routes URI regex


I have blog web application on Roda where links have the following URL format: example.com/posts/<id>/<slug>.

For example example.com/posts/1/example-blog-post.

What I want to achieve is to redirect user to example.com/posts/1/example-blog-post in case he either visits:

  1. example.com/posts/1 or
  2. example.com/posts/1/ (note last backslash)

That's what I got in routes so far:

r.on /posts\/([0-9]+)\/(.*)/ do |id, slug|
  @post = Post[id]

  if URI::encode(@post[:slug]) == slug
    view("blogpage")
  else
    r.redirect "/posts/#{id}/#{@post[:slug]}"
  end
end

With this code:

  1. example.com/posts/1 - FAILS
  2. example.com/posts/1/ - OK

Can I satisfy both conditions?


Solution

  • You could wrap the forward slash followed by the second capturing group in an optional non capturing group:

    posts\/([0-9]+)(?:\/(.*))?
    

    Explanation

    • posts\/ Match posts/
    • ([0-9]+) Capture group 1, match 1+ digits
    • (?: Non capture group
      • \/(.*) Match / and capture in group 2 0+ times any char except a newline
    • )? Close non capture group and make it optional

    Regex demo