Plenty of GraphQL query implementation
Implement query for languages, words, initial implementation for user query
This commit is contained in:
parent
c0b0a53061
commit
ecd8f58542
104
src/db/mod.rs
104
src/db/mod.rs
@ -2,14 +2,32 @@ pub mod models;
|
|||||||
pub mod schema;
|
pub mod schema;
|
||||||
|
|
||||||
use self::models::languages::Language;
|
use self::models::languages::Language;
|
||||||
|
use self::models::users::User;
|
||||||
|
use self::models::words::Word;
|
||||||
use diesel::pg::PgConnection;
|
use diesel::pg::PgConnection;
|
||||||
use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
|
use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
|
||||||
use dotenvy::dotenv;
|
use dotenvy::dotenv;
|
||||||
use std::env;
|
use std::env;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
|
macro_rules! find_element {
|
||||||
|
($conn:expr,$dsl:ident,$type:ty,$value:expr,$errmsg:expr) => {
|
||||||
|
if let Ok(val) = $conn {
|
||||||
|
$dsl.find($value).first::<$type>(val).map_or_else(
|
||||||
|
|e| {
|
||||||
|
info!("{}: {:?}", $errmsg, e);
|
||||||
|
None
|
||||||
|
},
|
||||||
|
Some,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
info!("Failed to obtain connection for the database");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
// use diesel::query_dsl::RunQueryDsl;
|
|
||||||
|
|
||||||
pub struct Database {
|
pub struct Database {
|
||||||
conn: Pool<ConnectionManager<PgConnection>>,
|
conn: Pool<ConnectionManager<PgConnection>>,
|
||||||
@ -17,13 +35,15 @@ pub struct Database {
|
|||||||
|
|
||||||
impl juniper::Context for Database {}
|
impl juniper::Context for Database {}
|
||||||
|
|
||||||
impl Database {
|
impl Default for Database {
|
||||||
pub fn new() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
conn: Database::get_connection_pool(),
|
conn: Database::get_connection_pool(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Database {
|
||||||
pub fn get_connection_pool() -> Pool<ConnectionManager<PgConnection>> {
|
pub fn get_connection_pool() -> Pool<ConnectionManager<PgConnection>> {
|
||||||
dotenv().ok();
|
dotenv().ok();
|
||||||
let database_url =
|
let database_url =
|
||||||
@ -51,23 +71,73 @@ impl Database {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn language(&self, name: &str) -> Option<Language> {
|
pub fn language(&self, name: &str, owner: &str) -> Option<Language> {
|
||||||
use self::schema::languages::dsl::languages;
|
use self::schema::languages::dsl;
|
||||||
match &mut self.conn() {
|
match &mut self.conn() {
|
||||||
Ok(val) => languages
|
Ok(conn) => match dsl::languages
|
||||||
.find(name.to_string())
|
.filter(dsl::name.eq(name))
|
||||||
.first::<Language>(val)
|
.filter(dsl::owner.eq(owner))
|
||||||
.map_or_else(
|
.first::<Language>(conn)
|
||||||
|e| {
|
{
|
||||||
info!(
|
Ok(val) => Some(val),
|
||||||
"Failed to retrieve language {} from database: {:?}",
|
Err(e) => {
|
||||||
name, e
|
info!("Could not retrieve language {} of user {} from database: {:?}",
|
||||||
);
|
name, owner, e);
|
||||||
None
|
None
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Some,
|
Err(e) => {
|
||||||
),
|
info!("Could not connect to the database: {:?}", e);
|
||||||
Err(_) => None,
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn user(&self, id: &str) -> Option<User> {
|
||||||
|
use self::schema::users::dsl::users;
|
||||||
|
find_element!(
|
||||||
|
&mut self.conn(),
|
||||||
|
users,
|
||||||
|
User,
|
||||||
|
id.to_string(),
|
||||||
|
format!("Failed to retrieve user {} from database", id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn word_id(&self, id: &str) -> Option<Word> {
|
||||||
|
use self::schema::words::dsl;
|
||||||
|
if let Ok(conn) = &mut self.conn() {
|
||||||
|
match dsl::words.find(id).first::<Word>(conn) {
|
||||||
|
Ok(val) => Some(val),
|
||||||
|
Err(e) => {
|
||||||
|
info!("Error retrieving {}: {:?}", id, e);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn words(&self, language: &str, word: &str) -> Vec<Word> {
|
||||||
|
use self::schema::words::dsl;
|
||||||
|
if let Ok(conn) = &mut self.conn() {
|
||||||
|
match dsl::words
|
||||||
|
.filter(dsl::language.eq(language))
|
||||||
|
.filter(dsl::norm.eq(word))
|
||||||
|
.load::<Word>(conn)
|
||||||
|
{
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(e) => {
|
||||||
|
info!(
|
||||||
|
"Error retrieving {} from language {}: {:?}",
|
||||||
|
word, language, e
|
||||||
|
);
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,28 @@
|
|||||||
use super::super::schema::{langandagents, languages};
|
use crate::db::Database;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use juniper::GraphQLEnum;
|
use juniper::GraphQLEnum;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
#[derive(diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq, GraphQLEnum)]
|
use super::super::schema;
|
||||||
|
use super::users::User;
|
||||||
|
|
||||||
|
use schema::{langandagents, languages};
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq, GraphQLEnum,
|
||||||
|
)]
|
||||||
#[DieselTypePath = "crate::db::schema::sql_types::Release"]
|
#[DieselTypePath = "crate::db::schema::sql_types::Release"]
|
||||||
pub enum Release {
|
pub enum Release {
|
||||||
Public,
|
Public,
|
||||||
#[graphql(name="NON_COMMERCIAL")]
|
#[graphql(name = "NON_COMMERCIAL")]
|
||||||
NonCommercial,
|
NonCommercial,
|
||||||
Research,
|
Research,
|
||||||
Private,
|
Private,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq, GraphQLEnum)]
|
#[derive(
|
||||||
|
diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq, GraphQLEnum,
|
||||||
|
)]
|
||||||
#[DieselTypePath = "crate::db::schema::sql_types::Dictgenre"]
|
#[DieselTypePath = "crate::db::schema::sql_types::Dictgenre"]
|
||||||
pub enum DictGenre {
|
pub enum DictGenre {
|
||||||
General,
|
General,
|
||||||
@ -24,7 +34,9 @@ pub enum DictGenre {
|
|||||||
Terminology,
|
Terminology,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq, GraphQLEnum)]
|
#[derive(
|
||||||
|
diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq, GraphQLEnum,
|
||||||
|
)]
|
||||||
#[DieselTypePath = "crate::db::schema::sql_types::Agentlanguagerelation"]
|
#[DieselTypePath = "crate::db::schema::sql_types::Agentlanguagerelation"]
|
||||||
pub enum AgentLanguageRelation {
|
pub enum AgentLanguageRelation {
|
||||||
Publisher,
|
Publisher,
|
||||||
@ -46,21 +58,163 @@ pub struct Language {
|
|||||||
owner: String,
|
owner: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[juniper::graphql_object]
|
|
||||||
impl Language {
|
impl Language {
|
||||||
#[graphql(name = "release")]
|
fn relationship(
|
||||||
|
&self,
|
||||||
|
context: &Database,
|
||||||
|
relationship: AgentLanguageRelation,
|
||||||
|
) -> Vec<User> {
|
||||||
|
use schema::langandagents::dsl;
|
||||||
|
match &mut context.conn() {
|
||||||
|
Ok(conn) => dsl::langandagents
|
||||||
|
.filter(dsl::language.eq(self.name.clone()))
|
||||||
|
.filter(dsl::relationship.eq(relationship))
|
||||||
|
.load::<LangAndAgent>(conn)
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|v| {
|
||||||
|
use schema::users::dsl;
|
||||||
|
dsl::users.find(v.agent.clone()).first::<User>(conn)
|
||||||
|
})
|
||||||
|
.filter_map(|author| match author {
|
||||||
|
Ok(val) => Some(val),
|
||||||
|
Err(e) => {
|
||||||
|
info!(
|
||||||
|
"Failed ot retrieve author from database: {:?}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<User>>(),
|
||||||
|
Err(e) => {
|
||||||
|
panic!("Could not connect to the database: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[juniper::graphql_object(Context = Database)]
|
||||||
|
impl Language {
|
||||||
|
#[graphql(
|
||||||
|
description = "Name in the main target language (often English) of the described language"
|
||||||
|
)]
|
||||||
|
fn name(&self) -> String {
|
||||||
|
self.name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "Native name of the language")]
|
||||||
|
fn native() -> Option<String> {
|
||||||
|
self.native.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "How the dictionary is currently released")]
|
||||||
fn release(&self) -> Release {
|
fn release(&self) -> Release {
|
||||||
self.release.clone()
|
self.release.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(name = "created")]
|
#[graphql(
|
||||||
|
name = "targetLanguage",
|
||||||
|
description = "Languages in which the current language is translated"
|
||||||
|
)]
|
||||||
|
fn target_language(&self, context: &Database) -> Vec<Language> {
|
||||||
|
use schema::languages::dsl;
|
||||||
|
match &mut context.conn() {
|
||||||
|
Ok(conn) => self
|
||||||
|
.targetlanguage
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.map(|l| dsl::languages.find(l).first::<Language>(conn))
|
||||||
|
.filter_map(|l| match l {
|
||||||
|
Ok(language) => Some(language),
|
||||||
|
Err(e) => {
|
||||||
|
info!(
|
||||||
|
"Failed to retrieve language from database: {:?}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<Language>>(),
|
||||||
|
Err(e) => {
|
||||||
|
info!("Failed to connect to the database: {:?}", e);
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "What kind of dictionary this is")]
|
||||||
|
fn genre(&self) -> Vec<DictGenre> {
|
||||||
|
self.genre.clone().into_iter().flatten().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(
|
||||||
|
name = "abstract",
|
||||||
|
description = "Short description of the language"
|
||||||
|
)]
|
||||||
|
fn abstract_(&self) -> Option<String> {
|
||||||
|
self.abstract_.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(
|
||||||
|
description = "Time at which the language's dictionary was created"
|
||||||
|
)]
|
||||||
fn created(&self) -> String {
|
fn created(&self) -> String {
|
||||||
self.created.to_string()
|
self.created.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(name = "name")]
|
#[graphql(
|
||||||
fn name(&self) -> String {
|
description = "Longer description of the language, its content can be formatted as Markdown"
|
||||||
self.name.clone()
|
)]
|
||||||
|
fn description(&self) -> Option<String> {
|
||||||
|
self.description.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(
|
||||||
|
description = "Copyrights held by various people over the language's dictionary and its content"
|
||||||
|
)]
|
||||||
|
fn rights(&self) -> Option<String> {
|
||||||
|
self.rights.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "License under which the dictionary is released")]
|
||||||
|
fn license(&self) -> Option<String> {
|
||||||
|
self.license.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(
|
||||||
|
description = "User with administrative rights over the language"
|
||||||
|
)]
|
||||||
|
fn owner(&self, context: &Database) -> User {
|
||||||
|
use schema::users::dsl;
|
||||||
|
match &mut context.conn() {
|
||||||
|
Ok(conn) => dsl::users
|
||||||
|
.find(self.owner.clone())
|
||||||
|
.first::<User>(conn)
|
||||||
|
.unwrap_or_else(|e| {
|
||||||
|
panic!(
|
||||||
|
"Failed to retrieve owner {} of language {}: {:?}",
|
||||||
|
self.owner, self.name, e
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
Err(e) => panic!("Failed to connect to the database: {:?}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(
|
||||||
|
description = "People who participate in the elaboration of the language's dictionary"
|
||||||
|
)]
|
||||||
|
fn authors(&self, context: &Database) -> Vec<User> {
|
||||||
|
self.relationship(context, AgentLanguageRelation::Author)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(
|
||||||
|
description = "People who can and do redistribute the language's dictionary"
|
||||||
|
)]
|
||||||
|
fn publishers(&self, context: &Database) -> Vec<User> {
|
||||||
|
self.relationship(context, AgentLanguageRelation::Publisher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,4 +224,5 @@ pub struct LangAndAgent {
|
|||||||
id: i32,
|
id: i32,
|
||||||
agent: String,
|
agent: String,
|
||||||
language: String,
|
language: String,
|
||||||
|
relationship: AgentLanguageRelation,
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use diesel::prelude::*;
|
|
||||||
use super::super::schema::{userfollows, users};
|
use super::super::schema::{userfollows, users};
|
||||||
|
use diesel::prelude::*;
|
||||||
|
|
||||||
|
use crate::db::Database;
|
||||||
|
|
||||||
#[derive(Queryable, Insertable, Debug, Clone, PartialEq, Eq)]
|
#[derive(Queryable, Insertable, Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
@ -7,14 +9,34 @@ pub struct User {
|
|||||||
pub username: String,
|
pub username: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[juniper::graphql_object]
|
#[juniper::graphql_object(Context = Database)]
|
||||||
impl User {
|
impl User {
|
||||||
pub fn id(&self) -> &str {
|
#[graphql(description = "Appwrite ID of the user")]
|
||||||
self.id.as_str()
|
pub fn id(&self) -> String {
|
||||||
|
self.id.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn username(&self) -> &str {
|
#[graphql(description = "The user's apparent name")]
|
||||||
self.username.as_str()
|
pub fn username(&self) -> String {
|
||||||
|
self.username.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "Who the user follows")]
|
||||||
|
pub fn following(&self, context: &Database) -> Vec<User> {
|
||||||
|
use super::super::schema::{userfollows, users};
|
||||||
|
let conn = &mut context.conn().unwrap();
|
||||||
|
userfollows::dsl::userfollows
|
||||||
|
.filter(userfollows::dsl::follower.eq(self.id.clone()))
|
||||||
|
.load::<UserFollow>(conn)
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|f| {
|
||||||
|
users::dsl::users
|
||||||
|
.find(f.following.clone())
|
||||||
|
.first::<User>(conn)
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.collect::<Vec<User>>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
use super::super::schema::{wordrelation, words};
|
use super::super::schema;
|
||||||
|
use crate::db::Database;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
|
use juniper::GraphQLEnum;
|
||||||
|
use schema::{wordrelation, words};
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
|
use super::languages::Language;
|
||||||
|
|
||||||
#[derive(diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq)]
|
#[derive(diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq)]
|
||||||
#[DieselTypePath = "crate::db::schema::sql_types::Wordrelationship"]
|
#[DieselTypePath = "crate::db::schema::sql_types::Wordrelationship"]
|
||||||
@ -8,13 +14,14 @@ pub enum WordRelationship {
|
|||||||
Related,
|
Related,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq)]
|
#[derive(diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq, GraphQLEnum)]
|
||||||
#[DieselTypePath = "crate::db::schema::sql_types::Partofspeech"]
|
#[DieselTypePath = "crate::db::schema::sql_types::Partofspeech"]
|
||||||
pub enum PartOfSpeech {
|
pub enum PartOfSpeech {
|
||||||
Adjective,
|
Adjective,
|
||||||
Adposition,
|
Adposition,
|
||||||
Adverb,
|
Adverb,
|
||||||
Auxilliary,
|
Auxilliary,
|
||||||
|
#[graphql(name = "COORDINATING_CONJUNCTION")]
|
||||||
CoordConj,
|
CoordConj,
|
||||||
Determiner,
|
Determiner,
|
||||||
Interjection,
|
Interjection,
|
||||||
@ -22,8 +29,10 @@ pub enum PartOfSpeech {
|
|||||||
Numeral,
|
Numeral,
|
||||||
Particle,
|
Particle,
|
||||||
Pronoun,
|
Pronoun,
|
||||||
|
#[graphql(name = "PROPER_NOUN")]
|
||||||
ProperNoun,
|
ProperNoun,
|
||||||
Punctuation,
|
Punctuation,
|
||||||
|
#[graphql(name = "SUBORDINATING_CONJUNCTION")]
|
||||||
SubjConj,
|
SubjConj,
|
||||||
Symbol,
|
Symbol,
|
||||||
Verb,
|
Verb,
|
||||||
@ -46,6 +55,136 @@ pub struct Word {
|
|||||||
morphology: Option<String>,
|
morphology: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Word {
|
||||||
|
fn relationship(&self, context: &Database, relationship: WordRelationship) -> Vec<Word> {
|
||||||
|
use schema::wordrelation::dsl;
|
||||||
|
match &mut context.conn() {
|
||||||
|
Ok(conn) => {
|
||||||
|
dsl::wordrelation
|
||||||
|
.filter(dsl::wordsource.eq(self.norm.clone()))
|
||||||
|
.filter(dsl::relationship.eq(relationship))
|
||||||
|
.load::<WordRelation>(conn)
|
||||||
|
.unwrap()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|w| {
|
||||||
|
use schema::words::dsl;
|
||||||
|
dsl::words.find(w.wordtarget).first::<Word>(conn)
|
||||||
|
})
|
||||||
|
.collect::<Vec<Word>>()
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
info!("Could not connect to database: {:?}", e);
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[juniper::graphql_object(Context = Database)]
|
||||||
|
impl Word {
|
||||||
|
#[graphql(description = "Normal form of the word")]
|
||||||
|
fn norm(&self) -> String {
|
||||||
|
self.norm.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "Native representation of the word")]
|
||||||
|
fn native(&self) -> Option<String> {
|
||||||
|
self.native.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "Base form of the current word")]
|
||||||
|
fn lemma(&self, context: &Database) -> Option<Word> {
|
||||||
|
use schema::words::dsl;
|
||||||
|
match self.lemma.clone() {
|
||||||
|
Some(lemma) => match &mut context.conn() {
|
||||||
|
Ok(conn) => match dsl::words.find(lemma.clone()).first::<Word>(conn) {
|
||||||
|
Ok(word) => Some(word),
|
||||||
|
Err(e) => {
|
||||||
|
info!(
|
||||||
|
"Failed to retrieve lemma {} of word {}: {:?}",
|
||||||
|
lemma, self.norm, e
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
info!("Could not connect to the database: {:?}", e);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "Language to which the word belongs")]
|
||||||
|
fn language(&self, context: &Database) -> Language {
|
||||||
|
use schema::languages::dsl;
|
||||||
|
match &mut context.conn() {
|
||||||
|
Ok(conn) => {
|
||||||
|
match dsl::languages
|
||||||
|
.find(self.language.clone())
|
||||||
|
.first::<Language>(conn)
|
||||||
|
{
|
||||||
|
Ok(lang) => lang,
|
||||||
|
Err(e) => {
|
||||||
|
panic!("Failed to retrieve language {} of word {} from database: {:?}",
|
||||||
|
self.language, self.norm, e
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => panic!("Failed to connect to database: {:?}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(name = "partOfSpeech", description = "Part of speech the word belongs to")]
|
||||||
|
fn part_of_speech(&self) -> PartOfSpeech {
|
||||||
|
self.partofspeech.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "Link to an audio file related to the word")]
|
||||||
|
fn audio(&self) -> Option<String> {
|
||||||
|
self.audio.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "Link to an video file related to the word")]
|
||||||
|
fn video(&self) -> Option<String> {
|
||||||
|
self.video.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "Link to an image file related to the word")]
|
||||||
|
fn image(&self) -> Option<String> {
|
||||||
|
self.image.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "Etymology of the word, can be in Markdown format")]
|
||||||
|
fn etymology(&self) -> Option<String> {
|
||||||
|
self.etymology.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "Usage of the word, can be in Markdown format")]
|
||||||
|
fn usage(&self) -> Option<String> {
|
||||||
|
self.lusage.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[graphql(description = "Morphology of the word, can be in Markdown format")]
|
||||||
|
fn morphology(&self) -> Option<String> {
|
||||||
|
self.morphology.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(name = "related", description = "Words related to the current word")]
|
||||||
|
fn related_words(&self, context: &Database) -> Vec<Word> {
|
||||||
|
self.relationship(context, WordRelationship::Related)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(name = "definitions", description = "Words that define the current word")]
|
||||||
|
fn definitions(&self, context: &Database) -> Vec<Word> {
|
||||||
|
self.relationship(context, WordRelationship::Definition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Queryable, Insertable, Debug, Clone, PartialEq, Eq)]
|
#[derive(Queryable, Insertable, Debug, Clone, PartialEq, Eq)]
|
||||||
#[diesel(table_name = wordrelation)]
|
#[diesel(table_name = wordrelation)]
|
||||||
pub struct WordRelation {
|
pub struct WordRelation {
|
||||||
|
@ -4,7 +4,7 @@ use rocket::State;
|
|||||||
use juniper::EmptySubscription;
|
use juniper::EmptySubscription;
|
||||||
use juniper_rocket::{GraphQLRequest, GraphQLResponse};
|
use juniper_rocket::{GraphQLRequest, GraphQLResponse};
|
||||||
|
|
||||||
use crate::db::models::languages::Language;
|
use crate::db::models::{languages::Language, users::User, words::Word};
|
||||||
use crate::db::Database;
|
use crate::db::Database;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -17,8 +17,32 @@ impl Query {
|
|||||||
context.all_languages().unwrap()
|
context.all_languages().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn language(context: &Database, name: String) -> Option<Language> {
|
#[graphql(
|
||||||
context.language(name.as_str())
|
description = "Retrieve a specific language from its name and its owner's id"
|
||||||
|
)]
|
||||||
|
fn language(
|
||||||
|
context: &Database,
|
||||||
|
name: String,
|
||||||
|
owner: String,
|
||||||
|
) -> Option<Language> {
|
||||||
|
context.language(name.as_str(), owner.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "Retrieve a specific user from its id")]
|
||||||
|
fn user(context: &Database, id: String) -> Option<User> {
|
||||||
|
context.user(id.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(description = "Retrieve a specific word from its id")]
|
||||||
|
fn word(context: &Database, id: String) -> Option<Word> {
|
||||||
|
context.word_id(id.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(
|
||||||
|
description = "Retrieve all words with a set normal form from a set language"
|
||||||
|
)]
|
||||||
|
fn words(context: &Database, language: String, word: String) -> Vec<Word> {
|
||||||
|
context.words(language.as_str(), word.as_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +55,8 @@ impl Mutation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Schema = juniper::RootNode<'static, Query, Mutation, EmptySubscription<Database>>;
|
type Schema =
|
||||||
|
juniper::RootNode<'static, Query, Mutation, EmptySubscription<Database>>;
|
||||||
|
|
||||||
pub fn create_schema() -> Schema {
|
pub fn create_schema() -> Schema {
|
||||||
Schema::new(Query {}, Mutation {}, EmptySubscription::default())
|
Schema::new(Query {}, Mutation {}, EmptySubscription::default())
|
||||||
@ -57,7 +82,7 @@ pub async fn get_graphql_handler(
|
|||||||
pub fn post_graphql_handler(
|
pub fn post_graphql_handler(
|
||||||
context: &State<Database>,
|
context: &State<Database>,
|
||||||
request: GraphQLRequest,
|
request: GraphQLRequest,
|
||||||
schema: &State<Schema>
|
schema: &State<Schema>,
|
||||||
) -> GraphQLResponse {
|
) -> GraphQLResponse {
|
||||||
request.execute_sync(schema, context)
|
request.execute_sync(schema, context)
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
#[allow(clippy::let_underscore_drop, clippy::no_effect_underscore_binding)]
|
#[allow(clippy::let_underscore_drop, clippy::no_effect_underscore_binding)]
|
||||||
let _ = rocket::build()
|
let _ = rocket::build()
|
||||||
.attach(cors)
|
.attach(cors)
|
||||||
.manage(db::Database::new())
|
.manage(db::Database::default())
|
||||||
.manage(create_schema())
|
.manage(create_schema())
|
||||||
.mount(
|
.mount(
|
||||||
"/",
|
"/",
|
||||||
|
Loading…
Reference in New Issue
Block a user