Grails数据绑定和瞬态

时间:2015-11-12 19:10:57

标签: grails data-binding grails-2.4

考虑以下课程:

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

时间表在客户审核方面可以有三种状态:

  1. TO_BE_CHECKED(reviewedByCustomer == false && approvedByCustomer == null
  2. 批准(reviewedByCustomer == true && approvedByCustomer == true
  3. DENIED(reviewedByCustomer == false && approvedByCustomer == false
  4. 我想使用枚举类型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数据绑定器,而不是弹簧数据绑定器。

1 个答案:

答案 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
    }
}
相关问题