Saturday, February 16, 2008

GORM insert and update auto-set of createUser and updateUser

Our company has a standard of using the following attributes on all database tables:

String createUser
Date createDate
String updateUser
Date updateDate


But we did not want to put code in all controller's to set these fields on insert or update. Grails has a nice facilities where you specify code in the beforeInsert and beforeUpdate closures to set the dates:

def beforeInsert = {
createDate = new Date()
}
def beforeUpdate = {
updateDate = new Date()
}

Grails will call these closures automatically. But the issue is setting the createUser and updateUser. What we did is create an abstract base class (concrete makes Grails look for a table called base):

abstract class Base {

String createUser = ''
Date createDate = new Date()
String updateUser = ''
Date updateDate = new Date()

def beforeInsert = {
setCreateUsername() // must be injected in login controller
createDate = new Date()
delegate.createUser = this.createUser
delegate.updateUser = this.updateUser
}

def beforeUpdate = {
setUpdateUsername() // must be injected in login controller
updateDate = new Date()
delegate.updateUser = this.updateUser
}
}


Each of our domain classes extended Base (so they did not have to specify the 4 fields.)
Then, when the user login is handled by the Login controller, we inject the setCreateUsername and updateUsername "methods" as closures that set the username with the HttpSession value:


def user = User.findWhere(userId:params.userId, userPwd:params.userPwd)
session.user = user
Base.metaClass.setCreateUsername = {
createUser = session.user.userId
updateUser = session.user.userId
}
Base.metaClass.setUpdateUsername = {
updateUser = session.user.userId
}


And the four columns are automatically set on all insert and updates.

2 comments:

Matutante said...

Hi Don,
this brings me a doubt: logUserId is a static field in Base. When you have many users wouldn't it always have the last user who logged?

Unknown said...

Matutante, you were right, I modified the strategy so it now works.