use crate::db::models::proposals::ChallengeType;
use crate::db::schema::challenges;
use diesel::backend::Backend;
use diesel::sql_types::{BigInt, Integer, Text};
use diesel::types::FromSql;
use diesel::{ExpressionMethods, Insertable, Queryable};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct ChallengeHighlights {
#[serde(default)]
pub sponsor: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct Challenge {
#[serde(alias = "internalId")]
pub internal_id: i32,
pub id: i32,
#[serde(alias = "challengeType")]
pub challenge_type: ChallengeType,
pub title: String,
pub description: String,
#[serde(alias = "rewardsTotal")]
pub rewards_total: i64,
#[serde(alias = "proposersRewards")]
pub proposers_rewards: i64,
#[serde(alias = "fundId")]
pub fund_id: i32,
#[serde(alias = "challengeUrl")]
pub challenge_url: String,
pub highlights: Option<ChallengeHighlights>,
}
impl<DB: Backend> Queryable<challenges::SqlType, DB> for Challenge
where
i32: FromSql<Integer, DB>,
i64: FromSql<BigInt, DB>,
String: FromSql<Text, DB>,
{
type Row = (
i32,
i32,
String,
String,
String,
i64,
i64,
i32,
String,
Option<String>,
);
fn build(row: Self::Row) -> Self {
Challenge {
internal_id: row.0,
id: row.1,
challenge_type: row.2.parse().unwrap(),
title: row.3,
description: row.4,
rewards_total: row.5,
proposers_rewards: row.6,
fund_id: row.7,
challenge_url: row.8,
highlights: row.9.and_then(|v| serde_json::from_str(&v).ok()),
}
}
}
impl Insertable<challenges::table> for Challenge {
#[allow(clippy::type_complexity)]
type Values = (
diesel::dsl::Eq<challenges::id, i32>,
diesel::dsl::Eq<challenges::challenge_type, String>,
diesel::dsl::Eq<challenges::title, String>,
diesel::dsl::Eq<challenges::description, String>,
diesel::dsl::Eq<challenges::rewards_total, i64>,
diesel::dsl::Eq<challenges::proposers_rewards, i64>,
diesel::dsl::Eq<challenges::fund_id, i32>,
diesel::dsl::Eq<challenges::challenge_url, String>,
diesel::dsl::Eq<challenges::highlights, Option<String>>,
);
fn values(self) -> Self::Values {
(
challenges::id.eq(self.id),
challenges::challenge_type.eq(self.challenge_type.to_string()),
challenges::title.eq(self.title),
challenges::description.eq(self.description),
challenges::rewards_total.eq(self.rewards_total),
challenges::proposers_rewards.eq(self.proposers_rewards),
challenges::fund_id.eq(self.fund_id),
challenges::challenge_url.eq(self.challenge_url),
challenges::highlights.eq(serde_json::to_string(&self.highlights).ok()),
)
}
}
#[cfg(test)]
pub mod test {
use super::*;
use crate::db::{DbConnection, DbConnectionPool};
use diesel::RunQueryDsl;
pub fn get_test_challenge_with_fund_id(fund_id: i32) -> Challenge {
const CHALLENGE_ID: i32 = 9001;
const REWARDS_TOTAL: i64 = 100500;
Challenge {
internal_id: 1,
id: CHALLENGE_ID,
challenge_type: ChallengeType::CommunityChoice,
title: "challenge title".to_string(),
description: "challenge description".to_string(),
rewards_total: REWARDS_TOTAL,
proposers_rewards: REWARDS_TOTAL,
fund_id,
challenge_url: "http://example.com/".to_string(),
highlights: None,
}
}
pub fn populate_db_with_challenge(challenge: &Challenge, pool: &DbConnectionPool) {
let connection = pool.get().unwrap();
populate_db_with_challenge_conn(challenge, &connection);
}
pub fn populate_db_with_challenge_conn(challenge: &Challenge, connection: &DbConnection) {
diesel::insert_into(challenges::table)
.values(challenge.clone().values())
.execute(connection)
.unwrap();
}
}