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

Template Rendering of a Result<T + Display, E + Display> Cleanly #1059

Open
jaw-sh opened this issue May 27, 2024 · 3 comments
Open

Template Rendering of a Result<T + Display, E + Display> Cleanly #1059

jaw-sh opened this issue May 27, 2024 · 3 comments

Comments

@jaw-sh
Copy link

jaw-sh commented May 27, 2024

I have a template that I call a View. It has implementations which return templates-in-templates with derived values. Sometimes these can fail and return results. These results need to be handled inside the template, even though both arms of Result<> implement Display.

/// View for editing a single post.
#[derive(Template)]
#[template(path = "post/edit.html")]
pub struct PostEditView {
    pub context: Context,
    pub attachment_collection: AttachmentCollection,
    pub post_collection: PostCollection,
    pub post_form: PostForm,
}

impl PostEditView {
    pub fn post_edit_template(&self) -> PostFormPartial {
        PostFormPartial {
            attachment_collates: Default::default(),
            post_collate: None,
            post_form: &self.post_form,
            thread_collate: None,
        }
    }

    pub fn post_template(&self) -> Result<impl Template + '_, Error> {
        Ok(PostPartial {
            attachment_collates: self.attachment_collection.collates(),
            post_collate: self.post_collection.collate_single()?,
            post_position: None,
        })
    }
}

My template could look like this:

{% block content %}
{{ self.post_template() }}
{{ self.post_edit_template() }}
{% endblock %}

Instead, it must look like this:

{% block content %}

{% self.post_template() }}
{% when Ok(post) %}
{{ post }}
{% when Err(e) %}
{{ e }}
{% endmatch %}

{{ self.post_edit_template() }}

{% endblock %}

I don't like this. It would be super cool if there was a way to simply {{ result }} and render either branch automatically.

@Kijewski
Copy link
Contributor

Kijewski commented May 27, 2024

I don't like this. It would be super cool if there was a way to simply {{ result }} and render either branch automatically.

Have a look how to implement custom filters. Adding your own |either_result filter would be simple enough.

I wouldn't like askama to branch both cases automagically, because I would most like wrap the error message in e.g. <div class="error">. If the template engine makes it harder to find such cases, it would be a disadvantage to me.

@jaw-sh
Copy link
Author

jaw-sh commented May 27, 2024

Have a look how to implement custom filters. Adding your own |either_result filter would be simple enough.

I did attempt this but had compiler errors regarding sized types and another anomalous issues I couldn't resolve myself. I would accept this as a solution if I could manage it.

@djc
Copy link
Owner

djc commented May 28, 2024

Have a look how to implement custom filters. Adding your own |either_result filter would be simple enough.

I did attempt this but had compiler errors regarding sized types and another anomalous issues I couldn't resolve myself. I would accept this as a solution if I could manage it.

A filter should definitely be possible. Do you have the exact error message?

I don't think there's a general solution here because a blanket impl for Display for Result<T, E> just doesn't make sense even if T and E both implement Display. A Display impl might be possible (coherence willing) for specific T/E combinations, of course.

A filter or macro definitely feels like the straightforward option here.

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