davidpdrsn / juniper-eager-loading

Library for avoiding N+1 query bugs with Juniper
68 stars 8 forks source link

Error with the juniper_eager_loading #59

Closed DidierBoivin closed 4 years ago

DidierBoivin commented 4 years ago

Hi After declaring the use of junpier_eager_loading, I have this message during compilation

Any idea ` use crate::juniper::{Executor, FieldResult}; use juniper_eager_loading::{prelude::*, EagerLoading, HasOne};

[derive(Clone, EagerLoading)]

| ^^^^^^^^^^^^ use of undeclared type or module models `

davidpdrsn commented 4 years ago

Cannot quite say what is wrong. I need to see more of your code.

DidierBoivin commented 4 years ago

here is my code 'use crate::db::PostgresPool;

use diesel::pg::PgConnection; use crate::diesel::RunQueryDsl;

use crate::juniper::{Executor, FieldResult}; use juniper_eager_loading::{prelude::*, EagerLoading, HasOne}; //use juniper_from_schema::QueryTrail; use juniper_from_schema::graphql_schema_from_file; graphql_schema_from_file!("src/graphql_schema.graphql");

use crate::schema::myapp_agenda; //use crate::schema::myapp_prestation;

pub struct Context { pub connexion: PgConnection, }

// This impl allows us to pass in GraphQLContext as the Context for GraphQL // objects impl juniper::Context for Context {}

[derive(Clone, EagerLoading)]

[eager_loading(context = Context, error = diesel::result::Error)]

pub struct Agenda {

agenda : crate::models::Agenda,

// these are the defaults. `#[has_one(default)]` would also work here.
#[has_one(
    foreign_key_field = prestation_id,
    root_model_field = prestation,
    graphql_field = prestation
)]
prestation: HasOne<Prestation>,

}

impl AgendaFields for Agenda { fn fieldid(&self, executor: &Executor<', Context>) -> FieldResult<&i32> { Ok(&self.agenda.id) }

fn field_prestation(
    &self,
    executor: &Executor<'_, Context>,
    trail: &QueryTrail<'_, Prestation, Walked>,
) -> FieldResult<&Prestation> {
    self.prestation.try_unwrap().map_err(From::from)
}
fn field_agenda_number(&self, _: &juniper::Executor<Context>) -> std::result::Result<&i32, juniper::FieldError> { 
     todo!() }
fn field_contact_person(&self, _: &juniper::Executor<Context>) -> std::result::Result<&std::option::Option<std::string::String>, juniper::FieldError> { todo!() }
fn field_date_agenda_creation(&self, _: &juniper::Executor<Context>) -> std::result::Result<&std::option::Option<DateTime>, juniper::FieldError> { todo!() }
fn field_media_type_agenda(&self, _: &juniper::Executor<Context>) -> std::result::Result<&std::option::Option<std::string::String>, juniper::FieldError> { todo!() }
fn field_level_agenda(&self, _: &juniper::Executor<Context>) -> std::result::Result<&std::option::Option<std::string::String>, juniper::FieldError> { todo!() }
fn field_telephone_number(&self, _: &juniper::Executor<Context>) -> std::result::Result<&std::option::Option<std::string::String>, juniper::FieldError> { todo!() }
fn field_date_agenda_todo(&self, _: &juniper::Executor<Context>) -> std::result::Result<&std::option::Option<DateTime>, juniper::FieldError> { todo!() }
fn field_comments_agenda(&self, _: &juniper::Executor<Context>) -> std::result::Result<&std::option::Option<std::string::String>, juniper::FieldError> { todo!() }
fn field_date_agenda_close(&self, _: &juniper::Executor<Context>) -> std::result::Result<&std::option::Option<DateTime>, juniper::FieldError> { todo!() }
fn field_history_agenda(&self, _: &juniper::Executor<Context>) -> std::result::Result<&std::option::Option<std::string::String>, juniper::FieldError> { todo!() }
fn field_activity_agenda(&self, _: &juniper::Executor<Context>) -> std::result::Result<&std::option::Option<std::string::String>, juniper::FieldError> { todo!() }
fn field_agenda_case_id(&self, _: &juniper::Executor<Context>) -> std::result::Result<&std::string::String, juniper::FieldError> { todo!() }
fn field_agenda_person_assigned_id(&self, _: &juniper::Executor<Context>) -> std::result::Result<&i32, juniper::FieldError> { todo!() }
fn field_agenda_user_id(&self, _: &juniper::Executor<Context>) -> std::result::Result<&i32, juniper::FieldError> { todo!() }

}

[derive(Clone, EagerLoading)]

[eager_loading(context = Context, error = diesel::result::Error)]

pub struct Prestation { prestation: crate::models::Prestation, }

impl PrestationFields for Prestation { fn fieldid(&self, executor: &Executor<', Context>) -> FieldResult<&i32> { Ok(&self.prestation.id) } fn field_libelleprestation(&self, : &juniper::Executor) -> std::result::Result<&std::string::String, juniper::FieldError> { todo!() } }

pub struct Query;

impl QueryFields for Query{ fn fieldagendas( &self, executor: &Executor<', Context>, trail: &QueryTrail<'_,Agenda, Walked>, ) -> FieldResult<Vec>{ let ctx = executor.context(); let agenda_models = myapp_agenda::table.load::(&ctx.connexion)?; let mut agendas = Agenda::from_db_models(&agenda_models); Agenda::eager_load_all_children_for_each(&mut agendas,&agenda_models,ctx,trail)?; Ok(agendas)

} 

} '

davidpdrsn commented 4 years ago

Can you format it correctly with triple backticks? It's a bit hard to read now.

DidierBoivin commented 4 years ago

The code is on Github https://github.com/DidierBoivin/api2

davidpdrsn commented 4 years ago

Thanks. I'll take a look some time this week.

davidpdrsn commented 4 years ago

The issues are here and here. One of the arguments the #[derive(EagerLoading)] takes is what your model type is called. By default it assumes the model can can be found at models::{name of struct}. This is also mentioned in the docs.

So you can either add use crate::models; to the top of graphql.rs or add model = crate::models::Agenda and model = crate::models::Prestation respectively to #[eager_loading(...)].

If you change that it still fails to compiles but for reasons that aren't related to juniper-eager-loading it seems.

I will close this issue but feel free to post follow up questions.

DidierBoivin commented 4 years ago

Thanks you It works now