use serde::Deserialize; use anyhow::Error; use anyhow::Result; use diesel::ExpressionMethods; use diesel::RunQueryDsl; use diesel::query_dsl::methods::FilterDsl; use diesel::Connection; use crate::db::DbPool; use crate::schema::cities; #[derive(Debug, Deserialize, diesel::Identifiable, diesel::Queryable, getset::Getters)] #[table_name = "cities"] pub struct City { pub(super) id: i32, #[getset(get = "pub")] name: String, } #[derive(Insertable)] #[table_name = "cities"] struct NewCity<'a> { name: &'a str } impl City { pub fn create_or_fetch(db: &DbPool, name: &str) -> Result { use crate::schema; let conn = db.get()?; conn.transaction::<_, Error, _>(|| { let new_city = NewCity { name }; diesel::insert_into(schema::cities::table) .values(&new_city) .on_conflict_do_nothing() .execute(&conn)?; schema::cities::table .filter(schema::cities::name.eq(name)) .first::(&conn) .map_err(Error::from) }) } }