Reputation: 223
I am writing a replacement system for a legacy application, and we want the old URLs to redirect to the new URL structure. I would like to use the redirect helper in routes.rb to accomplish this. This works great for simple cases. However, there are some legacy identifiers that contain dots. If an identifier contains a dot I need to:
So, here is my test for this in rspec:
it "redirects requests correctly when there are dots in the eadid" do
get "/collections/MC001.02.01/c00003"
expect(response.code).to eq "301"
expect(response).to redirect_to("http://www.example.com/catalog/MC001-02-01_c00003")
end
I have read the documentation for the redirect helper in several places. I see that I can use constraints
to correctly grab the entire id, in spite of the dots. So, this works for grabbing the entire id:
get "/collections/:eadid/:componentid", to: redirect("/catalog/%{eadid}_%{componentid}"), constraints: { eadid: /([^\/])+?/ }
This returns /catalog/MC001.02.01_c00003
. Close, but not quite right, because I also need to replace the dots with dashes.
I also see that I can use a block format if I need to do some more complicated logic, e.g., string replacement, like this:
get "/collections/:eadid/:componentid", to: redirect { |params, request|
"/catalog/#{params[:eadid].gsub('.','-')}_#{params[:componentid]}"
}
This doesn't work, because the bit of the eadid
after the first dot has been dropped, as I can see if I examine both the params
and the request
:
"action_dispatch.request.path_parameters"=>{:eadid=>"C0140", :componentid=>"c03411"}
I have not been able to find an example of a redirect helper configured to use both a constraint
and a block. Guesses at syntax have not been fruitful. Anyone know the secret formula here? Or is there a better approach for what I'm trying to do?
Thank you!
Sources consulted:
Upvotes: 3
Views: 781
Reputation: 223
I ended up going with this, because I find it slightly easier to read, but I can confirm that Geoffroy's answer works and I've marked it as accepted.
get "/collections/:eadid/:componentid", constraints: { eadid: /([^\/])+?/ }, to: redirect { |params, _request|
"/catalog/#{params[:eadid].tr('.', '-')}_#{params[:componentid]}"
}
Geoffroy's suggestion to list out what syntax guesses I had made already was also very helpful. Thank you!
Upvotes: 4
Reputation: 12719
You have to take care with the similar (but different) syntax between blocks and hashes
This is the syntax for one-line blocks:
redirect {|params, request| ...}
This is the syntax for a Hash:
{to: redirect("/catalog/%{eadid}_%{componentid}")}
The {
and closing }
are optional when the Hash is the last argument to a method call, as is the case with your get
.
Now if you want to mix boths, you may need to take good care of what you're doing.
Another solution would be to extract the constraint:
constraints(eadid: /[^\/]+/) do
get "/collections/:eadid/:componentid", to: redirect { |params, request|
"/catalog/#{params[:eadid].gsub('.','-')}_#{params[:componentid]}"
}
end
Upvotes: 4