Skip to main content

doido_generators/generators/
job.rs

1use crate::generator::{GeneratedFile, Generator};
2use crate::generators::{register_module, to_pascal, to_snake};
3use doido_core::Result;
4
5/// Fallback `app/jobs/mod.rs` when the app doesn't have one on disk yet.
6const JOBS_MOD_BASE: &str = include_str!("../../templates/new/app/jobs/mod.rs");
7const JOBS_MOD_PATH: &str = "app/jobs/mod.rs";
8
9pub struct JobGenerator;
10
11impl Generator for JobGenerator {
12    fn name(&self) -> &str {
13        "job"
14    }
15
16    fn generate(&self, args: &[&str]) -> Result<Vec<GeneratedFile>> {
17        let name = args
18            .first()
19            .copied()
20            .ok_or_else(|| doido_core::anyhow::anyhow!("job generator requires a name argument"))?;
21        let snake = to_snake(name);
22        let pascal = to_pascal(name);
23        let content = crate::templates::get("job/job.rs.template")
24            .replace("{pascal}", &pascal)
25            .replace("{snake}", &snake);
26        let test = crate::templates::get("job/job_test.rs.template")
27            .replace("{pascal}", &pascal)
28            .replace("{snake}", &snake);
29
30        // Register the job's module in app/jobs/mod.rs, preserving any existing.
31        let existing =
32            std::fs::read_to_string(JOBS_MOD_PATH).unwrap_or_else(|_| JOBS_MOD_BASE.to_string());
33        let jobs_mod = register_module(&existing, &format!("{snake}_job"), "@generated-jobs");
34
35        Ok(vec![
36            GeneratedFile {
37                path: format!("app/jobs/{snake}_job.rs"),
38                content,
39            },
40            GeneratedFile {
41                path: JOBS_MOD_PATH.to_string(),
42                content: jobs_mod,
43            },
44            GeneratedFile {
45                path: format!("tests/{snake}_job_test.rs"),
46                content: test,
47            },
48        ])
49    }
50}