I have a wildcard route in my routes.rb
file:
get "*client" => "client#show"
In the controller, I look up the client in the database and display their custom page:
def show
@client = Client.find_by(slug: params[:client])
if @client.nil?
render file: "client/404", layout: "error", status: :not_found
return
end
end
This works great, but my problem is that any asset that is not found is also being routed through my client#show
handler.
This results in a pointless lookup in the database for a client and then I get a 500 error because Rails doesn't know how to render my error page for non-html formats.
My question is: How can I prevent non-HTML formats from going into my wildcard handler?
I've tried the following to no avail:
Format Constraint
Putting a scope around the route to constrain it to the HTML format:
scope :format => true, :constraints => { :format => 'html' } do
get "*client" => "client#show"
end
This does keep assets from being routed to my handler, but unfortunately only routes pages to the handler if they explicitly end with the .html
extension. Failure.
Format Default
Next, I thought I'd try a format default. Like so:
get "*client" => "client#show", :defaults => { :format => 'html' }
Unfortunately, still no workee. There is no change. My understanding is that this just sets the default format if Rails can't otherwise figure it out from the content-type header or file extension.
I'm starting to think there may not be a way to do this at the route level.
Since I couldn't figure out how to restrict assets from going into my handler at the route
level, I just put a check at the beginning of my handler to short-circuit the handler if the request is not HTML format.
def show
render nothing: true, status: :not_found and return if invalid_format?
...
end
private
def invalid_format?
request.format != "html"
end