1

I want to set this routing:

http://localhost:3000/sites/search/www.google.com

My config/routes.rb

resources :sites, only: [:index] do
  collection do
    get 'search/:url', to: 'sites#search'
  end
end

Routes:

GET    /v1/sites/search/:url(.:format)                          v1/sites#search {:format=>:json}

Controller

def search
  @url = params[:url]
end

But when I access from URI

http://localhost:3000/sites/search/www.google.com

Got

{
    "status": 404,
    "error": "Not Found",
    "exception": "#<ActionController::RoutingError: No route matches [GET] \"/sites/search/www.google.com\">",
    "traces": {
        "Application Trace": [],
oiio
  • 13
  • 4
  • For anything with a `.` in the path you'll need to use `*url` to grab it all or else the `(:format)` part will grab things like `.com`. – tadman Nov 25 '20 at 02:47
  • @tadman You are right! `get 'search/*url', to: 'sites#search'` works well. Could you write it as an answer? – oiio Nov 25 '20 at 02:52
  • Oh wait, I got an URL as `"www.google"` but not a full domain. – oiio Nov 25 '20 at 02:55
  • You may need to tack on `params[:format]`. If you can get it working, add a self-answer with the full method. – tadman Nov 25 '20 at 03:10
  • Should I do as `@url = params[:url] + '.' + params[:format]` ? It can show all the things. – oiio Nov 25 '20 at 03:40
  • It's worth a shot, yeah. Just realized you can also [disable `:format`](https://stackoverflow.com/questions/4579652/disable-format-routes-in-rails3). – tadman Nov 25 '20 at 03:41

1 Answers1

1

A . in a url has a specific meaning, and hence can't be used directly. To handle all possible URLs in your queries, you should encode the urls before sending them in your query parameters. So

http://localhost:3000/sites/search/www.google.com

will become

http://localhost:3000/sites/search/www%2Egoogle%2Ecom

Edit:
There's actually a better solution that is more Railsy. By default, Rails expects the . to be a separator in your URL. However Rails allows you to define the format expected for your parameters using constraints.

So if you update your route definition by adding a regex constraint for the url parameter,

get 'search/:url', to: 'sites#search', constraints: { url: /.*/ }

you should now be able to handle even URLs like,

http://localhost:3000/sites/search/www.google.com
Anuj
  • 1,912
  • 1
  • 12
  • 19