This commit adds a comprehensive hot reload example that demonstrates how to use the rhai_system for dynamic template rendering with Tera. Key improvements include: - Refactor the example to use external script files instead of hardcoded Rhai code - Implement proper module imports using the BasePathModuleResolver approach - Fix template rendering by using keyword arguments in Tera function calls - Add support for hot reloading both main and utility scripts - Remove unnecessary output file generation to keep the example clean - Fix compatibility issues with Rhai functions (avoiding to_string with parameters) This example showcases how changes to Rhai scripts are automatically detected and applied to rendered templates without restarting the application, providing a smooth development experience.
3.3 KiB
Tera Factory
A factory for creating Tera template engines with integrated Rhai scripting support.
Overview
The Tera Factory module provides a simple way to integrate Rhai scripting capabilities with Tera templates. It allows Rhai functions to be called directly from Tera templates and supports hot reloading of Rhai scripts, ensuring that template rendering always uses the latest version of the functions without requiring application restarts.
Features
- Create Tera engines with specified template directories
- Integrate Tera with hot reloadable Rhai scripts
- Automatically register Rhai functions with Tera
- Support for dynamic updates when Rhai scripts are modified
- Comprehensive type conversion between Tera and Rhai values
Usage
Basic Usage
use std::path::PathBuf;
use std::sync::{Arc, RwLock};
use rhai_factory::RhaiFactory;
use tera_factory::TeraFactory;
// Create the factories
let rhai_factory = Arc::new(RhaiFactory::with_caching());
let tera_factory = TeraFactory::new();
// Set up directories
let scripts_dir = PathBuf::from("scripts");
let templates_dir = PathBuf::from("templates");
// Compile the initial script
let script_path = scripts_dir.join("math.rhai");
let ast = rhai_factory.compile_modules(&[&script_path], Some(&scripts_dir))?;
let hot_ast = Arc::new(RwLock::new(ast));
// Enable hot reloading
let handle = rhai_factory.enable_hot_reload(
hot_ast.clone(),
&[&script_path],
Some(&scripts_dir),
Some(Box::new(|| println!("Script reloaded!")))
)?;
// Create a Tera engine with Rhai integration
let tera = tera_factory.create_tera_with_rhai(&[&templates_dir], hot_ast.clone())?;
// Render a template
let mut context = tera::Context::new();
context.insert("a", &20);
context.insert("b", &22);
let rendered = tera.render("math.html", &context)?;
println!("Rendered template: {}", rendered);
// In a real application, you would periodically check for changes
rhai_factory.check_for_changes()?;
// Disable hot reloading when done
rhai_factory.disable_hot_reload(handle);
Example Rhai Script (math.rhai)
// A simple function to sum two numbers
fn sum(a, b) {
a + b
}
// A function to format a string
fn format_greeting(name) {
"Hello, " + name + "!"
}
Example Tera Template (template.html)
<div>
<h1>{{ format_greeting(name) }}</h1>
<p>The sum of {{ a }} and {{ b }} is {{ sum(a, b) }}</p>
</div>
Integration with Existing Applications
To integrate the Tera Factory with an existing application:
- Create instances of
RhaiFactory
andTeraFactory
- Compile your Rhai scripts using the
RhaiFactory
- Enable hot reloading for the scripts
- Create a Tera engine with Rhai integration using the
TeraFactory
- Periodically call
check_for_changes()
to detect script modifications - Render templates as needed, with the Rhai functions automatically available
Error Handling
The TeraFactory
provides a custom error type, TeraFactoryError
, which includes detailed information about any errors that occur during template engine creation or rendering.
Thread Safety
The integration between Tera and Rhai is designed to be thread-safe, using Arc<RwLock<AST>>
to ensure that multiple threads can safely access and update the Rhai AST. This makes it suitable for use in multi-threaded web servers and other concurrent applications.