13

I have a problem, recently the name of a controller changed.

I changed the routes file to accept calls using the old controller name, for people with bookmarks referencing the old name:

get '/old/about', to: redirect('/new/about')
get '/old/report/:client', to: redirect('/new/report/%{client}')
get '/old/:sub_path', to: redirect('/new/%{sub_path}')

that works fine. But for calls with query string it blocks it to /report/200. for example:

/old/report/200?c_id=257&end=2013-10-19&num_results=294540&start=2013-10-13

it cuts the url to:

old/report/200

and shows me an error because of the lack of parameters. Do you know what can I do? (I thought the :sub_path line in the routes would help but not) :(

2

4 Answers 4

21

Modify redirect to use the path: option to preserve the querystring:

- get '/old/about', to: redirect('/new/about')
+ get '/old/about', to: redirect(path: '/new/about')

This is demonstrated in the API docs for redirect, see http://api.rubyonrails.org/classes/ActionDispatch/Routing/Redirection.html#method-i-redirect

Sign up to request clarification or add additional context in comments.

Comments

12

The question mention by Matt helped me to figure out my answer (thanks a lot!). It was a slightly different for my specific case. Im leaving the answer that worked for me for future reference.

match "/old/report/:client" => redirect{ |params, request| "/new/report/#{params[:client]}?#{request.query_string}" }

1 Comment

I would modify it a bit to check if request.query_string present as current solution always will add '?' to the bottom.
3

Building on Alejandra's answer, more verbose but without the ? if there's no query string:

get "/old/report/:client", to: redirect{ |params, request| ["/new/report/#{params[:client]}", request.query_string.presence].compact.join('?') }

So /old/report/:client?with=param will become /new/report/:client?with=param, and /old/report/:client will become /new/report/:client.

Comments

0

The existing answers work perfectly, but are not quite suitable for keeping things DRY — there is a lot of duplicate code once you need to redirect more than one route.

In this case, a custom redirector is an elegant approach:

class QueryRedirector
  def call(params, request)
    uri = URI.parse(request.original_url)
    if uri.query
      "#{@destination}?#{uri.query}"
    else
      @destination
    end
  end

  def initialize(destination)
    @destination = destination
  end
end

Now you can provide the redirect method with a new instance of this class:

get "/old/report/:client", to: redirect(QueryRedirector.new("/new/report/#{params[:client]}"))

I have a written an article with a more detailed explanation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.