Rails3 RSpec testing custom redirect route in routes.rb
I have a custom redirection in my routes.rb which works fine at the ui:
match ':hash' => redirect { |params| begin url = Shar开发者_如何学Going.find_by_short_url(params[:hash]); "/#{url.shareable_type}/#{url.shareable_id}/" rescue '/' end }, :constraints => { :hash => /[a-zA-Z0-9]{7}/ }
What is does is takes a shortened url and looks up the actual url path.
However my test is failing:
it "routes GET 'STU1VWX' to stations/1" do
{ :get => "STU1VWX" }.should redirect_to(
:controller => "stations",
:action => "show",
:params => {:id => 1}
)
end
With:
1) Shorter URL redirect routes GET 'STU1VWX' to stations/1
Failure/Error: { :get => "STU1VWX" }.should route_to(
ActionController::RoutingError:
No route matches "/STU1VWX"
# ./spec/routing_spec.rb:12:in `block (2 levels) in <top (required)>'
So the problem is isolated at the test level. I know I could test this in a controller test but given that the code is in routes.rb I should not have to. Is there inherently a reason that using should route_to not to work in the case of redirection?
Looks like you're saying here that if you can't find the page belonging to the hash, then redirect to "/"
There's something really stinky about performing an ActiveRecord find in your routes.
If you have to redirect to a specific controller depending on the sharable type, then I'd put this as a separate controller with a redirect:
match "/:hash" => 'SharableController#redirect':constraints => { :hash => /[a-zA-Z0-9]{7}/ }
and then deal with finding the record and redirecting to the correct controller action from there:
class SharableController < ApplicationController
def redirect
@sharable = Sharable.find_by_sharable_type(params[:hash])
redirect_to controller: @sharable.sharable_type, action: 'show', id: @sharable.id
end
end
OR... depending on how similar the show actions are:
class SharableController < ApplicationController
def redirect
@sharable = Sharable.find_by_sharable_type(params[:hash])
render template: "#{@sharable.sharable_type.pluralize}/show"
end
end
If you're only dealing with GET requests, better to swap out match for get by the way:
get "/:hash" => 'SharableController#redirect', :constraints => { :hash => /[a-zA-Z0-9]{7}/ }
精彩评论