Skip to content

Commit f5c75e2

Browse files
committed
models/user: Extract insert_or_update() fn
1 parent 61dfe02 commit f5c75e2

File tree

1 file changed

+31
-25
lines changed

1 file changed

+31
-25
lines changed

src/models/user.rs

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use bon::Builder;
22
use chrono::NaiveDateTime;
3+
use diesel::dsl::sql;
34
use diesel::prelude::*;
5+
use diesel::sql_types::Integer;
6+
use diesel::upsert::excluded;
47
use diesel_async::scoped_futures::ScopedFutureExt;
58
use diesel_async::{AsyncConnection, AsyncPgConnection, RunQueryDsl};
69

@@ -119,39 +122,42 @@ pub struct NewUser<'a> {
119122

120123
impl<'a> NewUser<'a> {
121124
/// Inserts the user into the database, or updates an existing one.
125+
pub async fn insert_or_update(&self, conn: &mut AsyncPgConnection) -> QueryResult<User> {
126+
diesel::insert_into(users::table)
127+
.values(self)
128+
// We need the `WHERE gh_id > 0` condition here because `gh_id` set
129+
// to `-1` indicates that we were unable to find a GitHub ID for
130+
// the associated GitHub login at the time that we backfilled
131+
// GitHub IDs. Therefore, there are multiple records in production
132+
// that have a `gh_id` of `-1` so we need to exclude those when
133+
// considering uniqueness of `gh_id` values. The `> 0` condition isn't
134+
// necessary for most fields in the database to be used as a conflict
135+
// target :)
136+
.on_conflict(sql::<Integer>("(gh_id) WHERE gh_id > 0"))
137+
.do_update()
138+
.set((
139+
users::gh_login.eq(excluded(users::gh_login)),
140+
users::name.eq(excluded(users::name)),
141+
users::gh_avatar.eq(excluded(users::gh_avatar)),
142+
users::gh_access_token.eq(excluded(users::gh_access_token)),
143+
))
144+
.get_result(conn)
145+
.await
146+
}
147+
148+
/// Inserts the user into the database, or updates an existing one.
149+
///
150+
/// This method also inserts the email address into the `emails` table
151+
/// and sends a confirmation email to the user.
122152
pub async fn create_or_update(
123153
&self,
124154
email: Option<&'a str>,
125155
emails: &Emails,
126156
conn: &mut AsyncPgConnection,
127157
) -> QueryResult<User> {
128-
use diesel::dsl::sql;
129-
use diesel::insert_into;
130-
use diesel::pg::upsert::excluded;
131-
use diesel::sql_types::Integer;
132-
133158
conn.transaction(|conn| {
134159
async move {
135-
let user: User = insert_into(users::table)
136-
.values(self)
137-
// We need the `WHERE gh_id > 0` condition here because `gh_id` set
138-
// to `-1` indicates that we were unable to find a GitHub ID for
139-
// the associated GitHub login at the time that we backfilled
140-
// GitHub IDs. Therefore, there are multiple records in production
141-
// that have a `gh_id` of `-1` so we need to exclude those when
142-
// considering uniqueness of `gh_id` values. The `> 0` condition isn't
143-
// necessary for most fields in the database to be used as a conflict
144-
// target :)
145-
.on_conflict(sql::<Integer>("(gh_id) WHERE gh_id > 0"))
146-
.do_update()
147-
.set((
148-
users::gh_login.eq(excluded(users::gh_login)),
149-
users::name.eq(excluded(users::name)),
150-
users::gh_avatar.eq(excluded(users::gh_avatar)),
151-
users::gh_access_token.eq(excluded(users::gh_access_token)),
152-
))
153-
.get_result(conn)
154-
.await?;
160+
let user = self.insert_or_update(conn).await?;
155161

156162
// To send the user an account verification email
157163
if let Some(user_email) = email {

0 commit comments

Comments
 (0)