9
votes

I am trying to create a Rails route that has optional parameters as well as varying order.

This question describes a similar problem: Routes with multiple, optional, and pretty parameters

I am trying to create routes that have map filters in them, like parameters but without the parameter URL styling. The idea is to have them look like

/search/country/:country/
/search/country/:country/state/:state/
/search/country/:country/state/:state/loc/:lat/:long/

but you should also be able to search with

/search/state/:state/
/search/state/:state/country/:country/
/search/loc/:lat/:long/

I know that I could write complex regex statements with route globbing - however I'm wondering if there is a way to have multiple optional route parameters with unspecified order, something like

/search/( (/country/:country)(/state/:state)(/loc/:lat/:long) )

Thanks!

1
I think you already have the best solution for your problem i.e. regexp - RAJ
One other way, maybe not the best, would be to just have the multiple entries in your routes.rb - RPinel
I used Regex to solve this problem but am still curious if there is a desire for the Rails5 protocol to support multiple optional parameters. You should be able to specify the delimiter(s) and choose between explicit and underordered. - Eric Walsh
@RPinel Yes this is a solution but it doesn't feasibly with a lot of parameters since N parameters would correspond to N! amount of routes in your routing doc. In that situation Regex would be an obvious choice! - Eric Walsh

1 Answers

3
votes

You can use the constraints with lambda to use multiple search options:

  search_options = %w(country state loc)
  get('search/*path',:to => 'people#search', constraints: lambda do |request|
             extra_params = request.params[:path].split('/').each_slice(2).to_h
             request.params.merge! extra_params # if you want to add search options to params, you can also merge it with search hash
             (extra_params.keys - search_options).empty?
           end)

You can make a different lambda for more complex routes