0

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
kmdreko
  • 42,554
  • 6
  • 57
  • 106
lion
  • 25
  • 5
  • Why are you deriving and the manually implementing `Serialize` for `User`? Just use the derived Serialization and it should work as far as I can tell. – belst Feb 06 '17 at 09:07
  • I thought that I do not need that. However, it is required at compile time. 1. Comment out `impl Serialize for User` 2. Comment out `let serialized = serde_json :: to_string (& query) .unwrap ();` 3. `$ cargo run` `Template::render("index", &query) // error the trait 'serde::ser::Serialize' is not implemented for 'mlib::models::User'` – lion Feb 06 '17 at 09:23
  • @belst Please let me teach if you do not mind. – lion Feb 06 '17 at 09:44
  • Welcome to Stack Overflow! Your English is fine, but the code is not up to the standards expected here. Please review how to create a [MCVE]. Ideally, you would to provide a single code block, *inside this question*, that an answerer could copy and paste locally to generate the same error. I can almost guarantee that you can remove some large part of your question (maybe Diesel?) and replace it with hard-coded values to eliminate it as a possible source of the error. – Shepmaster Feb 06 '17 at 13:43
  • Thank you for editing. I would like to ask questions from the next carefully. – lion Feb 06 '17 at 16:17

1 Answers1

1

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)
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • Apparently I seemed to be terribly confused. As you said, i could implement it with HashMap. However, it was lost sight of all the time due to other errors. Thanks. – lion Feb 06 '17 at 16:25