Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First thing that's not None or empty #814

Open
alper opened this issue Apr 23, 2023 · 3 comments
Open

First thing that's not None or empty #814

alper opened this issue Apr 23, 2023 · 3 comments

Comments

@alper
Copy link

alper commented Apr 23, 2023

Is there a way to do something like: {{ venue.name or venue.fallback_name }}

So take the first thing that's not None or empty and render that?

@alper
Copy link
Author

alper commented Apr 23, 2023

Currently I have to do this like so, which is verbose:

{% if !venue.name.is_empty() %}
    {{ venue.name }}
{% else %}
    {{ venue.google_name }}
{% endif %}

@vallentin
Copy link
Collaborator

vallentin commented Apr 28, 2023

Assuming that name is Option<T> (where T is e.g. String) and fallback_name then is String. Then you can utilize Option's methods, such as or() and unwrap_or().

So say we have the following struct:

#[derive(Template)]
struct Page {
    a: Option<String>,
    b: Option<String>,
    default: String,
}

Then to be able to render a otherwise default, you can do:

{{ a.as_deref().unwrap_or(default.as_str()) }}

If you want to render a otherwise b otherwise default, then you can do:

{{ a.as_deref().or(b.as_deref()).unwrap_or(default.as_str()) }}

Complete Example:

#[derive(Template)]
#[template(
    source = "{{ a.as_deref().or(b.as_deref()).unwrap_or(default.as_str()) }}",
    ext = "html"
)]
struct Page {
    a: Option<String>,
    b: Option<String>,
    default: String,
}

let pages = [
    Page {
        a: Some("a".into()),
        b: None,
        default: "default".into(),
    },
    Page {
        a: None,
        b: Some("b".into()),
        default: "default".into(),
    },
    Page {
        a: Some("a".into()),
        b: Some("b".into()),
        default: "default".into(),
    },
    Page {
        a: None,
        b: None,
        default: "default".into(),
    },
];

for page in pages {
    println!("{:?}", page.render().unwrap());
}

Which would output:

"a"
"b"
"a"
"default"

@Kijewski
Copy link
Collaborator

An Option can also be used as a single element iterator, and might come in handy with for-else.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants