uses tips from diesel.rs guide for application integration

This commit is contained in:
2019-06-22 21:55:21 +02:00
parent 99404543b3
commit 5379ad236f
5 changed files with 69 additions and 44 deletions

Binary file not shown.

View File

@@ -6,35 +6,24 @@ extern crate serde_derive;
use diesel::prelude::*; use diesel::prelude::*;
use diesel::r2d2::{self, ConnectionManager}; use diesel::r2d2::{self, ConnectionManager};
// Convenience re-export, maybe DbApi should me move here instead ??
pub use diesel::query_dsl::RunQueryDsl;
pub mod models; mod models;
pub mod schema; mod schema;
pub use models::Item;
pub use models::Player;
pub type DbConnection = SqliteConnection; pub type DbConnection = SqliteConnection;
pub type Pool = r2d2::Pool<ConnectionManager<DbConnection>>; pub type Pool = r2d2::Pool<ConnectionManager<DbConnection>>;
pub type QueryResult<T> = Result<T, diesel::result::Error>; pub type QueryResult<T> = Result<T, diesel::result::Error>;
pub type ActionResult = QueryResult<bool>; pub type ActionResult = QueryResult<bool>;
pub use models::Item;
pub use models::Player;
impl Player { impl Player {
/// Query the list of all players /// Query the list of all players
pub fn fetch_list(conn: &SqliteConnection) -> QueryResult<Vec<Self>> { pub fn fetch_list(conn: &SqliteConnection) -> QueryResult<Vec<Self>> {
use schema::players::dsl::*; Ok( schema::players::table.load::<Self>(conn)? )
Ok( players
.load::<Self>(conn)?
)
}
/// Query the list of items belonging to player
pub fn fetch_loot(player_id: i32, conn: &SqliteConnection) -> QueryResult<Vec<Item>> {
use schema::looted::dsl::*;
Ok( looted
.filter(owner_id.eq(player_id))
.select((id, name, base_price))
.load::<Item>(conn)?
)
} }
pub fn action_claim_object(player_id: i32, item_id: i32, conn: &DbConnection) -> ActionResult { pub fn action_claim_object(player_id: i32, item_id: i32, conn: &DbConnection) -> ActionResult {
@@ -48,8 +37,8 @@ impl Player {
pub fn create_pool() -> Pool { pub fn create_pool() -> Pool {
dbg!(dotenv::dotenv().ok());
let connspec = std::env::var("DATABASE_URL").expect("DATABASE_URL"); let connspec = std::env::var("DATABASE_URL").expect("DATABASE_URL");
dbg!( &connspec );
let manager = ConnectionManager::<DbConnection>::new(connspec); let manager = ConnectionManager::<DbConnection>::new(connspec);
r2d2::Pool::builder() r2d2::Pool::builder()
.build(manager) .build(manager)
@@ -58,23 +47,5 @@ pub fn create_pool() -> Pool {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
fn with_db<F>(f: F) -> ()
where
F: Fn(&SqliteConnection) -> (),
{
let conn = establish_connection().unwrap();
conn.test_transaction::<_, diesel::result::Error, _>(|| {
f(&conn);
Ok(())
});
}
#[test]
fn database_connection() {
use crate::establish_connection;
let conn = establish_connection();
assert_eq!(conn.is_ok(), true);
}
} }

View File

@@ -1,8 +1,64 @@
use crate::*; use diesel::prelude::*;
use diesel::dsl::{Eq, Filter, Select};
use crate::schema::{looted, items};
/// Represents a unique item in inventory
///
/// It is also used as a public representation of Loot, since owner
/// information is implicit.
/// Or maybe this is a little too confusing ??
#[derive(Debug, Queryable, Serialize)] #[derive(Debug, Queryable, Serialize)]
pub struct Item { pub struct Item {
id: i32, id: i32,
name: String, name: String,
base_value: i32, base_price: i32,
}
type ItemColumns = ( looted::id, looted::name, looted::base_price, );
type OwnedBy = Select<OwnedLoot, ItemColumns>;
const ITEM_COLUMNS: ItemColumns = ( looted::id, looted::name, looted::base_price, );
impl Item {
/// Insert this item inside the Looted table.
///
/// This adds a copy of the item into the group chest,
/// to be claimed by players or sold.
/// Returns the id of the looted item (differs from the original id)
pub fn to_looted(self) -> Result<i32, ()>{
// Copy data inside a new Loot
// Set the owner id to 0 (group)
Err(())
}
/// Public proxy for Loot::owned_by that selects only Item fields
pub fn owned_by(player: i32) -> OwnedBy {
Loot::owned_by(player)
.select(ITEM_COLUMNS)
}
}
/// Represents an item that has been looted
#[derive(Debug, Queryable, Serialize)]
struct Loot {
id: i32,
name: String,
base_value: i32,
owner: i32,
}
type WithOwner = Eq<looted::owner_id, i32>;
type OwnedLoot = Filter<looted::table, WithOwner>;
impl Loot {
/// A filter on Loot that is owned by given player
fn owned_by(id: i32) -> OwnedLoot {
looted::table
.filter(looted::owner_id.eq(id))
}
/// Delete the item, returning the gained wealth
fn sell(_modifier: i8) -> Result<i32, ()> {
// Calculate sell value : base_value / 2 * modifier
// Delete recording of loot
Err(())
}
} }

View File

@@ -1,6 +1,4 @@
use crate::schema::players; use crate::schema::players;
use crate::serde_derive::Serialize;
use crate::*;
/// Representation of a player in database /// Representation of a player in database
#[derive(Debug, Queryable, Serialize)] #[derive(Debug, Queryable, Serialize)]

View File

@@ -1,7 +1,7 @@
use actix_web::{web, web::Json, Error, HttpResponse, Result}; use actix_web::{web, web::Json, Error, HttpResponse, Result};
use futures::Future; use futures::Future;
use lootalot_db::{Pool, DbConnection, QueryResult, ActionResult}; use lootalot_db::{RunQueryDsl, Pool, DbConnection, QueryResult, ActionResult};
use lootalot_db::{Item, Player}; use lootalot_db::{Item, Player};
/// A wrapper providing an API over the database /// A wrapper providing an API over the database
@@ -49,7 +49,7 @@ pub struct AsPlayer<'q> {
impl<'q> AsPlayer<'q> { impl<'q> AsPlayer<'q> {
/// Fetch the content of a player's chest /// Fetch the content of a player's chest
pub fn loot(self) -> QueryResult<Vec<Item>> { pub fn loot(self) -> QueryResult<Vec<Item>> {
Player::fetch_loot(self.id, self.conn) dbg!( Ok( Item::owned_by(self.id).load(self.conn)? ) )
} }
/// Put a claim on a specific item /// Put a claim on a specific item
pub fn claim(self, item: i32) -> ActionResult { pub fn claim(self, item: i32) -> ActionResult {