pub fn snake_case(input: &str) -> String {
let mut out = String::with_capacity(input.len() + 4);
for (i, ch) in input.chars().enumerate() {
if ch.is_uppercase() {
if i != 0 {
out.push('_');
}
for lower in ch.to_lowercase() {
out.push(lower);
}
} else {
out.push(ch);
}
}
out
}
pub fn pluralize(word: &str) -> String {
if word.ends_with('y')
&& !word.ends_with("ay")
&& !word.ends_with("ey")
&& !word.ends_with("oy")
&& !word.ends_with("uy")
{
format!("{}ies", &word[..word.len() - 1])
} else if word.ends_with('s')
|| word.ends_with("x")
|| word.ends_with("ch")
|| word.ends_with("sh")
{
format!("{word}es")
} else {
format!("{word}s")
}
}
pub fn table_name(model: &str) -> String {
pluralize(&snake_case(model))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn snake_cases() {
assert_eq!(snake_case("User"), "user");
assert_eq!(snake_case("BlogPost"), "blog_post");
assert_eq!(snake_case("OAuthToken"), "o_auth_token");
}
#[test]
fn pluralizes() {
assert_eq!(pluralize("user"), "users");
assert_eq!(pluralize("category"), "categories");
assert_eq!(pluralize("box"), "boxes");
assert_eq!(pluralize("day"), "days");
}
#[test]
fn builds_table_names() {
assert_eq!(table_name("User"), "users");
assert_eq!(table_name("BlogPost"), "blog_posts");
assert_eq!(table_name("Category"), "categories");
}
}