askama icon indicating copy to clipboard operation
askama copied to clipboard

Add support for reference operator (i.e. `{% let x = &y %}`)

Open cipriancraciun opened this issue 4 years ago • 5 comments

Sometimes while working with deeply nested structures, it would be useful to create an alias to a field, like say {% let h = &parent.child.hash %}

At the moment the & unary operator is not supported.

cipriancraciun avatar May 25 '20 13:05 cipriancraciun

Not supporting this has been a design goal from the start. If I remember correctly, your example should already work without &.

djc avatar May 25 '20 13:05 djc

If I remember correctly, your example should already work without &.

Unfortunately it doesn't (hash here is an owned HashMap, and all other structures are owned by self):

error[E0507]: cannot move out of `self.nested_1.nested_2.hash` which is behind a shared reference
   --> /home/build/sources/testing/tests/simple.rs:406:10
    |
406 | #[derive(askama::Template, Default)]
    |          ^^^^^^^^^^^^^^^^
    |          |
    |          move occurs because `self.nested_1.nested_2.hash` has type `std::collections::HashMap<&str, &str>`, which does not implement t
he `Copy` trait                                                                                                                                  |          help: consider borrowing here: `&askama::Template`
    |
    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error

cipriancraciun avatar May 25 '20 13:05 cipriancraciun

Hmm, okay. Perhaps we should eagerly take a reference in variable declarations (and then not do so when referencing variables later).

djc avatar May 25 '20 13:05 djc

I don't know this issue is still being tracked, by I solved by using a filter.

    pub fn asref<'a, T>(s: &'a T) -> askama::Result<&'a T> {
        Ok(s)
    }

And on the template:

{% let doc = invoice.0|asref %}

dgsantana avatar Sep 09 '20 10:09 dgsantana

It is also possible to use https://doc.rust-lang.org/std/borrow/trait.Borrow.html

At least for my usecase where I needed to compare dates:

{% if (Utc::now() + Duration::days(1)).borrow() > delete_at %}
    {{ delete_at.format("%H:%M:%S") }}
{% else %}
    {{ delete_at }}
{% endif %}

ModProg avatar May 08 '22 12:05 ModProg