Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying type for #[graphql_object] #647

Closed
zhenwenc opened this issue May 1, 2020 · 3 comments
Closed

Allow specifying type for #[graphql_object] #647

zhenwenc opened this issue May 1, 2020 · 3 comments
Labels
enhancement Improvement of existing features or bugfix

Comments

@zhenwenc
Copy link

zhenwenc commented May 1, 2020

Is your feature request related to a problem? Please describe.
Consider the following case:

#[derive(Debug, Clone)]
pub struct User {
    pub id: i32,
    pub first_name: String,
    pub last_name: String,
    pub notes: Vec<Note>,
}

#[derive(Debug, Clone)]
pub struct Note {
    pub name: String,
}

In order to define extra field resolvers for a struct, I need to use the graphql_object macro:

#[juniper::graphql_object]
impl User {
    pub fn full_name(&self) -> String {
        format!("{} {}", self.first_name, self.last_name)
    }
}

which generates impl juniper::GraphQLType<juniper::DefaultScalarValue> for User. However, I am also using diesel and defining SQL queries in impl User, clearly I don't want those functions to be exposed as field resolvers for User object.

Describe the solution you'd like
I am thinking to use a similar approach for objects-and-generics in the docs:

#[juniper::graphql_object]
impl User {
    pub fn full_name(&self) -> String {
        format!("{} {}", self.first_name, self.last_name)
    }

    // Instead of doing this...
    // pub fn notes(&self) -> Vec<GraphObject<Note>> {
    //     self.notes.clone().into_iter().map(GraphObject).collect()
    // }

    // I prefer this...
    pub fn notes(&self) -> Vec<Note> {
        self.notes.clone()
    }
}

struct GraphObject<T>(T);

impl Note {
    fn get_notes_from_database() -> Vec<Note> {
        vec![]
    }
}

#[juniper::graphql_object(
    name = "Note", 
    _type = Note,  // <-- proposed solution
)]
impl GraphObject<Note> {
    fn name(&self) -> String {
        self.name.clone()
    }
}

No sure if reading from an optional _type attribute would work, similar to the name attribute:

_type: *_impl.target_type.clone(),

Thanks very much for the great library!

@zhenwenc zhenwenc added the enhancement Improvement of existing features or bugfix label May 1, 2020
@LegNeato
Copy link
Member

LegNeato commented May 1, 2020

I am likely misunderstanding, but you can have two impl blocks:

#[juniper::graphql_object]
impl User {
    pub fn full_name(&self) -> String {
        format!("{} {}", self.first_name, self.last_name)
    }
}

impl User {
  pub fn foo() {
    // Do whatever, this will not be exposed in GraphQL
  }
}

The GraphQL impl block isn't really an impl block...we just use that format to make it familiar to rust folks, provide syntax highlighting in IDEs, and not create another DSL. But it generates a impl GraphQLType for User block so you can still use impl User to do whatever you need.

I believe you can make the GraphQL one this (note the GraphQLObject):

#[juniper::graphql_object]
impl GraphQLObject for User {
    pub fn full_name(&self) -> String {
        format!("{} {}", self.first_name, self.last_name)
    }
}

to make it clearer.

Does that work?

@zhenwenc
Copy link
Author

zhenwenc commented May 1, 2020

@LegNeato Thank you very much for the clarification! Sorry, it was my mistake. 🤦‍♂️

Both having two impl User block and impl GraphQLObject for User works, and I do prefer the second one as it seems more clear. Thanks!

Closing this as its not an issue. Sorry for the confusion!

@zhenwenc zhenwenc closed this as completed May 1, 2020
@LegNeato
Copy link
Member

LegNeato commented May 2, 2020

Perhaps we should change the docs to use the second form, hmmm. Glad it fixed your issue!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improvement of existing features or bugfix
Projects
None yet
Development

No branches or pull requests

2 participants