Change Serials to UUIDs, fix translation table
Languages now refer to other languages they are translated to through an additional table rather than an array of identifiers. This ensures no orphan identifier remains when a language is deleted. The primary key of languages is now a unique identifier rather than the name of the language itself. It now allows for multiple languages to have the same name. Their unique identifier is now a v4 UUID. Set Diesel to specific version 2.0.2, since 2.0 apparently does not mean the latest version of 2.0.z and 2.0 has issues with its uuid feature. Cleanup and simplify some code. Some more GraphQL documentation on available queries.
This commit is contained in:
parent
eb48924761
commit
5c199e2628
@ -16,9 +16,11 @@ publish = false
|
|||||||
dotenvy = "0.15"
|
dotenvy = "0.15"
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
diesel = { version = "2.0", features = ["postgres", "chrono", "r2d2"] }
|
diesel = { version = "2.0.2", features = ["postgres", "chrono", "r2d2", "uuid"] }
|
||||||
diesel-derive-enum = { version = "2.0.0-rc.0", features = ["postgres"] }
|
diesel-derive-enum = { version = "2.0.0-rc.0", features = ["postgres"] }
|
||||||
|
# DB types
|
||||||
chrono = "0.4.23"
|
chrono = "0.4.23"
|
||||||
|
uuid = { version = "1.2.2", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] }
|
||||||
|
|
||||||
# Web server
|
# Web server
|
||||||
rocket = "0.5.0-rc.2"
|
rocket = "0.5.0-rc.2"
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
-- This file should undo anything in `up.sql`
|
-- This file should undo anything in `up.sql`
|
||||||
DROP TABLE LangAndAgents;
|
DROP TABLE LangAndAgents;
|
||||||
|
DROP TABLE LangTranslatesTo;
|
||||||
DROP TABLE Languages;
|
DROP TABLE Languages;
|
||||||
DROP TYPE Release;
|
DROP TYPE Release;
|
||||||
DROP TYPE DictGenre;
|
DROP TYPE DictGenre;
|
||||||
DROP TYPE AgentLanguageRelation;
|
DROP TYPE AgentLanguageRelation;
|
||||||
|
DROP EXTENSION "uuid-ossp";
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
-- Your SQL goes here
|
-- Your SQL goes here
|
||||||
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
|
||||||
CREATE TYPE Release as ENUM ('PUBLIC', 'NONCOMMERCIAL', 'RESEARCH', 'PRIVATE');
|
CREATE TYPE Release as ENUM ('PUBLIC', 'NONCOMMERCIAL', 'RESEARCH', 'PRIVATE');
|
||||||
CREATE TYPE DictGenre as ENUM ('gen', 'lrn', 'ety', 'spe', 'his', 'ort', 'trm');
|
CREATE TYPE DictGenre as ENUM ('gen', 'lrn', 'ety', 'spe', 'his', 'ort', 'trm');
|
||||||
CREATE TYPE AgentLanguageRelation as ENUM ('publisher', 'author');
|
CREATE TYPE AgentLanguageRelation as ENUM ('publisher', 'author');
|
||||||
|
|
||||||
CREATE TABLE Languages (
|
CREATE TABLE Languages (
|
||||||
name VARCHAR(255) PRIMARY KEY,
|
id UUID DEFAULT uuid_generate_v4 () PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
native VARCHAR(255),
|
native VARCHAR(255),
|
||||||
release Release NOT NULL,
|
release Release NOT NULL,
|
||||||
targetLanguage TEXT[] NOT NULL,
|
|
||||||
genre DictGenre[] NOT NULL,
|
genre DictGenre[] NOT NULL,
|
||||||
abstract TEXT,
|
abstract TEXT,
|
||||||
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||||
@ -21,6 +23,20 @@ CREATE TABLE Languages (
|
|||||||
NOT NULL
|
NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE LangTranslatesTo (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
langfrom UUID
|
||||||
|
REFERENCES Languages(id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE CASCADE
|
||||||
|
NOT NULL,
|
||||||
|
langto UUID
|
||||||
|
REFERENCES Languages(id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE CASCADE
|
||||||
|
NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE LangAndAgents (
|
CREATE TABLE LangAndAgents (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
agent VARCHAR(31)
|
agent VARCHAR(31)
|
||||||
@ -28,8 +44,8 @@ CREATE TABLE LangAndAgents (
|
|||||||
ON UPDATE CASCADE
|
ON UPDATE CASCADE
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
NOT NULL,
|
NOT NULL,
|
||||||
language VARCHAR(255)
|
language UUID
|
||||||
REFERENCES Languages(name)
|
REFERENCES Languages(id)
|
||||||
ON UPDATE CASCADE
|
ON UPDATE CASCADE
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
NOT NULL,
|
NOT NULL,
|
||||||
|
@ -9,8 +9,8 @@ CREATE TABLE Words (
|
|||||||
REFERENCES Words(norm)
|
REFERENCES Words(norm)
|
||||||
ON UPDATE CASCADE
|
ON UPDATE CASCADE
|
||||||
ON DELETE SET NULL,
|
ON DELETE SET NULL,
|
||||||
language VARCHAR(255)
|
language UUID
|
||||||
REFERENCES Languages(name)
|
REFERENCES Languages(id)
|
||||||
ON UPDATE CASCADE
|
ON UPDATE CASCADE
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
NOT NULL,
|
NOT NULL,
|
||||||
|
@ -119,7 +119,7 @@ impl Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn words(&self, language: &str, word: &str) -> Vec<Word> {
|
pub fn words(&self, language: uuid::Uuid, word: &str) -> Vec<Word> {
|
||||||
use self::schema::words::dsl;
|
use self::schema::words::dsl;
|
||||||
if let Ok(conn) = &mut self.conn() {
|
if let Ok(conn) = &mut self.conn() {
|
||||||
match dsl::words
|
match dsl::words
|
||||||
|
@ -3,10 +3,12 @@ use diesel::prelude::*;
|
|||||||
use juniper::GraphQLEnum;
|
use juniper::GraphQLEnum;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::super::schema;
|
use super::super::schema;
|
||||||
use super::users::User;
|
use super::users::User;
|
||||||
|
|
||||||
use schema::{langandagents, languages};
|
use schema::{langandagents, langtranslatesto, languages};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq, GraphQLEnum,
|
diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq, GraphQLEnum,
|
||||||
@ -43,12 +45,12 @@ pub enum AgentLanguageRelation {
|
|||||||
Author,
|
Author,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Queryable, Insertable, Debug, Clone, PartialEq, Eq)]
|
#[derive(Queryable, Insertable, Debug, Clone)]
|
||||||
pub struct Language {
|
pub struct Language {
|
||||||
|
id: Uuid,
|
||||||
name: String,
|
name: String,
|
||||||
native: Option<String>,
|
native: Option<String>,
|
||||||
release: Release,
|
release: Release,
|
||||||
targetlanguage: Vec<Option<String>>,
|
|
||||||
genre: Vec<Option<DictGenre>>,
|
genre: Vec<Option<DictGenre>>,
|
||||||
abstract_: Option<String>,
|
abstract_: Option<String>,
|
||||||
created: chrono::NaiveDateTime,
|
created: chrono::NaiveDateTime,
|
||||||
@ -67,7 +69,7 @@ impl Language {
|
|||||||
use schema::langandagents::dsl;
|
use schema::langandagents::dsl;
|
||||||
match &mut context.conn() {
|
match &mut context.conn() {
|
||||||
Ok(conn) => dsl::langandagents
|
Ok(conn) => dsl::langandagents
|
||||||
.filter(dsl::language.eq(self.name.clone()))
|
.filter(dsl::language.eq(self.id))
|
||||||
.filter(dsl::relationship.eq(relationship))
|
.filter(dsl::relationship.eq(relationship))
|
||||||
.load::<LangAndAgent>(conn)
|
.load::<LangAndAgent>(conn)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -97,6 +99,11 @@ impl Language {
|
|||||||
|
|
||||||
#[juniper::graphql_object(Context = Database)]
|
#[juniper::graphql_object(Context = Database)]
|
||||||
impl Language {
|
impl Language {
|
||||||
|
#[graphql(description = "Unique identifier of the language")]
|
||||||
|
fn id(&self) -> String {
|
||||||
|
self.id.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
#[graphql(
|
#[graphql(
|
||||||
description = "Name in the main target language (often English) of the described language"
|
description = "Name in the main target language (often English) of the described language"
|
||||||
)]
|
)]
|
||||||
@ -119,23 +126,16 @@ impl Language {
|
|||||||
description = "Languages in which the current language is translated"
|
description = "Languages in which the current language is translated"
|
||||||
)]
|
)]
|
||||||
fn target_language(&self, context: &Database) -> Vec<Language> {
|
fn target_language(&self, context: &Database) -> Vec<Language> {
|
||||||
use schema::languages::dsl;
|
use schema::langtranslatesto::dsl;
|
||||||
match &mut context.conn() {
|
match &mut context.conn() {
|
||||||
Ok(conn) => self
|
Ok(conn) => dsl::langtranslatesto
|
||||||
.targetlanguage
|
.filter(dsl::langfrom.eq(self.id))
|
||||||
.clone()
|
.load::<LangTranslatesTo>(conn)
|
||||||
|
.unwrap()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flat_map(|l| {
|
||||||
.map(|l| dsl::languages.find(l).first::<Language>(conn))
|
use schema::languages::dsl;
|
||||||
.filter_map(|l| match l {
|
dsl::languages.find(l.langto).first::<Language>(conn)
|
||||||
Ok(language) => Some(language),
|
|
||||||
Err(e) => {
|
|
||||||
info!(
|
|
||||||
"Failed to retrieve language from database: {:?}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect::<Vec<Language>>(),
|
.collect::<Vec<Language>>(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -223,6 +223,14 @@ impl Language {
|
|||||||
pub struct LangAndAgent {
|
pub struct LangAndAgent {
|
||||||
id: i32,
|
id: i32,
|
||||||
agent: String,
|
agent: String,
|
||||||
language: String,
|
language: Uuid,
|
||||||
relationship: AgentLanguageRelation,
|
relationship: AgentLanguageRelation,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Queryable, Insertable, Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[diesel(table_name = langtranslatesto)]
|
||||||
|
pub struct LangTranslatesTo {
|
||||||
|
id: i32,
|
||||||
|
langfrom: Uuid,
|
||||||
|
langto: Uuid,
|
||||||
|
}
|
||||||
|
@ -14,7 +14,9 @@ pub enum WordRelationship {
|
|||||||
Related,
|
Related,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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::Partofspeech"]
|
#[DieselTypePath = "crate::db::schema::sql_types::Partofspeech"]
|
||||||
pub enum PartOfSpeech {
|
pub enum PartOfSpeech {
|
||||||
Adjective,
|
Adjective,
|
||||||
@ -44,7 +46,7 @@ pub struct Word {
|
|||||||
norm: String,
|
norm: String,
|
||||||
native: Option<String>,
|
native: Option<String>,
|
||||||
lemma: Option<String>,
|
lemma: Option<String>,
|
||||||
language: String,
|
language: uuid::Uuid,
|
||||||
partofspeech: PartOfSpeech,
|
partofspeech: PartOfSpeech,
|
||||||
audio: Option<String>,
|
audio: Option<String>,
|
||||||
video: Option<String>,
|
video: Option<String>,
|
||||||
@ -56,11 +58,14 @@ pub struct Word {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Word {
|
impl Word {
|
||||||
fn relationship(&self, context: &Database, relationship: WordRelationship) -> Vec<Word> {
|
fn relationship(
|
||||||
|
&self,
|
||||||
|
context: &Database,
|
||||||
|
relationship: WordRelationship,
|
||||||
|
) -> Vec<Word> {
|
||||||
use schema::wordrelation::dsl;
|
use schema::wordrelation::dsl;
|
||||||
match &mut context.conn() {
|
match &mut context.conn() {
|
||||||
Ok(conn) => {
|
Ok(conn) => dsl::wordrelation
|
||||||
dsl::wordrelation
|
|
||||||
.filter(dsl::wordsource.eq(self.norm.clone()))
|
.filter(dsl::wordsource.eq(self.norm.clone()))
|
||||||
.filter(dsl::relationship.eq(relationship))
|
.filter(dsl::relationship.eq(relationship))
|
||||||
.load::<WordRelation>(conn)
|
.load::<WordRelation>(conn)
|
||||||
@ -70,15 +75,13 @@ impl Word {
|
|||||||
use schema::words::dsl;
|
use schema::words::dsl;
|
||||||
dsl::words.find(w.wordtarget).first::<Word>(conn)
|
dsl::words.find(w.wordtarget).first::<Word>(conn)
|
||||||
})
|
})
|
||||||
.collect::<Vec<Word>>()
|
.collect::<Vec<Word>>(),
|
||||||
},
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
info!("Could not connect to database: {:?}", e);
|
info!("Could not connect to database: {:?}", e);
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[juniper::graphql_object(Context = Database)]
|
#[juniper::graphql_object(Context = Database)]
|
||||||
@ -98,7 +101,8 @@ impl Word {
|
|||||||
use schema::words::dsl;
|
use schema::words::dsl;
|
||||||
match self.lemma.clone() {
|
match self.lemma.clone() {
|
||||||
Some(lemma) => match &mut context.conn() {
|
Some(lemma) => match &mut context.conn() {
|
||||||
Ok(conn) => match dsl::words.find(lemma.clone()).first::<Word>(conn) {
|
Ok(conn) => {
|
||||||
|
match dsl::words.find(lemma.clone()).first::<Word>(conn) {
|
||||||
Ok(word) => Some(word),
|
Ok(word) => Some(word),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
info!(
|
info!(
|
||||||
@ -107,7 +111,8 @@ impl Word {
|
|||||||
);
|
);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
info!("Could not connect to the database: {:?}", e);
|
info!("Could not connect to the database: {:?}", e);
|
||||||
None
|
None
|
||||||
@ -122,9 +127,7 @@ impl Word {
|
|||||||
use schema::languages::dsl;
|
use schema::languages::dsl;
|
||||||
match &mut context.conn() {
|
match &mut context.conn() {
|
||||||
Ok(conn) => {
|
Ok(conn) => {
|
||||||
match dsl::languages
|
match dsl::languages.find(self.language).first::<Language>(conn)
|
||||||
.find(self.language.clone())
|
|
||||||
.first::<Language>(conn)
|
|
||||||
{
|
{
|
||||||
Ok(lang) => lang,
|
Ok(lang) => lang,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -138,7 +141,10 @@ impl Word {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(name = "partOfSpeech", description = "Part of speech the word belongs to")]
|
#[graphql(
|
||||||
|
name = "partOfSpeech",
|
||||||
|
description = "Part of speech the word belongs to"
|
||||||
|
)]
|
||||||
fn part_of_speech(&self) -> PartOfSpeech {
|
fn part_of_speech(&self) -> PartOfSpeech {
|
||||||
self.partofspeech.clone()
|
self.partofspeech.clone()
|
||||||
}
|
}
|
||||||
@ -168,18 +174,25 @@ impl Word {
|
|||||||
self.lusage.clone()
|
self.lusage.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[graphql(
|
||||||
#[graphql(description = "Morphology of the word, can be in Markdown format")]
|
description = "Morphology of the word, can be in Markdown format"
|
||||||
|
)]
|
||||||
fn morphology(&self) -> Option<String> {
|
fn morphology(&self) -> Option<String> {
|
||||||
self.morphology.clone()
|
self.morphology.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(name = "related", description = "Words related to the current word")]
|
#[graphql(
|
||||||
|
name = "related",
|
||||||
|
description = "Words related to the current word"
|
||||||
|
)]
|
||||||
fn related_words(&self, context: &Database) -> Vec<Word> {
|
fn related_words(&self, context: &Database) -> Vec<Word> {
|
||||||
self.relationship(context, WordRelationship::Related)
|
self.relationship(context, WordRelationship::Related)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(name = "definitions", description = "Words that define the current word")]
|
#[graphql(
|
||||||
|
name = "definitions",
|
||||||
|
description = "Words that define the current word"
|
||||||
|
)]
|
||||||
fn definitions(&self, context: &Database) -> Vec<Word> {
|
fn definitions(&self, context: &Database) -> Vec<Word> {
|
||||||
self.relationship(context, WordRelationship::Definition)
|
self.relationship(context, WordRelationship::Definition)
|
||||||
}
|
}
|
||||||
|
@ -29,21 +29,29 @@ diesel::table! {
|
|||||||
langandagents (id) {
|
langandagents (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
agent -> Varchar,
|
agent -> Varchar,
|
||||||
language -> Varchar,
|
language -> Uuid,
|
||||||
relationship -> Agentlanguagerelation,
|
relationship -> Agentlanguagerelation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
langtranslatesto (id) {
|
||||||
|
id -> Int4,
|
||||||
|
langfrom -> Uuid,
|
||||||
|
langto -> Uuid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
use diesel::sql_types::*;
|
use diesel::sql_types::*;
|
||||||
use super::sql_types::Release;
|
use super::sql_types::Release;
|
||||||
use super::sql_types::Dictgenre;
|
use super::sql_types::Dictgenre;
|
||||||
|
|
||||||
languages (name) {
|
languages (id) {
|
||||||
|
id -> Uuid,
|
||||||
name -> Varchar,
|
name -> Varchar,
|
||||||
native -> Nullable<Varchar>,
|
native -> Nullable<Varchar>,
|
||||||
release -> Release,
|
release -> Release,
|
||||||
targetlanguage -> Array<Nullable<Text>>,
|
|
||||||
genre -> Array<Nullable<Dictgenre>>,
|
genre -> Array<Nullable<Dictgenre>>,
|
||||||
#[sql_name = "abstract"]
|
#[sql_name = "abstract"]
|
||||||
abstract_ -> Nullable<Text>,
|
abstract_ -> Nullable<Text>,
|
||||||
@ -90,7 +98,7 @@ diesel::table! {
|
|||||||
norm -> Varchar,
|
norm -> Varchar,
|
||||||
native -> Nullable<Varchar>,
|
native -> Nullable<Varchar>,
|
||||||
lemma -> Nullable<Varchar>,
|
lemma -> Nullable<Varchar>,
|
||||||
language -> Varchar,
|
language -> Uuid,
|
||||||
partofspeech -> Partofspeech,
|
partofspeech -> Partofspeech,
|
||||||
audio -> Nullable<Varchar>,
|
audio -> Nullable<Varchar>,
|
||||||
video -> Nullable<Varchar>,
|
video -> Nullable<Varchar>,
|
||||||
@ -109,6 +117,7 @@ diesel::joinable!(words -> languages (language));
|
|||||||
|
|
||||||
diesel::allow_tables_to_appear_in_same_query!(
|
diesel::allow_tables_to_appear_in_same_query!(
|
||||||
langandagents,
|
langandagents,
|
||||||
|
langtranslatesto,
|
||||||
languages,
|
languages,
|
||||||
userfollows,
|
userfollows,
|
||||||
users,
|
users,
|
||||||
|
@ -7,6 +7,8 @@ use juniper_rocket::{GraphQLRequest, GraphQLResponse};
|
|||||||
use crate::db::models::{languages::Language, users::User, words::Word};
|
use crate::db::models::{languages::Language, users::User, words::Word};
|
||||||
use crate::db::Database;
|
use crate::db::Database;
|
||||||
|
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Query;
|
pub struct Query;
|
||||||
|
|
||||||
@ -21,7 +23,11 @@ impl Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(
|
#[graphql(
|
||||||
description = "Retrieve a specific language from its name and its owner's id"
|
description = "Retrieve a specific language from its name and its owner's id",
|
||||||
|
arguments(
|
||||||
|
name(description = "Name of the language"),
|
||||||
|
owner(description = "ID of the owner of the language")
|
||||||
|
)
|
||||||
)]
|
)]
|
||||||
fn language(
|
fn language(
|
||||||
context: &Database,
|
context: &Database,
|
||||||
@ -31,21 +37,38 @@ impl Query {
|
|||||||
context.language(name.as_str(), owner.as_str())
|
context.language(name.as_str(), owner.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(description = "Retrieve a specific user from its id")]
|
#[graphql(
|
||||||
|
description = "Retrieve a specific user from its id",
|
||||||
|
arguments(id(description = "Appwrite ID of a user"))
|
||||||
|
)]
|
||||||
fn user(context: &Database, id: String) -> Option<User> {
|
fn user(context: &Database, id: String) -> Option<User> {
|
||||||
context.user(id.as_str())
|
context.user(id.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(description = "Retrieve a specific word from its id")]
|
#[graphql(
|
||||||
|
description = "Retrieve a specific word from its id",
|
||||||
|
arguments(id(description = "Unique identifier of a word"))
|
||||||
|
)]
|
||||||
fn word(context: &Database, id: String) -> Option<Word> {
|
fn word(context: &Database, id: String) -> Option<Word> {
|
||||||
context.word_id(id.as_str())
|
context.word_id(id.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(
|
#[graphql(
|
||||||
description = "Retrieve all words with a set normal form from a set language"
|
description = "Retrieve all words with a set normal form from a set language",
|
||||||
|
arguments(
|
||||||
|
owner(
|
||||||
|
description = "ID of the owner of the language to search a word in"
|
||||||
|
),
|
||||||
|
language(description = "Name of the language to search a word in"),
|
||||||
|
word(description = "Word to search")
|
||||||
|
)
|
||||||
)]
|
)]
|
||||||
fn words(context: &Database, language: String, word: String) -> Vec<Word> {
|
fn words(
|
||||||
context.words(language.as_str(), word.as_str())
|
context: &Database,
|
||||||
|
language: String,
|
||||||
|
word: String,
|
||||||
|
) -> Vec<Word> {
|
||||||
|
context.words(uuid::Uuid::from_str(&language).unwrap(), word.as_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user