Как использовать Diesel connection и Gtk-rs события? - PullRequest
0 голосов
/ 22 апреля 2020

Я пытаюсь получить объект из базы данных с помощью Diesel при нажатии клавиши Enter в gtk Entry. Моя идея состоит в том, чтобы создать дизельное соединение SQLite в основной функции, а затем заимствовать его каждый раз, когда мне это нужно.

Для этого я пытаюсь использовать очень простой MVC. Идея состоит в том, чтобы передать соединение всем контроллерам и повторно использовать его. Я знаю, что здесь необходимо время жизни.

pub struct Controller<'a> {
    pub connection: &'a SQLiteConnection,
    pub search_entry: SearchEntry,
    ....
}

impl<'a> Controller<'a> {

    pub fn new(conn: &'a SQLiteConnection) -> Self {
        Self {
            search_entry: SearchEntry::new(),
            connection: conn,
            ....
        }
    }

    pub fn init(&self) {
        self.search_entry.connect_activate(|x| {
            let need_it = diesel_table
            .filter(column_id.eq(&x.get_text().unwrap()))
            .first(self.connection)
            .unwrap();
        });
    }
}

При компиляции я получаю это:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/lib.rs:44:44
   |
44 |           self.search_entry.connect_activate(|x| {
   |  ____________________________________________^
45 | |             let need_it = diesel_table
46 | |                 .filter(column_id.eq(&x.get_text().unwrap()))
47 | |                 .first(self.connection)
48 | |                 .unwrap();
49 | |         });
   | |_________^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 43:5...
  --> src/lib.rs:43:5
   |
43 | /     pub fn init(&self) {
44 | |         let need_it = diesel_table
46 | |                 .filter(column_id.eq(&x.get_text().unwrap()))
47 | |                 .first(self.connection)
48 | |                 .unwrap();
49 | |         });
50 | |     }
   | |_____^
note: ...so that the types are compatible
  --> src/lib.rs:44:44
   |
44 |           self.search_entry.connect_activate(|x| {
   |  ____________________________________________^
45 | |             let need_it = diesel_table
46 | |                 .filter(column_id.eq(&x.get_text().unwrap()))
47 | |                 .first(self.connection)
48 | |                 .unwrap();
49 | |         });
   | |_________^
   = note: expected  `&&Controller<'_>`
              found  `&&Controller<'a>`
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/lib.rs:44:44: 49:10 self:&&Controller<'_>]` will meet its required lifetime bounds
  --> src/lib.rs:44:27
   |
44 |         self.search_entry.connect_activate(|x| {
   |                           ^^^^^^^^^^^^^^^^

Эта ошибка вызвана тем, что функция connect_activate имеет параметр stati c: fn connect_activate<F: Fn(&Self) + 'static>.

Я не хотел бы инициализировать соединение каждый раз, когда пользователь нажимает клавишу Intro, используя функцию, которая возвращает соединение. Вместо этого я хотел бы позаимствовать эту связь.

Какой самый эффективный способ сделать это?

Большое спасибо. Я надеюсь, что вы все понимаете.

Ответы [ 2 ]

1 голос
/ 23 апреля 2020

Я думаю, вам нужно Rc<SQLiteConnection>

0 голосов
/ 24 апреля 2020

Вопрос содержит различные другие проблемы с кодом, помимо упомянутой ОП, поэтому я приведу полный рабочий пример, основанный на информации, представленной выше. Для будущих вопросов: пожалуйста, убедитесь, что ваш пример самодостаточен и не содержит других ошибок компиляции, как указано в вопросе. Это поможет другим людям воспроизвести вашу проблему и ответить на вопрос.

#[macro_use] extern crate diesel;

use diesel::prelude::*;

table! {
    diesel_table(id) {
        id -> Integer,
        column_id -> Text,
    }
}

pub struct Controller<'a> {
    pub connection: &'a SqliteConnection,
    pub search_entry: SearchEntry,
}

pub struct SearchEntry;

impl SearchEntry {
    fn new() -> Self {
        SearchEntry
    }

    fn connect_activate<'a, F: Fn(&Self) + 'a>(&self, f: F) {
        f(self)
    }

    fn get_text(&self) -> Option<&'static str> {
        Some("foo")
    }
}

impl<'a> Controller<'a> {

    pub fn new(conn: &'a SqliteConnection) -> Self {
        Self {
            search_entry: SearchEntry::new(),
            connection: conn,
        }
    }

    pub fn init(&self) {
        self.search_entry.connect_activate(|x| {
            use self::diesel_table::dsl::*;

            let need_it: (i32, String) = diesel_table
            .filter(column_id.eq(&x.get_text().unwrap()))
            .first(self.connection)
            .unwrap();
        });
    }
}

Единственным значимым изменением для устранения ошибки, описанным в ОП, является следующее изменение connect_activate:

- fn connect_activate<F: Fn(&Self) + 'static>(&self, f: F) {
+ fn connect_activate<'a, F: Fn(&Self) + 'a>(&self, f: F) {
...