Custom Route Builders
As mentioned previously, route builders handle parsing the action spec to determine what code to run when a route is matched. Although OX comes with some default route builders, you can also write your own to handle other kinds of action specs.
A note beforehand: this API is a lot less finalized and more experimental than many of the other parts discussed so far, and may change in the future. It is a useful piece of functionality however, and still worth discussing even if the details may change later.
A route builder is implemented via a class which consumes the OX::RouteBuilder role. This role requires two methods:
This is a class method which is called when OX attempts to parse an action spec. If the action spec should be handled by this route builder, this method should return a value containing the parsed data (to be used later). Otherwise, it should return
undef. OX will call the
parse_action_specmethod on all enabled route builders to find the one that doesn't return
undef, and that one will be instantiated with the route data.
This method is called on the instantiated route builder, and is used to turn the route description into actual route data. You can access the route data via the
pathis the path given as the first argument of the
route_specis the value that
paramsis a hashref of the parameters given at the end of the route statement. The parameters can be split into defaults and validations by calling the
compile_routesmethod should return a hashref containing keys for
This is perhaps more clear with an example. Here is a route builder which parses action specs of the form:
In other words, a hashref mapping HTTP methods to code to run for those methods.
So going through this a piece at a time, we first have the
parse_action_spec method. This will match any action spec which is a hashref, as in the case of a route that looks like
It returns the action spec as-is to be used later, since nothing about it needs to be parsed out.
Next, we have the
compile_routes method. The first thing it does is extract the defaults and validations from the given params. Validations are params whose values are hashrefs with an
isa key, and defaults are params whose values are strings. If you want to add any additional defaults, you can also do that at this point (adding a value for
name is often a useful thing to do in cases where there is a natural default to use for it, since it will make using
uri_for easier, as described in a previous article).
It then creates the target coderef. This is the code which will be called as the action for the route. It receives an OX::Request object as its only parameter, and returns some kind of response. Here, it looks at the request to see what HTTP method it was given, and sees if there is a corresponding action to use for it. If there is, it calls that action with the request object. If there isn't, it looks for a key of
'*' as a fallback. If that doesn't exist either, it returns a valid
405 Method Not Allowed error response.
Finally, it returns the hashref containing all of the data it has assembled.
Using custom route builders
So now we have our custom route builder, but how do we use it? By default if nothing is specified, OX uses the OX::RouteBuilder::Code, OX::RouteBuilder::ControllerAction, and OX::RouteBuilder::HTTPMethod route builders. To specify an alternate set of route builders to use, you provide them in an arrayref as the first argument to the
Note that this replaces the default list rather than appending to it. This way, you can provide your own interpretation of things that the default route builders would otherwise handle, without things getting confused.
In the case of nested routers, the default set of route builders is taken from the enclosing router if nothing is specified, rather than always using the base default. For instance:
Here, the second
route statement works properly, because the router mounted at
/posts uses the same list of route builders as its parent.