maghoff / bart

A compile time templating language for Rust inspired by Mustache
https://crates.io/crates/bart
MIT License
37 stars 7 forks source link

[discuss] Allow multi template for same data type #13

Closed hh9527 closed 7 years ago

hh9527 commented 7 years ago

for now:

#[derive(BartDisplay)]
#[template = "hello_world.html"]
struct HelloWorld<'a> {
    name: &'a str,
}

My suggestion is split renderer and input data type, something like this:

#[derive(BartDisplay)]
#[bart(template="hello_world.html", type_args="'a", input_type="HelloWorld<'a>")]
struct HelloWorldTemplate;

#[derive(BartDisplay)]
#[bart(template="hello_world.mob.html", type_args="'a", input_type="HelloWorld<'a>")]
struct HelloWorldTemplateForMobile;

struct HelloWorld<'a> {
    name: &'a str,
}

fn handle_request(req: Request) -> String {
  let data: HelloWorld<_> = req.get_data();
  if req.is_mobile_browser() {
    HelloWoldTemplateForMobile.render(data)
  } else {
    HelloWoldTemplate.render(data)
  }
}
maghoff commented 7 years ago

Hi :) Thanks for your input.

For now, I recommend the following workaround (or "alternative solution", if you will ;)

struct HelloWorld<'a> {
    name: &'a str,
}

#[derive(BartDisplay)]
#[template="hello_world.html"]
struct HelloWorldTemplate<'a> {
    data: HelloWorld<'a>
}

#[derive(BartDisplay)]
#[template="hello_world.mob.html"]
struct HelloWorldTemplateForMobile<'a> {
    data: HelloWorld<'a>
}

// ...

Of course, this requires you to change the templates to match the extra layer of indirection, data.


Perhaps that hints to a different way of attacking this in Bart? Maybe we could allow a root_element attribute? Something like the following:

struct HelloWorld<'a> {
    name: &'a str,
}

#[derive(BartDisplay)]
#[bart(template="hello_world.html", root_element="data")]
struct HelloWorldTemplate<'a> {
    data: HelloWorld<'a>
}

#[derive(BartDisplay)]
#[bart(template="hello_world.mob.html", root_element="data")]
struct HelloWorldTemplateForMobile<'a> {
    data: HelloWorld<'a>
}

// ...

In this case, the templates would not need to know about data.

What do you think about this idea?


It could be tempting to use a newtype (1-tuple, struct Template<'a>(HelloWorld<'a>)) for this, but Bart currently fails to accept {{0}} to refer to the contained element.


(Aside: How about making one responsive template instead? 😛 )

hh9527 commented 7 years ago

I am using the same workaround solution for now. But I think it is a little verbose to write boilerplate code.

this is my code for now:

#[derive(Debug, BartDisplay)]
#[template = "views/index.html"]
struct EchoHtml<'a> {
    scope: Echo<'a>
}

impl<'a> Renderable<Echo<'a>> for EchoHtml<'a> {
    fn render(scope: Echo<'a>) -> (Self, Cow<'static, str>) {
        (EchoHtml { scope: scope }, "text/html;charset=utf8".into())
    }
}

BTW, I like the idea of root_element.

And further more, I think use Display for render trait will pollution the data type, maybe give another specialized trait, like Renderable or something else.

maghoff commented 7 years ago

I am closing this in favor of #14 and #15