Получение ошибки неопределенного типа или модуля при определении структуры для дизельных моделей - PullRequest
0 голосов
/ 16 марта 2020

Я не могу заставить дизель работать на Rust. В основе этого проекта лежит система подсчета очков, использующая postgres в качестве сервера для сохранения результатов и дизеля для доступа к postgres. Когда я определяю структуру в models.rs (с именем Score), я получаю эту ошибку:

error[E0433]: failed to resolve: use of undeclared type or module `scores`
 --> src/models.rs:7:16
  |
7 | #[table_name = "scores"]
  |                ^^^^^^^^ use of undeclared type or module `scores`

Содержимое schema.rs:

table! {
    scores (name) {
        name -> Varchar,
        points -> Nullable<Int4>,
        subject -> Nullable<Varchar>,
    }
}

Вот мой models.rs:

#[macro_use]
use diesel::*;
use diesel::sql_types::*;
use crate::schema::scores::*;

#[derive(Queryable, Insertable, QueryableByName)]
#[table_name = "scores"]
pub struct Score {
    #[sql_type = "Varchar"]
    name: String,
    #[sql_type = "Integer"]
    points: Option<i32>,
    #[sql_type = "Varchar"]
    subject: Option<String>,
}

Я пытаюсь добавить записи к нему, используя add_entry.rs:

use super::models::Score;
use diesel::pg::PgConnection;
use crate::schema::*;

pub fn create_score(conn: PgConnection, name: String, score: i32, subject: String) -> () {
    let new_score = Score {
        name: name,
        points: Some(score),
        subject: Some(subject),
    };   

    let ins = diesel::insert_into(scores::table)
        .values(new_score)
        .execute(&conn);
}

В main.rs у меня есть:

#[macro_use] extern crate diesel;
mod add_entry;
mod connect;
mod models;
mod schema;
use diesel::dsl::sql_query;

fn main() {
    let conn = connect::connect();
    let name = String::from("name");
    let subject = String::from("subject");
    add_entry::create_score(conn, name.clone(), 75, subject.clone());
    //random data
    list_score();
}

fn list_score() {
    let connection = connect::connect();
    let result = sql_query("SELECT * FROM scores");
    println!("{:#?}", result);
}

А в connect.rs (для соединения с сервером) у меня есть:

use dotenv::dotenv;
use diesel::pg::PgConnection;
use diesel::prelude::*;
use std::env;

pub fn connect() -> PgConnection {
     dotenv().ok();
     let database_url = env::var("DATABASE_URL")
         .expect("Cannot get DB URL.");
     PgConnection::establish(&database_url)
         .expect(&format!("Error connecting to {}", database_url));
}

Содержимое раздела зависимостей моего Автомобиля go .toml равно

dotenv = "0.9.0" 
diesel = { git = "https://github.com/diesel-rs/diesel", features = ["postgres"] }

Чтобы получить эту ошибку, я запустил diesel setup, чтобы настроить все, diesel migration run, diesel migration redo, diesel migration run снова и, наконец, cargo build.

Мой полный код можно найти в этом repository .

Что мне нужно сделать, чтобы устранить эту ошибку? Спасибо.

Ответы [ 2 ]

0 голосов
/ 21 марта 2020

Краткий ответ: Вам нужно импортировать use crate::schema::scores; вместо use crate::schema::scores::*;.

Более подробное объяснение:

Макрос table! Дизеля генерирует довольно сложную модульную структуру, содержащую несколько типов. Кроме того, эти типы реэкспортируются из разных мест, например, из модуля dsl. Производное должно знать тип crate::schema::your_table::table и все типы для каждого столбца (поэтому crate::schema::your_table::column_a,…). Поскольку он не может получить доступ ко всему модулю и не знает, какие типы находятся в области применения, дизель должен каким-то образом определить этот тип. Самый простой способ сделать это - получить имя модуля откуда-то. Это делается с помощью атрибута #[table_name = "your_table"], который предполагает, что в области видимости находится модуль your_table, который содержит соответствующие типы для таблицы и столбцов.

Для получения более подробной информации ознакомьтесь со следующей документацией:

0 голосов
/ 17 марта 2020

Если ваша схема содержит пустые поля, вам нужно использовать Option<T> на стороне ржавчины для такого поля:

#[macro_use]
use diesel::*;

use crate::schema::scores;

#[derive(Queryable, Insertable)]
//#[table_name = "scores"]
pub struct Score {
    //#[sql_type = "Varchar"]
    pub name: String,
    //#[sql_type = "Integer"]
    pub points: Option<i32>,
    //#[sql_type = "Varchar"]
    pub subject: Option<String>,
    //#[sql_type = "Varchar"]
    pub date: Option<String>,
}

И при использовании diesel::insert_into не забудьте импортировать schema::scores.

add_entry.rs:

use super::models::Score;
use crate::schema::scores;
use diesel::pg::PgConnection;
use diesel::prelude::*;

pub fn create_score(
    conn: PgConnection,
    name: String,
    score: i32,
    subject: String,
    date: String,
) -> () {
    let new_score = Score {
        name: name,
        points: Some(score),
        subject: Some(subject),
        date: Some(date),
    };

    let ins = diesel::insert_into(scores::table)
        .values(new_score)
        .execute(&conn);
}

Если вы исправили проблему, связанную с использованием перемещенного значения в main.rs, теперь вы можете скомпилировать свой проект.

add_entry::create_score(
    connection,
    option.clone(),
    scores,
    subject.clone(),
    date.clone(),
);
...