使用元类删除/修改域属性

时间:2015-10-16 06:27:33

标签: grails groovy metaprogramming

有一个域包含静态属性:

var app = angular.module("app", []);
app.controller('ctrlTesting', ['$scope', '$filter', function ($scope, $filter) {
    $scope.setValue = function () {
        $scope.dateField = $filter('date')(new Date(), 'yyyy-MM-dd');
        document.getElementById('dateField').value = $filter('date')(new Date(), 'yyyy-MM-dd');
    };
}]);

代码是:

public static fieldNames = ['fieldName','fieldName2']

在spock测试中我想测试else部分,但是我不能直接更改域,所以我想使用元类从域名中删除fieldNames属性或者仅将其设置为null用于测试。可能吗 ?我知道如何使用元类覆盖方法但不知道删除/覆盖属性。

更新

def fieldNamesProperty = grailsApplication.getDomainClass("domainPackage....domain").getPropertyValue('fieldNames')

if(fieldNamesProperty){

// do something

} else{

// do something

}

返回null

也尝试过:

    DomainClass.metaClass.static.getFieldNames = { ['category'] }
    def fieldNameProperty = grailsApplication.getDomainClass("...DomainClass").getPropertyValue('fieldNames')

抛出missingPropertyException

也尝试不使用.static。

1 个答案:

答案 0 :(得分:1)

因为Groovy属性(通过属性属性)具有getter和setter方法,所以可以使用MetaClass覆盖getter方法。

使用域类

SomeClass.metaClass.static.getFieldNames = { [] }

这是一个使用普通Groovy类的演示,您可以使用它来适应Grails域类。

class SomeClass {
    static fieldNames = ['fieldName','fieldName2']
}

SomeClass.metaClass.static.getFieldNames = { [] }

def fieldNamesProperty = SomeClass.fieldNames

if(fieldNamesProperty) println 'Got some field names'
else println 'No field names'

在此示例中, else 分支将执行,因为空列表的计算结果为 false

使用GrailsDomainClass

如果需要GrailsDomainClass返回grailsApplication.getDomainClass(),则需要采用不同的方法。因为这不仅会影响特定的域类,所以最好不要使用MetaClass。相反,我将使用一个类别。

import org.grails.core.AbstractGrailsClass

def klass = grailsApplication.getDomainClass("domainPackage....domain")

def fieldNamesProperty = use(GrailsClassCategory) { klass.getPropertyValue('fieldNames') }

class GrailsClassCategory {
    static Object getPropertyValue(AbstractGrailsClass klass, String name) {
        return ['fieldName','fieldName2']
    }
}

该类别用于覆盖AbstractGrailsClass.getPropertyValue()