diff --git a/contrib/lib/src/templates/metadata.rs b/contrib/lib/src/templates/metadata.rs index 04aacabd..0dee3a70 100644 --- a/contrib/lib/src/templates/metadata.rs +++ b/contrib/lib/src/templates/metadata.rs @@ -1,59 +1,67 @@ -use rocket::{http::Status, outcome, request::{FromRequest, Outcome}, Request, State}; -use templates::context::Context; +use rocket::{Request, State, Outcome}; +use rocket::http::Status; +use rocket::request::{self, FromRequest}; -/// The TemplateEngine type: implements `FromRequest`, allowing you to communicate -/// directly with the template engines. -/// -/// Using it in a request handler always returns successfully except when the [`Template::fairing()`] -/// wasn't attached to rocket. +use templates::Context; + +/// The `TemplateMetadata` type: implements `FromRequest`, allowing dynamic +/// queries about template metadata. /// /// # Usage /// -/// Ensure that the template [fairing](/rocket/fairing/) is attached to +/// First, ensure that the template [fairing](`rocket::fairing`) is attached to /// your Rocket application: /// /// ```rust -/// extern crate rocket; -/// extern crate rocket_contrib; -/// +/// # extern crate rocket; +/// # extern crate rocket_contrib; +/// # /// use rocket_contrib::Template; /// /// fn main() { /// rocket::ignite() -/// // ... /// .attach(Template::fairing()) /// // ... /// # ; /// } /// ``` /// -/// The `TemplateEngine` type implements Rocket's `FromRequest` trait, so it can be -/// used as Parameter in a request handler: +/// The `TemplateMetadata` type implements Rocket's `FromRequest` trait, so it can +/// be used as a request guard in any request handler. +/// +/// ```rust +/// # #![feature(plugin, decl_macro)] +/// # #![plugin(rocket_codegen)] +/// # extern crate rocket; +/// # #[macro_use] extern crate rocket_contrib; +/// # fn main() { } +/// # +/// use rocket_contrib::{Template, TemplateMetadata}; /// -/// ```rust,ignore /// #[get("/")] -/// fn homepage(engine: TemplateEngine) -> Template { -/// if engine.template_exists("specific") { -/// return Template::render("specfic", json!({})); +/// fn homepage(metadata: TemplateMetadata) -> Template { +/// // Conditionally render a template if it's available. +/// if metadata.contains_template("some-template") { +/// Template::render("some-template", json!({ /* .. */ })) +/// } else { +/// Template::render("fallback", json!({ /* .. */ })) /// } -/// Template::render("fallback", json!({})) /// } /// ``` pub struct TemplateMetadata<'a>(&'a Context); impl<'a> TemplateMetadata<'a> { - /// Returns `true` if the template with name `name` was loaded at start-up time. Otherwise, - /// returns `false`. + /// Returns `true` if the template with name `name` was loaded at start-up + /// time. Otherwise, returns `false`. /// /// # Example /// - /// ```rust,ignore - /// #[get("/")] - /// fn homepage(engine: TemplateEngine) -> Template { - /// if engine.template_exists("specific") { - /// return Template::render("specfic", json!({})); - /// } - /// Template::render("fallback", json!({})) + /// ```rust + /// use rocket_contrib::TemplateMetadata; + /// + /// fn handler(metadata: TemplateMetadata) { + /// // Returns `true` if the template with name `"name"` was loaded. + /// let loaded = metadata.contains_template("name"); /// } /// ``` pub fn contains_template(&self, name: &str) -> bool { @@ -61,19 +69,21 @@ impl<'a> TemplateMetadata<'a> { } } +/// Retrieves the template metadata. If a template fairing hasn't been attached, +/// an error is printed and an empty `Err` with status `InternalServerError` +/// (`500`) is returned. impl<'a, 'r> FromRequest<'a, 'r> for TemplateMetadata<'a> { type Error = (); - fn from_request(request: &'a Request) -> Outcome { - request - .guard::>() + fn from_request(request: &'a Request) -> request::Outcome { + request.guard::>() .succeeded() - .and_then(|ctxt| Some(outcome::Outcome::Success(TemplateMetadata(ctxt.inner())))) + .and_then(|ctxt| Some(Outcome::Success(TemplateMetadata(ctxt.inner())))) .unwrap_or_else(|| { error_!("Uninitialized template context: missing fairing."); info_!("To use templates, you must attach `Template::fairing()`."); info_!("See the `Template` documentation for more information."); - outcome::Outcome::Failure((Status::InternalServerError, ())) + Outcome::Failure((Status::InternalServerError, ())) }) } } diff --git a/contrib/lib/tests/templates.rs b/contrib/lib/tests/templates.rs index fc098a00..d3822845 100644 --- a/contrib/lib/tests/templates.rs +++ b/contrib/lib/tests/templates.rs @@ -6,15 +6,19 @@ extern crate rocket_contrib; #[cfg(feature = "templates")] mod templates_tests { - use rocket::{http::RawStr, response::content::Plain, Rocket}; - use rocket::config::{Config, Environment}; - use rocket_contrib::{Template, TemplateMetadata}; use std::env; use std::path::PathBuf; + use rocket::{Rocket, http::RawStr}; + use rocket::config::{Config, Environment}; + use rocket_contrib::{Template, TemplateMetadata}; + #[get("//")] - fn contains_template(template_metadata: TemplateMetadata, engine: &RawStr, name: &RawStr) -> Plain { - Plain(template_metadata.contains_template(&format!("{}/{}", engine, name)).to_string()) + fn template_check(md: TemplateMetadata, engine: &RawStr, name: &RawStr) -> Option<()> { + match md.contains_template(&format!("{}/{}", engine, name)) { + true => Some(()), + false => None + } } fn template_root() -> PathBuf { @@ -28,7 +32,7 @@ mod templates_tests { .expect("valid configuration"); ::rocket::custom(config).attach(Template::fairing()) - .mount("/", routes![contains_template]) + .mount("/", routes![template_check]) } #[cfg(feature = "tera_templates")] @@ -60,20 +64,20 @@ mod templates_tests { } #[test] - fn test_template_engine_with_tera() { + fn test_template_metadata_with_tera() { let client = Client::new(rocket()).unwrap(); - let mut response = client.get("/tera/txt_test").dispatch(); + let response = client.get("/tera/txt_test").dispatch(); assert_eq!(response.status(), Status::Ok); - assert_eq!(response.body().unwrap().into_string().unwrap(), "true"); - let mut response = client.get("/tera/html_test").dispatch(); + let response = client.get("/tera/html_test").dispatch(); assert_eq!(response.status(), Status::Ok); - assert_eq!(response.body().unwrap().into_string().unwrap(), "true"); - let mut response = client.get("/tera/not_existing").dispatch(); - assert_eq!(response.status(), Status::Ok); - assert_eq!(response.body().unwrap().into_string().unwrap(), "false"); + let response = client.get("/tera/not_existing").dispatch(); + assert_eq!(response.status(), Status::NotFound); + + let response = client.get("/hbs/txt_test").dispatch(); + assert_eq!(response.status(), Status::NotFound); } } @@ -100,16 +104,17 @@ mod templates_tests { } #[test] - fn test_template_engine_with_handlebars() { + fn test_template_metadata_with_handlebars() { let client = Client::new(rocket()).unwrap(); - let mut response = client.get("/hbs/test").dispatch(); + let response = client.get("/hbs/test").dispatch(); assert_eq!(response.status(), Status::Ok); - assert_eq!(response.body().unwrap().into_string().unwrap(), "true"); - let mut response = client.get("/hbs/not_existing").dispatch(); - assert_eq!(response.status(), Status::Ok); - assert_eq!(response.body().unwrap().into_string().unwrap(), "false"); + let response = client.get("/hbs/not_existing").dispatch(); + assert_eq!(response.status(), Status::NotFound); + + let response = client.get("/tera/test").dispatch(); + assert_eq!(response.status(), Status::NotFound); } } }