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.