rustrails_record/
strict_loading.rs1#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq)]
3#[error("`{association}` was lazily loaded on `{model}` which has strict_loading enabled")]
4pub struct StrictLoadingViolation {
5 pub model: String,
7 pub association: String,
9}
10
11pub trait StrictLoading {
13 fn strict_loading(&self) -> bool;
15
16 fn set_strict_loading(&mut self, enabled: bool);
18
19 fn check_strict_loading(&self, association: &str) -> Result<(), StrictLoadingViolation> {
21 if self.strict_loading() {
22 let model = std::any::type_name::<Self>()
23 .rsplit("::")
24 .next()
25 .map_or_else(|| "unknown".to_owned(), str::to_owned);
26
27 return Err(StrictLoadingViolation {
28 model,
29 association: association.to_owned(),
30 });
31 }
32
33 Ok(())
34 }
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
39pub struct StrictLoadingState {
40 enabled: bool,
41}
42
43impl StrictLoadingState {
44 #[must_use]
46 pub fn new() -> Self {
47 Self::default()
48 }
49
50 #[must_use]
52 pub fn enabled() -> Self {
53 Self { enabled: true }
54 }
55
56 #[must_use]
58 pub fn is_enabled(&self) -> bool {
59 self.enabled
60 }
61
62 pub fn set(&mut self, enabled: bool) {
64 self.enabled = enabled;
65 }
66}
67
68impl StrictLoading for StrictLoadingState {
69 fn strict_loading(&self) -> bool {
70 self.is_enabled()
71 }
72
73 fn set_strict_loading(&mut self, enabled: bool) {
74 self.set(enabled);
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::{StrictLoading, StrictLoadingState, StrictLoadingViolation};
81
82 #[test]
83 fn strict_loading_state_new_is_disabled_by_default() {
84 let state = StrictLoadingState::new();
85
86 assert!(!state.is_enabled());
87 assert!(!state.strict_loading());
88 }
89
90 #[test]
91 fn strict_loading_state_enabled_is_enabled() {
92 let state = StrictLoadingState::enabled();
93
94 assert!(state.is_enabled());
95 assert!(state.strict_loading());
96 }
97
98 #[test]
99 fn check_strict_loading_on_enabled_state_returns_violation() {
100 let state = StrictLoadingState::enabled();
101
102 let error = state
103 .check_strict_loading("comments")
104 .expect_err("enabled strict loading should reject lazy loads");
105
106 assert_eq!(
107 error,
108 StrictLoadingViolation {
109 model: "StrictLoadingState".to_owned(),
110 association: "comments".to_owned(),
111 }
112 );
113 }
114
115 #[test]
116 fn check_strict_loading_on_disabled_state_returns_ok() {
117 let state = StrictLoadingState::new();
118
119 assert!(state.check_strict_loading("comments").is_ok());
120 }
121}