The words Under construction in black text on a yellow background with diagonal black stipes surrounding it
I'm in the process of moving my site. It's still a work in progress. Please excuse the mess and broken links.

Use StructObject For Dynamic Variables In Rust's MiniJinja

TODO: Pull subtitle into page object
Code
use crate::page::Page;
use minijinja::value::{StructObject, Value};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type", rename_all = "lowercase")]
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,
        }
    }
}

Code
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(tag = "type", rename_all = "lowercase")]
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

Debugging Stuff

I'm moving stuff around right now. All this below is helping me figure out where to put stuff

        -- title

Use StructObject For Dynamic Variables In Rust's MiniJinja

-- code
-- rust

use crate::page::Page;
use minijinja::value::{StructObject, Value};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type", rename_all = "lowercase")]
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,
        }
    }
}



-- code
-- rust

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(tag = "type", rename_all = "lowercase")]
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 to `serde`` in _Cargo.toml__ like:

```
serde = {version = "1.0.177", features = ["derive"] }
```

- 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


-- 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


-- ref
-- url: https://docs.rs/minijinja/latest/minijinja/value/struct.Value.html
-- title: minijinja::value::Value

This is the key to being able to use functions
from object inside templates

-- categories
-- Rust 
-- MiniJinja 

-- metadata
-- date: 2023-07-27 14:58:15
-- id: 2tasgoyx
-- site: aws
-- type: post
-- status: published