Use StructObject For Dynamic Variables In Rust's MiniJinja
use crate::page::Page;
use minijinja::value::{StructObject, Value};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(content = "content", rename_all = "lowercase", tag = "type")]
pub struct Universe {
pub pages: Vec<Page>,
}
impl Universe {
pub fn home_page_links(&self) -> Vec<(String, String)> {
vec![("a".to_string(), "b".to_string())]
}
}
impl StructObject for Universe {
fn get_field(&self, field: &str) -> Option<Value> {
match field {
"home_page_links" => Some(Value::from_serializable(&self.clone().home_page_links())),
_ => None,
}
}
}
use minijinja::value::{StructObject, Value};
use minijinja::{context, Environment};
use serde::{Deserialize, Serialize};
pub struct Widget;
pub struct Thing;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(content = "content", rename_all = "lowercase", tag = "type")]
pub enum Payload {
Tango { value: String },
}
impl Widget {
fn alfa_signal(&self) -> String {
"This is alfa in widget".to_string()
}
}
impl StructObject for Widget {
fn get_field(&self, field: &str) -> Option<Value> {
match field {
"alfa" => Some(Value::from(self.alfa_signal())),
_ => None,
}
}
}
impl Thing {
fn bravo_signal(&self) -> String {
"This is bravo in thing".to_string()
}
}
impl StructObject for Thing {
fn get_field(&self, field: &str) -> Option<Value> {
match field {
"bravo" => Some(Value::from(self.bravo_signal())),
_ => None,
}
}
}
fn main() {
let widget = Widget;
let thing = Thing;
let p = Payload::Tango {
value: "charlie".to_string(),
};
let env = Environment::new();
let tmpl = env
.template_from_str("{{ p.type}};{{ p.value }} - {{ w.alfa }} - {{ t.bravo }}")
.unwrap();
let w = Value::from_struct_object(widget);
let t = Value::from_struct_object(thing);
let output = tmpl.render(context!(w => w, t => t, p=> p)).unwrap();
dbg!(output);
}
Notes
-
needs
cargo add minijinja serde
-
needs
derive
added toserde
in Cargo.toml like:
serde = {version = "1.0.177", features = ["derive"] }
Notes
-
If you try to just print the main object out in the template (e.g. with
{{ whatever }}
and don't call a function on it nothing will show up. Makes sense, but it threw me the first couple of times -
The old notes had
#[serde(content = "content", rename_all = "lowercase", tag = "type")]
but I think that causes a problem with enums with a single value (i.e. not struct enums, but I forget what the other ones are called)
TODO
☐
Combine these two examples with .from and .from_seriliazble
☐
Combine with 2vauitbb
☐
Show regular object which allows method calls and is the way to go with neopoligin
-- end of line --
References
-
This is the key to being able to use functions from object inside templates