Reputation: 1819
I want to have a rails route that triggers if the given id is present, but falls back to further route matching if not.
Specifically, I want to have promo codes at the root level of my site. So, you can go to foo.com/save87
or foo.com/xmasspecial
, and it'll treat it as a promo code, but if you go to a promo code that's not there (foo.com/badcode
), that route will not match and rails will continue down the route list.
In an ideal world, I'd do something like this in my routes.rb
file:
get '/:promo_id' => 'promos#show, constraints => lambda { Promo.exists?(promo_id) }
I know that the above code, without the constraints, would work as a catch-all for foo.com/*
, and would sorta work if I put it as the last line in the routes file. Unfortunately, that would result in foo.com/badcode
a 'promocode not found' error, rather than a normal 'route not found' error.
So, is there a way to accomplish what I'm trying to accomplish? This is in Rails 3, for reference.
Edit: To clarify a bit-
foo.com/save87
instead of foo.com/promo_codes/save87
)foo.com/widget_deluxe
, foo.com/widget_extreme
, etc in addition to my promo code urls. I'd have to make sure that there's no collision between promo codes and widget varieties, but that's easily handled elsewhere.Upvotes: 0
Views: 1497
Reputation: 8122
In an ideal world, I'd do something like this in my routes.rb file:
No way. In Rails
World, this functionality should go inside controller.
In controller you can do something like
def show
if Promo.exists?(promo_id)
#do something
else
raise ActionController::RoutingError.new('Not Found')
end
end
Update
With routes, you can do something like this
constraints(lambda { |req| Promo.exists?(req.params["promo_id"]) }) do
get '/:promo_id' => 'promos#show
end
Please keep in mind that this constraints will query the database for every request with a url matching the pattern /:promo_id
(e.q. /users
, /faq
). To avoid unnecessary database queries that decrease your website performance, you should add this rule as far as possible to the end of your routes.rb
.
Upvotes: 4
Reputation: 6075
Using this routing logic, every request to your application would do an extra search for a promo code before it moved on to the rest of the routes. I recommend looking at your business case and consider doing a Promo controller. If you must do routes, something like this would work but I would put it at the end so that it goes to your regular routes first.
get '*', to: 'promos#show'
Upvotes: 0