考虑以下课程:
Class Timesheet {
BigDecimal hoursWorked
Boolean reviewedByCustomer
Boolean approvedByCustomer
...
}
时间表在客户审核方面可以有三种状态:
reviewedByCustomer == false && approvedByCustomer == null
)reviewedByCustomer == true && approvedByCustomer == true
)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数据绑定器,而不是弹簧数据绑定器。
答案 0 :(得分: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
}
}