~glyph/myka

ref: e516f30beb9db2daabfa68fbb67c17abb672f600 myka/src/lib.rs -rw-r--r-- 3.2 KiB
e516f30bmycognosist Ignore screenshots directory 1 year, 30 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#[macro_use]
extern crate diesel;
extern crate dotenv;

pub mod models;
pub mod schema;

use crate::models::{Culture, NewCulture};
use anyhow::{Context, Result};
use diesel::prelude::*;
use dotenv::dotenv;
use std::env;

/// Add a new culture to the Library.
pub fn add_culture<'a>(
    genus: String,
    species: String,
    strain: String,
    source: String,
    culture_id: String,
) -> Result<usize> {
    use schema::cultures;

    let conn = establish_connection()?;
    let culture = NewCulture::new(genus, species, strain, source, culture_id);

    let insert = diesel::insert_into(cultures::table)
        .values(&culture)
        .execute(&conn)
        .context("Error saving new culture")?;

    Ok(insert)
}

/// Delete a culture from the library.
pub fn delete_culture(unique_id: String) -> Result<usize> {
    use schema::cultures::dsl::*;
    //use schema::cultures;

    let conn = establish_connection()?;

    let delete = diesel::delete(cultures.filter(culture_id.like(unique_id)))
        .execute(&conn)
        .context("Error deleting culture")?;

    Ok(delete)
}

/// List a single culture from the Library.
pub fn list_culture(unique_id: Option<String>) -> Result<()> {
    use schema::cultures::dsl::*;

    let unique_id = unique_id.unwrap();

    let conn = establish_connection()?;
    let results = cultures
        .filter(culture_id.like(unique_id))
        .limit(1)
        .load::<Culture>(&conn)
        .context("Error loading cultures")?;

    write_cultures(results, &mut std::io::stdout())?;

    Ok(())
}

/// List all cultures in the Library.
pub fn list_cultures() -> Result<()> {
    use schema::cultures::dsl::*;

    let conn = establish_connection()?;
    let results = cultures
        .load::<Culture>(&conn)
        .context("Error loading cultures")?;

    println!("[ Library contains {} cultures ]\n", results.len());

    write_cultures(results, &mut std::io::stdout())?;

    Ok(())
}

pub fn write_cultures(results: Vec<Culture>, mut writer: impl std::io::Write) -> Result<()> {
    for culture in results {
        writeln!(
            writer,
            "{} {} {} '{}' ({})",
            culture.culture_id, culture.genus, culture.species, culture.strain, culture.source
        )?;
    }

    Ok(())
}

pub fn establish_connection() -> Result<SqliteConnection> {
    dotenv().ok();

    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    let conn = SqliteConnection::establish(&database_url)
        .with_context(|| format!("Error connecting to {}", database_url))?;

    Ok(conn)
}

#[test]
fn test_write_cultures() {
    let culture = Culture {
        id: 1,
        genus: "Hericium".to_string(),
        species: "erinaceus".to_string(),
        strain: "UK".to_string(),
        source: "WoodlandGourmet".to_string(),
        culture_id: "HEUKWG001".to_string(),
    };
    let mut cultures = Vec::new();
    cultures.push(culture);
    let mut result = Vec::new();
    write_cultures(cultures, &mut result);
    assert_eq!(
        // convert result `[u8; 52]` to a str to avoid `LengthAtMost32` error
        std::str::from_utf8(&result).unwrap(),
        "HEUKWG001 Hericium erinaceus 'UK' (WoodlandGourmet)\n"
    );
}