How do I do a redirection in routes.rb passing on

2019-04-19 05:14发布

问题:

I had a functioning redirect in my routes.rb like so;

match "/invoices" => redirect("/dashboard")

I now want to add a query string to this so that, e.g.,

/invoices?show=overdue

will be redirected to

/dashboard?show=overdue

I've tried several things. The closest I have got is;

match "/invoices?:string" => redirect("/dashboard?%{string}")

which gives me the correct output but with the original URL still displayed in the browser.

I'm sure I'm missing something pretty simple, but I can't see what.

回答1:

You can use request object in this case:

match "/invoices" => redirect{ |p, request| "/dashboard?#{request.query_string}" }


回答2:

The simplest way to do this (at least in Rails 4) is do use the options mode for the redirect call..

get '/invoices' => redirect(path: '/dashboard')

This will ONLY change the path component and leave the query parameters alone.



回答3:

While the accepted answer works perfectly, it is 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 "/invoices", to: redirect(QueryRedirector.new("/dashboard"))

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