如何使用 Diesel 连接和 Gtk-rs 事件?

How to use Diesel connection and Gtk-rs events?

我正在尝试在 gtk 条目中按下 Enter 键时使用 Diesel 从数据库中获取对象。我的想法是在 main 函数中创建一个 Diesel 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有一个静态参数:fn connect_activate<F: Fn(&Self) + 'static>

我不想在每次用户使用 returns 连接的函数按下 Intro 键时初始化连接。相反,我想借用那个连接。

最有效的方法是什么?

非常感谢。我希望你明白一切。

我想你需要一个Rc<SQLiteConnection>

除了 OP 提到的问题之外,该问题还包含其他各种代码问题,因此我将根据上面提供的信息提供一个完整的工作示例。对于以后的问题:请确保您的示例是独立的,并且不包含问题中提到的其他编译错误。这将使其他人更容易重现您的问题并回答问题。

#[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();
        });
    }
}

解决 OP 中描述的错误的唯一相关更改是对 connect_activate 的以下更改:

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