0

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.

Burt Beckwith
  • 75,342
  • 5
  • 143
  • 156
Tobia
  • 17,856
  • 6
  • 74
  • 93

2 Answers2

1

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.

Joshua Moore
  • 24,706
  • 6
  • 50
  • 73
  • I just found out that Java has an efficient, typed alternative to my custom bit map: the EnumSet. Unfortunately, Hibernate / Gorm do not seem to persist that class in an efficient manner, they just try to save a serialized blob. – Tobia Feb 24 '15 at 10:28
  • You could always add a custom type handler for Hibernate to account for that. – Joshua Moore Feb 24 '15 at 10:37
  • I went with 7 boolean fields, it being just the 7 days of the week. But I will keep in mind EnumSet and the custom type handler for the future. – Tobia Feb 24 '15 at 10:58
0

You could use a List of enum that defines your choices. enum are really simple to show and read in Grails. It's going to generate a different table mapping that what you are currently achieving but you get simplicity.

<g:select class="form-control" name="test" from="${AnEnum.values()}" keys="${AnEnum.values()}" valueMessagePrefix="anEnum.value" value="${aModel.enumList}"/>
bassmartin
  • 525
  • 2
  • 9