2016-11-22 31 views
0

我試圖做出Entity接口,用於動態映射數據庫結果變成鐵鏽結構:使用特質的接口,用於數據庫實體

pub trait Entity { 
    fn map(&self, Result<QueryResult>) -> Self; 
} 

pub struct DbQuery<T> { 
    pub sql: String, 
    pub params: Vec<Value>, 
    pub limit: i32, 
    pub paged: Option<Pagination>, 
    pub entity: T, 
} 

pub struct Settings { 
    pub name: String, 
    pub value: Option<String>, 
} 

impl Entity for Settings { 
    fn map(&self, result: Result<QueryResult>) -> Settings { 
     // ... 
     Settings { 
      name: "hello".to_string(), 
      value: None, 
     } 
    } 
} 

impl DbMapper { 
    // ... 

    pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>> { 
     println!("query find SQL: {}", query.sql); 
     let mut stmt = &self.pool.prepare(query.sql).unwrap(); 
     let ret = Vec::new(); 
     for row in stmt.execute(query.params).unwrap() { 
      ret.push(query.entity.map(row.unwrap())); 

     } 

     Some(ret) 
    } 
} 

但我得到一個錯誤:

error: no method named map found for type T in the current scope
ret.push(query.entity.map(row.unwrap())); |
note: the method map exists but the following trait bounds were not satisfied: T : std::iter::Iterator = help: items from traits can only be used if the trait is implemented and in scope; the following traits define an item map , perhaps you need to implement one of them: = help: candidate #1: models::holders::database::Entity = help: candidate #2: std::iter::Iterator

+1

你的例子並不完全站在它自己的最小例子,但我認爲答案是你沒有限制'T'來在'DbQuery'和/或'DbMapper ::中實現'Entity' find'。 –

+0

對不起,我使用最小的代碼來解釋它。 不幸的是,我已經嘗試過與實體,而不是T,但我收到相同的錯誤 – plailopo

+1

嗨 - 它有點微不足道,但它不夠完整,把它放到play.rust-lang.org並嘗試編譯它,並得到相同的錯誤,所以有點難以確定。 –

回答

2

Here is a version of your code that runs on the playground並複製你的問題:

pub struct QueryResult; 
pub struct Value; 
pub struct Pagination; 
pub struct DbMapper; 

pub trait Entity { 
    fn map(&self, Result<QueryResult,()>) -> Self; 
} 

pub struct DbQuery<T> { 
    pub sql: String, 
    pub params: Vec<Value>, 
    pub limit: i32, 
    pub paged: Option<Pagination>, 
    pub entity: T, 
} 

pub struct Settings { 
    pub name: String, 
    pub value: Option<String>, 
} 

impl Entity for Settings { 
    fn map(&self, result: Result<QueryResult,()>) -> Settings { 
     // ... 
     Settings { 
      name: "hello".to_string(), 
      value: None, 
     } 
    } 
} 

impl DbMapper { 
    // ... 

    pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>> { 
     println!("query find SQL: {}", query.sql); 

     // ########## attempt to call map() 
     let _ = query.entity.map(Ok(QueryResult {})); 

     let ret = Vec::new(); 
     Some(ret) 

    } 
} 

fn main() {} 

問題是,在find方法中的參數中的不知道TEntity類型。所以我們需要告訴它:

pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>> 
    where T: Entity 
{ 
    // ... code here ... 
} 

This now compiles and runs

編譯器現在知道T是一個Entity的一些描述,它可以調用它的map方法。

+0

是啊! ThankU非常尷尬。我是Rust的新人。 但是,爲什麼不使用實體而不是T? – plailopo

+0

由於'T'在該方法中沒有上下文,除非明確給出它。從編譯器的角度來看,你曾經說過「這是一個T型......它可以是任何類型」。編譯器無法知道該類型實現了映射方法。通過給它提示它是一個實體類型,編譯器知道它可以調用map。 –

相關問題