I have two resource controllers where I am using a slug to represent the ID. (friendly_id gem).
I am able to have the show path for one resource on the route but not for two at the same time. ie.
root :to => 'home#index'
match '/:id' => "properties#show"
match '/:id' => "contents#show"
Basically I want urls like,
# Content
domain.com/about-us
domain.com/terms
# Property
domain.com/unique-property-name
domain.com/another-unique-property-name
Whatever resource I put on top works. Is there a way to do this?
Thanks in advace if you can help.
This is untested, but try utilizing a constraint
on your route.
root :to => 'home#index'
match '/:id', :to => "properties#show",
:constraints => lambda { |r| Property.find_by_id(r.params[:id]).present? }
match '/:id', :to => "contests#show",
:constraints => lambda { |r| Contest.find_by_id(r.params[:id]).present? }
Alternatively, you can create a separate class that responds to matches?
instead of defining a lambda
proc. (I recommend placing these classes into separate files that will autoload within your Rails app.)
# app/constraints/property_constraint.rb
class PropertyConstraint
def self.matches?(request)
property = Property.find_by_id(request.params[:id])
property.present?
end
end
# app/constraints/contest_constraint.rb
class ContestConstraint
def self.matches?(request)
contest = Contest.find_by_id(request.params[:id])
contest.present?
end
end
# config/routes.rb
root :to => 'home#index'
match '/:id', :to => "properties#show", :constraints => PropertyConstraint
match '/:id', :to => "contests#show", :constraints => ContestConstraint
Unfortunately this results in an extra DB query (once in the routes, and once more in your controller). If anyone has a suggestion on minimizing this, please share. :)
This Rails Engine does what you want:
Slug Engine at Github
Basically, the author's approach was to mount a Rails Engine inside his main app. This Engine incorporates both a controller for handling slugs that exist and a piece of middleware for filtering out and abstaining on slugs that don't exist.
He explains why he took this approach and other aborted solutions in a rather detailed and interesting blog post. This blog post and the slug engine source code should be enough detail for you to get your own code up and running, but that open-source engine seems to be exactly what you're looking for if you want a drop-in solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With