pub(crate) fn resource_and_action(route_name: &str) -> Option<(String, String)> {
let (resource_part, action) = route_name.rsplit_once('.')?;
if resource_part.is_empty() || action.is_empty() {
return None;
}
let resource = resource_part.split('.').map(studly).collect::<String>();
Some((resource, action.to_string()))
}
fn studly(segment: &str) -> String {
let mut chars = segment.chars();
match chars.next() {
None => String::new(),
Some(first) => first.to_uppercase().collect::<String>() + chars.as_str(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn splits_simple_resource_and_action() {
assert_eq!(
resource_and_action("posts.show"),
Some(("Posts".to_string(), "show".to_string()))
);
}
#[test]
fn studly_cases_multi_segment_resource() {
assert_eq!(
resource_and_action("admin.posts.show"),
Some(("AdminPosts".to_string(), "show".to_string()))
);
}
#[test]
fn none_for_name_without_a_dot() {
assert_eq!(resource_and_action("home"), None);
}
#[test]
fn none_for_trailing_dot() {
assert_eq!(resource_and_action("posts."), None);
}
}