0

考虑以下类:

Class Timesheet {
    BigDecimal hoursWorked
    Boolean reviewedByCustomer
    Boolean approvedByCustomer
    ...
}

就客户评论而言,时间表可以具有三种状态:

  1. TO_BE_CHECKED ( reviewedByCustomer == false && approvedByCustomer == null)
  2. 已批准 ( reviewedByCustomer == true && approvedByCustomer == true)
  3. 拒绝 ( reviewedByCustomer == false && approvedByCustomer == false)

我想使用枚举类型ReviewStatus来表示可以从时间表中检索或用于更新时间表的这些状态。不再使用这两个布尔值。使用以下参数映射:[reviewStatus:'APPROVED'],数据绑定应该如下工作。

def timesheet = new Timesheet(params)

或者

bindData(timesheet, params)

应按如下方式检查状态:

if(timesheet.reviewStatus == ReviewStatus.TO_BE_REVIEWED){
    //do Logic
}

为了实现这种行为,我使用了一个瞬态属性以及 getter 和 setter 方法:

...

//reviewStatus does only exist as getter and setter methods, not as fields
static transients = ['reviewStatus']

ReviewStatus getReviewStatus(){
    if(reviewedByCustomer == false && approvedByCustomer == null){
        ReviewStatus.TO_BE_REVIEWED
    } else if(reviewedByCustomer == true && approvedByCustomer == true){
        ReviewStatus.APPROVED 
    } else if(reviewedByCustomer == true && approvedByCustomer == false){
        ReviewStatus.DENIED
    }
}

void setReviewStatus(ReviewStatus reviewStatus){
    if(reviewStatus == ReviewStatus.TO_BE_REVIEWED){
        reviewedByCustomer = false
        approvedByCustomer = null
    } else if(reviewStatus == ReviewStatus.APPROVED){
        reviewedByCustomer = true
        approvedByCustomer = true
    } else if(reviewStatus == ReviewStatus.DENIED){
        reviewedByCustomer = true
        approvedByCustomer = false
    }
}
...

但是,它不起作用。甚至没有bindable:true。我发现这是类似问题的答案,但他们似乎一直在使用早期版本的 Grails。我可以让它工作的唯一方法是使用bindData(object, params, [exclude:[]]). 我假设空映射会阻止瞬态属性自动添加到排除列表中。

我更喜欢使用可绑定约束,因为这比每次将数据绑定到时间表时都传递一个空映射更简洁

使用 Grails 2.4.2。

编辑 1:使用 Grails 2.4.2 数据绑定器,而不是弹簧数据绑定器。

4

1 回答 1

0

https://github.com/jeffbrown/enumprop上的项目演示了一种方法来做到这一点。

域类:

// grails-app/domain/demo/Timesheet.groovy
package demo

class Timesheet {
    Boolean reviewedByCustomer
    Boolean approvedByCustomer

    static transients = ['reviewStatus']

    ReviewStatus getReviewStatus(){
        if(reviewedByCustomer == false && approvedByCustomer == null){
            ReviewStatus.TO_BE_REVIEWED
        } else if(reviewedByCustomer == true && approvedByCustomer == true){
            ReviewStatus.APPROVED
        } else if(reviewedByCustomer == true && approvedByCustomer == false){
            ReviewStatus.DENIED
        }
    }

    void setReviewStatus(ReviewStatus reviewStatus){
        if(reviewStatus == ReviewStatus.TO_BE_REVIEWED){
            reviewedByCustomer = false
            approvedByCustomer = null
        } else if(reviewStatus == ReviewStatus.APPROVED){
            reviewedByCustomer = true
            approvedByCustomer = true
        } else if(reviewStatus == ReviewStatus.DENIED){
            reviewedByCustomer = true
            approvedByCustomer = false
        }
    }
}

单元测试:

// test/unit/demo/TimesheetSpec.groovy
package demo

import grails.test.mixin.TestFor
import spock.lang.Specification
import spock.lang.Unroll

@TestFor(Timesheet)
class TimesheetSpec extends Specification {

    @Unroll('When reviewStatus is #reviewStatus reviewedByCustomer should be #reviewedByCustomer and approvedByCustomer should be #approvedByCustomer')
    void "test enum property binding"() {
        given:
        def timesheet = new Timesheet(reviewStatus: reviewStatus)

        expect:
        timesheet.reviewedByCustomer == reviewedByCustomer
        timesheet.approvedByCustomer == approvedByCustomer

        where:
        reviewStatus     | reviewedByCustomer | approvedByCustomer
        'APPROVED'       | true               | true
        'DENIED'         | true               | false
        'TO_BE_REVIEWED' | false              | null
    }

    @Unroll('When reviewedByCustomer is #reviewedByCustomer and approvedByCustomer is #approvedByCustomer then reviewStatus should be #reviewStatus')
    void "test retrieving the value of the enum property"() {
        given:
        def timesheet = new Timesheet(reviewedByCustomer: reviewedByCustomer,
                                      approvedByCustomer: approvedByCustomer)

        expect:
        timesheet.reviewStatus == reviewStatus

        where:
        reviewStatus                | reviewedByCustomer | approvedByCustomer
        ReviewStatus.APPROVED       | true               | true
        ReviewStatus.DENIED         | true               | false
        ReviewStatus.TO_BE_REVIEWED | false              | null
    }
}
于 2015-11-13T12:50:21.470 回答