Is the Repository pattern a viable pattern in Rust?

When dealing with databases I'm used to using a sort of Repository pattern (a simplefied version of it), and I wondered if that is viable in rust and it led me in this direction (see below). However, this pattern is very OO and I don't know if it's a god fit for Rust. Looking for some feedback on this or if anyone has a more "Rusty" solution to seperate out database access when a ORM like Diesel would be overkill?


fn main() {

    let mut repo = repository::Repository::init();
    let orders = repo.orders();

    orders.add(10);
    orders.delete(10);

    println!("{}", repo.commit());
}


mod repository {
    use std::cell::RefCell;
    use std::rc::Rc;

    pub struct Repository {
        order_repo: OrderRepository,
        conn: Rc<RefCell<Connection>>,
    }

    impl Repository {
        pub fn init() -> Repository {
            let conn = Rc::new(RefCell::new(Connection::default()));
            Repository {
                order_repo: OrderRepository::new(conn.clone()),
                conn,
            }
        }

        pub fn orders(&mut self) -> &mut OrderRepository {
            &mut self.order_repo
        }

        pub fn commit(&self) -> String {
            let conn = self.conn.clone();
            let conn = (*conn).borrow();
            conn.commit().to_string()
        }
    }

    #[derive(Default)]
    pub struct OrderRepository {
        conn: Rc<RefCell<Connection>>,
    }
    
    impl OrderRepository {
        fn new(conn: Rc<RefCell<Connection>>) -> Self {
            OrderRepository { conn }
        }
        pub fn add(&self, id: i32) {
            let conn = self.conn.clone();
            let mut conn = (*conn).borrow_mut();
            let op = format!("Operation: Added item with id: {}", id);
            conn.add_transaction(op.as_str());
        }

        pub fn delete(&self, id: i32) {
            let conn = self.conn.clone();
            let mut conn = (*conn).borrow_mut();
            let op = format!("Operation: Deleted item with id: {}", id);
            conn.add_transaction(op.as_str());
        }
    }

    // MOCKS
    #[derive(Default)]
    struct Connection {
        transaction: String,
    }

    impl Connection {
        pub fn add_transaction(&mut self, op: &str) {
            self.transaction += op;
            self.transaction += "\n";
        }

        pub fn commit(&self) -> &str {
            &self.transaction
        }
    }

}

(Playground)

Output:

Operation: Added item with id: 10
Operation: Deleted item with id: 10


Errors:

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.91s
     Running `target/debug/playground`

1 Like

Did you find an answer? Are you using this pattern successfully?