Search code examples
grailssetgrails-ormbitset

How to store a set of values in Grails?


In one of my domain classes I need to store a set of symbols chosen from a finite set. In my case it's a choice of one or more weekdays, say Monday plus Tuesday.

Generally speaking I would approach this problem with a bitset (bit 0 = Monday, bit 1 = Tuesday...)

So my first version looks like this:

class SomeDomainClass {
    // available elements
    static final MON = 1, TUE = 2, WED = 4, THU = 8, FRI = 16, SAT = 32, SUN = 64

    // the persistent field and its default value
    int businessDays = MON | TUE | WED | THU | FRI

    // constraint: not null, not empty and not outside bit set
    static constraints = {
        businessDays nullable: false, min: 1, max: 127
    }

    // list getter, returns a list such as [MON, TUE]
    def getBusinessDaysList() {
        return [MON, TUE, WED, THU, FRI, SAT, SUN].findAll { businessDays & it }
    }

    // list setter, accepts a list such as [MON, TUE]
    void setBusinessDaysList(list) {
        businessDays = list.inject { a,b -> a|b }
    }
}   

But something tells me there's a better way to handle this kind of field in Grails / Hibernate, including automatic data binding for checkboxes and such.


Solution

  • It really depends on your needs.

    Your approach is elegant in some respects, but limited in others. If you were to keep with this approach a simple tag library to handle rendering checkboxes and data binding would be the next step and a custom data binder to handle the binding in the controller.

    However, another typical approach would be to model these as a domain class and and have a collection of the selected domain classes added to your domain class.

    Another, less elegant, but simple, approach would be to simply flatten these into individual properties on your domain and let the scaffolding handle the data binding and such.

    Again, it really depends on what you are looking to do. If your comfortable modeling them as properties then that's the simplest solution. Moving from there would be a collection of the selected values. Finally, something along the lines of what you have implemented with the use of a tag library to encapsulate the UI rendering.