2016-03-06 41 views
1

我的數據庫中的每張表格都需要有一個created_atupdated_at字段用於一般衛生和家務管理。這導致持久性模型看起來是這樣的:如何處理記錄類型中的「內務」字段?

User 
    email String Maybe 
    name String Maybe 
    tgramUserId TgramUserId Maybe 
    createdAt UTCTime 
    updatedAt UTCTime 
    deriving Show 

現在,我有用於創建用戶的一串的API,根據不同的業務情況。例如:

  • createUserFromWebForm
  • createUserFromTelegram
  • createUserFromOAuth

我想每個API的類型的簽名是:

createUserFromX :: User -> SqlPersistM (Entity User) 

然而,這意味着每個呼叫站點createUserFromX需要撥打getCurrentTime並設置createdAtupdatedAt管家字段。在這些API中本地化這種複雜性的方法是什麼?

一個不潔(IMO)的解決方案是將簽名改爲:

createUserFromTelegram :: Maybe TgramUserId -> SqlPersistM (Entity User) 

...但是,違背了擺在首位使用記錄類型的目的(在這個特殊的例子,你可能支持這種方法,但如果記錄類型有10個字段會怎麼樣)?

+1

您的所有功能處理'User'它應該要簡單地重構一個像'updateTimes :: User - > IO User'這樣的函數並使用它 - 如果你想爲'User'做更多的事情,那麼你可能想爲這個引入一些類型類 – Carsten

回答

3

但是,這意味着每個createUserFromX的調用站點需要調用getCurrentTime並設置createdAt和updatedAt管家字段。

這是不正確的。的SqlPersistM的定義是:

type SqlPersistM = SqlPersistT (NoLoggingT (ResourceT IO)) 
type SqlPersistT = ReaderT SqlBackend 

所以SqlPersistM已MonadIO的實例,可以在裏面你createUserFromX通過liftIO your_io_action執行任何IO動作:

createUserFromX :: User -> SqlPersistM (Entity User) 
createUserFromX user = do 
    utctime <- liftIO getCurrentTime 
    let user' = user { createdAt = utctime, updatedAt = utctime } 
    -- your codes