On Thu, 31 May 2012 10:04:17 +0200, simendsjo simendsjo@gmail.com wrote:
I cannot find a good way to pass parameters to templates, but I have
several sub-optimal ways of doing it...
One is wrapper that adds a parameter:
void auth(alias View)(Request req, Response res) {
auto user = getLoggedInUser();
view(req, res, user);
}
This doesn't scale well, as all views needs this field, and I haven't
found a way to nest several wrappers.
Another way is to hijack the render method to add fields:
void render(string templateName, Params)(Response res, Request req) {
auto user = getLoggedInUser();
if(user)
vibe.http.server.render!(templateName, Params, user)(res, req);
else
vibe.http.server.render!(templateName, Params)(res, req);
}
As you see, this allows me to only add the parameter if it makes sense.
A static if in the diet template could check if it's passed in (could
share a layout with a login/logout view even for static templates)
But I don't know how to do this for several parameters either.
The "best" way I've found is passing in the Request, and let the views
call helper methods in the application. I don't really like this
approach as I would like the static typing present, and want to keep my
views as dumb as possible.
So.. What's a good way to pass parameters to diet templates?
I found an acceptable way to handle this, but it requires some cleanup.
I store all "injectors", as I called them, in template parameters, and
each injector adds it's values, pops off it's own method pointer and calls
the next.
The last method pointer is the actual view.
Usage:
// the first value is the view
routes.get("/test", &inject!(test, injectUser, injectA, injectB,
injectC))
The inject method:
// We need to add a variant as I didn't find a way to allow default values
when using variadic arguments. I just add the request..
void inject(alias view, Injectors...)(Request req, Response res)
{
static if(Injectors.length == 0)
{
alias view!(Request, "req") Fn;
}
else static if(Injectors.length == 1)
{
alias Injectors[0] Injector;
alias Injector!(view, Request, "req") Fn;
}
else
{
alias Injectors[0] Injector;
alias Injectors[1..$] Rest;
alias Injector!(Rest, view, Request, "req") Fn;
}
Fn(req, res, [Variant(req)]);
}
Each inject method looks like this:
void injectA(Params...)(Request req, Response res, Variant[] args...)
{
int a = 10;
alias Params[0] next;
next!(Params[1..$], int, "a")(req, res, args~Variant(a));
}
And the view:
void test(Params...)(Request req, Response res, Variant[] args...)
{
res.renderCompat!("test.dt", Params)(args);
}
This way, each injector can choose to store a default value, or not add
the value at all.
For diet templates, this means you'll have to check if a variable exists
if you choose to use an injector that doesn't always add a default value.