transaction_diesel/
lib.rs

1//! A transaction runner for diesel
2
3extern crate diesel;
4extern crate transaction;
5use transaction::*;
6use std::marker::PhantomData;
7
8/// run the given function insed a transaction using the given connection.
9pub fn run<'a, Cn, T, E, Tx>(cn: &'a Cn, tx: Tx) -> Result<T, E>
10where
11    Cn: diesel::Connection,
12    E: From<diesel::result::Error>,
13    Tx: Transaction<Ctx = DieselContext<'a, Cn>, Item = T, Err = E>,
14{
15    cn.clone().transaction(
16        || tx.run(&mut DieselContext::new(cn)),
17    )
18}
19
20/// run the given function insed a transaction using the given connection but do not commit it.
21/// Panics if the given function returns an Err.
22/// This is usefull for testing
23pub fn test_run<'a, Cn, T, E, Tx>(cn: &'a Cn, tx: Tx) -> T
24where
25    Cn: diesel::Connection,
26    E: From<diesel::result::Error>,
27    Tx: Transaction<Ctx = DieselContext<'a, Cn>, Item = T, Err = E>,
28{
29    cn.clone().test_transaction(
30        || tx.run(&mut DieselContext::new(cn)),
31    )
32}
33
34/// diesel transaction object.
35pub struct DieselContext<'a, Cn: 'a> {
36    conn: &'a Cn,
37    _phantom: PhantomData<()>,
38}
39
40impl<'a, Cn> DieselContext<'a, Cn> {
41    // never pub this function
42    fn new(conn: &'a Cn) -> Self {
43        DieselContext {
44            conn: conn,
45            _phantom: PhantomData,
46        }
47    }
48
49    fn conn(&self) -> &'a Cn {
50        &self.conn
51    }
52}
53
54/// Receive the connection from the executing transaction and perform computation.
55pub fn with_conn<'a, Conn, F, T, E>(f: F) -> WithConn<'a, Conn, F>
56where
57    F: Fn(&'a Conn) -> Result<T, E>,
58{
59    WithConn {
60        f: f,
61        _phantom: PhantomData,
62    }
63}
64
65/// The result of `with_conn`
66#[derive(Debug)]
67pub struct WithConn<'a, Conn: 'a, F> {
68    f: F,
69    _phantom: PhantomData<&'a Conn>,
70}
71
72impl<'a, Conn, T, E, F> Transaction for WithConn<'a, Conn, F>
73where
74    F: Fn(&'a Conn) -> Result<T, E>,
75{
76    type Ctx = DieselContext<'a, Conn>;
77    type Item = T;
78    type Err = E;
79    fn run(&self, ctx: &mut DieselContext<'a, Conn>) -> Result<Self::Item, Self::Err> {
80        (self.f)(ctx.conn())
81    }
82}