hobbit
hobbit copied to clipboard
More extensible routing
Hobbit is by far the most extensible web library I ever seen. There is still, however, a feature which I miss. I would like to have a way to change routing behaviour besides defining routes.
Let me give an example. Currently, the default behaviour of the following app
class App < Hobbit::Base
get '/before' do
'before'
end
get '/:name' do
"The name is #{request.params[:name]}"
end
get '/after' do
'after'
end
end
is to return "The name is after" when /after route is requested. And it seems there is no easy way to make it return "after", without changing the order of route definitions.
Suppose there is a third-party module which provides /before and /:name routes. The question is how can we get the app routes have priority over the module ones? (Of course, we can just include this module at the very end. But still, in a more complex app, it seems beneficial to have a way to set priorities.)
I have started to do some work here, but it would be difficult to proceed until #21 resolved.
I kind of like the idea, but I'd rather do this explicitly (like Sinatra does) by calling a pass
method or something alike. Otherwise could be difficult to find certain issues.
Could you try to make an extension instead of modify the codebase?
Could you try to make an extension instead of modify the codebase?
I probably could, but what I want is very different from what Sinatra's pass
does. For that reason I would like to discuss a little bit more(if it does not disturb you).
I provide an implementation of the feature in this branch for illustrative purposes. ( I do not propose to merge it into the master, obviously. )
One can specify a custom router for an app like so:
class App < Hobbit::Base
router do
Hobbit::Router.new # Router should be able to take a block,
# in which its behaviour can be changed in various ways.
# Currently, it does not implemented yet.
end
end
Users should not be obligated to use Hobbit::Router. On the contrary, they should be allowed to use any object as a router, as long as it complies to the public API of Hobbit::Router:
class App < Hobbit::Base
router do
Class.new do
def add_route(*)
end
def route_for(_request)
Proc.new { 'This string will be returned for any route.' }
end
end.new
end
end
The API of Hobbit::Router(and the whole implementation) is preliminary. Every part of it should be discussed if you like the idea. I would like to draw your attention to the general idea of extracting Router from Base and providing the ability to change routing behaviour completely.
I hope, this time I expressed my wish more clearly. How do you like it?