1
votes

I have field int displayOrder = 1 in Grails domain object and would like to increment it by 1 each time the domain object gets saved.

If I have domain object Widget that has one-to-many relationship with Pix, every time Widget gets a new Pix, Pix needs to have displayOrder incremented.

What would be the most prudent way of setting this up? Preferably count should start from 1 to keep confusion to minimum when someone wants to change the display order. I thought about just duplicating the ID, but then we are possibly looking at displayOrder of 1123, followed by 1169 , etc., so that's not a practical option.

The collection of Pixes belonging to Widget is a sortedSet.

2
Can you share some of your code of how you are creating Pix and assigning them to Widget? It sounds like you're trying to have it so you create a Widget, then the first Pix you associate to it is displayOrder = 1 then the next pix you associate to it is displayOrder = 2. Is that correct? - Jarred Olson
... yes, that's exactly right. - vector

2 Answers

2
votes

You could also do a Named Query to get the last max value of the Pixes, which would work in scenarios where the display orders have skips and jumps.

class Widget {
    static hasMany = [pixes: Pix]
    ...
}
class Pix {
    static belongsTo = [widget: Widget]

    static namedQueries = {
        selectMaxDisplayOrderForWidget { widgetInstance ->
            eq('widget', widgetInstance)
            projections {
                max('displayOrder')
            }
            uniqueResult = true
        }
    }
    ...
}

Then:

def widget = retrieveOrCreateWidget()
def pix = new Pix(propertyA: "A", ..., displayOrder: Pix.selectMaxDisplayOrderForWidget(widget).list(), widget: widget)

If you want to reinitialize the display order numbers after a deleted Pix so they are sequential for a Widget, per your comment to @Jarred Olson, you could do:

Pix.findAllByWidgetAndDisplayOrderGreaterThan(widget, deletedPixDisplayOrder, [sort:'displayOrder',order:'asc']).eachWithIndex { pixInstance, idx ->
    pixInstance.displayOrder = deletedPixDisplayOrder + idx
    pixInstance.save()
}
1
votes

I'd assume that your code looks something like this then:

class Widget {
    static hasMany = [pixes: Pix]
    ...
}
class Pix {
    static belongsTo = [widget: Widget]
    ...
}


def widget = retrieveOrCreateWidget()
def pix = new Pix(propertyA: "A", ..., displayOrder: 1, widget: widget)
pix.save()
widget.addToPixes(pix)
widget.save()

You can determine the displayOrder by the size of pixes:

def widget = retrieveOrCreateWidget()
def pix = new Pix(propertyA: "A", ..., displayOrder: widget.pixes.size() + 1, widget: widget)

EDIT:

If all you need to do is be able to sort a Widget's Pixes by when they were created you could add dateCreated to Pix. This automatically gets set by Grails when a Pix is created. Then you wouldn't have to increment/decrement the value when you add and delete.