lion
lion

Reputation: 25

How to display the value retrieved using Diesel in HTML using a Tera template in Rocket?

I want to display a value retrieved from the database with Diesel and serve it as HTML using a Tera template with Rocket:

#[get("/")]
fn index(db: DB) -> Template {
    use mlib::schema::users::dsl::*;
    let query = users.first::<User>(db.conn()).expect("Error loading users");
    let serialized = serde_json::to_string(&query).unwrap();
    println!("query = {:?}", &serialized);
    Template::render("index", &serialized)
}

The full sample code is here

It receives User { id: 1, name: "yamada" } from the database in #[get("/")] of src/main.rs and tries to render it with a template. It looks good to me, but this error is returned:

Error: Error rendering Tera template 'index': Failed to value_render 'index.html.tera': context isn't an object

Upvotes: 0

Views: 830

Answers (1)

Shepmaster
Shepmaster

Reputation: 431809

The error message is telling you everything you need to know:

context isn't an object

And what is context? Check out the docs for Template::render:

fn render<S, T>(name: S, context: &T) -> Template 
    where S: AsRef<str>,
          T: Serialize,

This MCVE shows the problem:

src/main.rs

#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;
extern crate rocket_contrib;

use rocket_contrib::Template;

#[get("/")]
fn index() -> Template {
    let serialized = "hello".to_string();
    Template::render("index", &serialized)
}

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}

Cargo.toml

[dependencies]
rocket = "0.1.6"
rocket_codegen = "0.1.6"

[dependencies.rocket_contrib]
version = "0.1.6"
features = ['tera_templates']

templates/index.html.tera

<html />

Most templating engines work against a data structure that maps a name to a value. In many cases, this is something as simple as a HashMap, but Rocket allows you to pass in anything that can be serialized. This is intended to allow passing in a struct, but it also allows you to pass in things that do not map names to values, like a pure string.

You have two choices:

  1. Create a HashMap (or maybe a BTreeMap) of values.
  2. Implement Serialize for a struct and pass that in.

Here's the first option:

use std::collections::HashMap;

let mut serialized = HashMap::new();
serialized.insert("greeting", "hello");
Template::render("index", &serialized)

Upvotes: 1

Related Questions