3

Can anyone tell me what would be a good way to implement soft deletes? I can have a deleted property in my class, but my question is how to easily ignore instances which have deleted = true in my searches, listings and so on.

So, rather than saying Domain.findByDeleted(true) just get Domain.list() to ignore deleted instances, rather than saying Domain.findByPropertyAndDeleted('property', true) just say Domain.findByProperty('property').

Is there a nice way of doing this?

doelleri
  • 19,232
  • 5
  • 61
  • 65
zoran119
  • 10,657
  • 12
  • 46
  • 88
  • This should help you out : http://stackoverflow.com/questions/8768534/grails-update-instead-of-delete/8768728 – Anuj Arora Jan 19 '12 at 19:35

3 Answers3

8

I would recommend using a named query for this. Something like

static namedQueries = {
    notDeleted {
        ne 'deleted', true
    }
}

which you could use like Domain.notDeleted.list() or Domain.notDeleted.findByProperty(value)

doelleri
  • 19,232
  • 5
  • 61
  • 65
1

The hibernate filter plugin can automatically add the predicate deleted = false to every query that is performed for a particular domain class. However, my testing indicated that this plugin does not work with Grails 2.0.0.

Dónal
  • 185,044
  • 174
  • 569
  • 824
0

We're used to override list(), get() and some more methods of domain classes. Now we can use syntax like A.delete(log: true)

On bootstrap, we do:

grailsApplication.domainClasses.each { GrailsDomainClass domainClassInfo ->
    def oldGormDelete = domainClassInfo.metaClass.getMetaMethod('delete', [] as Class[])
    assert oldGormDelete
    domainClassInfo.metaClass.delete = { Map params ->
        ...
        def result = oldGormDelete.invoke(delegate)
        ...
    }
}
Victor Sergienko
  • 13,115
  • 3
  • 57
  • 91
  • This is the second time I've come across this strategy. I'm not too familiar with grails meta programming, Could you please explain what is going on here, invoking delegate? – gotomanners Jan 19 '12 at 13:06
  • 1
    I'm using Groovy metaprogramming (see http://groovy.codehaus.org/JN3525-MetaClasses, "ExpandoMetaClass" section). In Class' `metaClass` property I'm assigning closures to be called instead of certain method signatures, in the example - static `delete(Map params)` method. `delegate` is a Groovy keyword like `this` and `owner`, meaning the object the closure is called as a method of - see http://groovy.codehaus.org/Closures. `invoke()` is, er, `Closure`'s method to execute it with a given `this` and given list of arguments - the parameters after first one will be used as call arguments. – Victor Sergienko Jan 19 '12 at 15:26