Grails подключается к GORM beforeUpdate () - PullRequest
1 голос
/ 08 мая 2011

У меня есть внутреннее требование к классам вложенных доменов, где я хочу, чтобы обновления родительских отношений распространялись на детей.Пример кода может прояснить это:

class Milestone {
    static belongsTo = [project:Project]
    static hasMany = [goals:OrgGoals, children:Milestone]
    String name
    Date start
    Date estimatedEnd
    Date achievedEnd
    ...
}

Когда обновленный оценочный конец родительского этапа обновляется, я хочу, чтобы оценочные данные детей автоматически обновлялись на ту же сумму. Хук beforeUpdate () GORM кажется логичным местом для этого:

Чтобы упростить жизнь, я бы хотел использовать простую арифметику дат , поэтомуВ класс Milestone добавлен следующий метод:

def beforeUpdate()
    {
        // check if an actual change has been made and the estimated end has been changed
        if(this.isDirty() && this.getDirtyPropertyNames().contains("estimatedEnd"))
        {
            updateChildEstimates(this.estimatedEnd,this.getPersistentValue("estimatedEnd"))
        }
    }

private void updateChildEstimates(Date newEstimate, Date original)
    {
        def difference = newEstimate - original
        if(difference > 0)
        {
            children.each{ it.estimatedEnd+= difference }
        }
    }

Нет ошибок компиляции.Но когда я запускаю следующий интеграционный тест:

void testCascadingUpdate() {
        def milestone1 = new Milestone(name:'test Parent milestone',
            estimatedEnd: new Date()+ 10,
        )
        def milestone2 = new Milestone(name:'test child milestone',
            estimatedEnd: new Date()+ 20,
        )
        milestone1.addToChildren(milestone2)
        milestone1.save()
        milestone1.estimatedEnd += 10
        milestone1.save()
        assert milestone1.estimatedEnd != milestone2.estimatedEnd
        assert milestone2.estimatedEnd == (milestone1.estimatedEnd + 10)
    }

я получаю:

Unit Test Results.

    Designed for use with JUnit and Ant.
All Failures
Class   Name    Status  Type    Time(s)
MilestoneIntegrationTests   testCascadingUpdate Failure Assertion failed: assert milestone2.estimatedEnd == (milestone1.estimatedEnd + 10) | | | | | | | | | | | Mon Jun 06 22:11:19 MST 2011 | | | | Fri May 27 22:11:19 MST 2011 | | | test Parent milestone | | false | Fri May 27 22:11:19 MST 2011 test child milestone

junit.framework.AssertionFailedError: Assertion failed: 

assert milestone2.estimatedEnd == (milestone1.estimatedEnd + 10)
       |          |            |   |          |            |

       |          |            |   |          |            Mon Jun 06 22:11:19 MST 2011
       |          |            |   |          Fri May 27 22:11:19 MST 2011
       |          |            |   test Parent milestone

       |          |            false
       |          Fri May 27 22:11:19 MST 2011
       test child milestone

    at testCascadingUpdate(MilestoneIntegrationTests.groovy:43)

    0.295

Что говорит о том, что beforeUpdate не запускается и выполняет то, что я хочу.Есть идеи?

1 Ответ

5 голосов
/ 08 мая 2011

У меня есть решение для вас.

1) Сохранить вызов (flush: true) при втором вызове сохранения после обновления оценочного конца milestone1. Это заставит beforeUpdate () немедленно сработать.

2) Даже после того, как вы выполните # 1, ваше утверждение по-прежнему не будет выполнено, потому что вы сравниваете 2 слегка отличающиеся даты (вы используете отдельный объект Date в каждом конструкторе Milestone, поэтому вторая дата немного позже / больше первой .) Если вы использовали тот же экземпляр даты, например,

Date date = new Date() 
def milestone1 = new Milestone(name:'test Parent milestone',
            estimatedEnd: date + 10)
def milestone2 = new Milestone(name:'test child milestone',
            estimatedEnd: date + 20,
        )

тогда утверждение будет успешным. Я оставлю вам, что делать дальше с точки зрения наилучшего способа сравнения немного разных дат, но вам, возможно, придется допустить разницу в точности порядка миллисекунд.

Надеюсь, это поможет,

Иордания

...