Use a variable with Vibe.d when rendering a template file with response.render

StackOverflow https://stackoverflow.com/questions/22870859

  •  27-06-2023
  •  | 
  •  

質問

Currently I'm using Vibe.d to make a website, which has a Response class that's handed to every request. That looks something like this:

import vibe.d;

void index(HTTPServerRequest req, HTTPServerResponse res)
{
  res.render!("index.dt", req);
}

shared static this()
{
  auto router = new URLRouter;
  router.get("/", &index);

  auto settings = new HTTPServerSettings;
  settings.port = 8080;

  listenHTTP(settings, router);
}

In the example, I'm passing a const string "index.dt to the res.render! method, but I want to pass a variable:

void render(string action, HTTPServerResponse res) {
  res.render!(action);
}

But I get the following error:

Error: variable action cannot be read at compile time

In every spot I'm calling render, I've hardcoded strings:

render("foo.dt");

But that doesn't satisfy the compiler. Any idea how I can make this work?

役に立ちましたか?

解決

While using a run time variable is not possible as a matter of principle (that would basically require compiling D code at run time), you could use a compile time defined enum constant or template parameters to avoid using the string constants directly:

void index(string templ)(HTTPServerRequest req, HTTPServerResponse res)
{
    res.render!(templ, req);
}

shared static this()
{
    // ...
    router.get("/", &index!"index.dt");
    // BTW, this special case is equal to
    //router.get("/", staticTemplate!"index.dt");
    // ...
}

or using an enum:

enum indexTemplateFile = "index.dt";

void index(HTTPServerRequest req, HTTPServerResponse res)
{
    res.render!(indexTemplateFile, req);
}

This alternative form of using a named enum can also be used:

enum TemplateFile {
    index = "index.dt",
    login = "login.dt"
}

void index(HTTPServerRequest req, HTTPServerResponse res)
{
    res.render!(TemplateFile.index, req);
}

Both of these approaches can also be combined and the constants can even be modified with the usual string operations, as long as the result can still be computed at compile time (e.g. it is possible to call something like std.string.toLower on the string before passing it to render).

他のヒント

You can't. Diet templates are completely pre-processed during compilation so it is necessary to know Diet template file name as compile-time constant. You can pass any amount of variable parameters to template to be processed dynamically but template file itself is strictly compile-time.

Option to render template during runtime has been asked several times and is conceptually approved but not being worked on actively.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top