Reputation: 4144
I have a rule in my routes.rb:
constraints AssetRestrictor do
match '*seopath' => SeoDispatcher
end
Then in lib/seo_dispatcher.rb, I have this:
class SeoDispatcher
AD_KEY = "action_dispatch.request.path_parameters"
def self.call(env)
seopath = env[AD_KEY][:seopath]
if seopath
params = seopath.split('/') # get array of path components
env[AD_KEY][:id] = params.last # the real page name is the last element
env[AD_KEY][:category] = params.first if params.length > 1
end
Rails.logger.debug "routing to show #{env[AD_KEY]}"
PagesController.action(:show).call(env)
# TODO error handling for invalid paths
end
end
class AssetRestrictor
EXCEPTION_FILES = ['javascripts', 'stylesheets', 'autodiscover']
def self.matches?(request)
return false if request.method == 'POST' # no post requests are SEO-ed
EXCEPTION_FILES.each do |ex|
return false if request.url.include?(ex)
end
true
end
end
And basically, the whole thing works. The idea is to peel off the last path component and match it to the slug for a page. SEO people tell me this is the cool way to trick search engines into ranking you higher.
My snarky comments aside, I'm having trouble writing a test in rSpec that exercises this code. My first shot at it was:
describe SeoDispatcher do
it "routes /insurance/charters-and-guides/how-to-buy-charter-boat-insurance to pages#show :id => how-to-buy-charter-boat-insurance" do
{ :get => "/insurance/charters-and-guides/how-to-buy-charter-boat-insurance"}.should route_to(
:controller => 'pages',
:action => 'show',
:id => 'how-to-buy-charter-boat-insurance'
)
end
end
But this simply doesn't exercise the Rack dispatch code. Does anyone know how one would (than cuking it) exercise the code? I really want to bring the parameters in from Rack instead of just doing SeoDispatcher.call({"action_dispatch.request.path_parameters" => {:seopath => "/foo/bar"}})
.
Thanks!
Upvotes: 2
Views: 1619
Reputation: 4144
Ok, answered my own question. Request spec:
describe SeoDispatcher do
describe "seo parsing" do
it "GET /insurance/charters-and-guides/how-to-buy-charter-boat-insurance displays how-to-buy-charter-boat-insurance (3-part path)" do
p = Page.make(:title => "how-to-buy-charter-boat-insurance")
p.save
get "/insurance/charters-and-guides/how-to-buy-charter-boat-insurance"
request.path.should == "/insurance/charters-and-guides/how-to-buy-charter-boat-insurance"
assigns[:page].slug.should == "how-to-buy-charter-boat-insurance"
end
it "GET /insurance/charters-and-guides displays guides (2-part path)" do
p = Page.make(:title => "charters and guides")
p.save
get "/insurance/charters-and-guides"
request.path.should == "/insurance/charters-and-guides"
assigns[:page].slug.should == "charters-and-guides"
end
it "GET /insurance displays insurance (1-part path)" do
p = Page.make(:title => "insurance")
p.save
get "/insurance"
request.path.should == "/insurance"
assigns[:page].slug.should == "insurance"
end
end
end
If anyone knows a better way, feel free to let me know!
Upvotes: 2