与我的上一个问题(Grails 数据绑定:创建抽象类的实例)类似,我想将数据绑定与包含具有 hasMany 关系的抽象类集合的类一起使用,但在这种情况下,我不使用列表,而是正在使用地图。
我创建了一个集成测试失败的小型项目,以显示可以在 Github 中找到的问题,运行它:
grails test-app -integration -echoOut DataBinding
无论如何,我将通过在这里描述类和测试来解释这个问题:
class LocalizableContent {
Map contentByLocale = [:].withDefault { locale -> new Text() }
static hasMany = [ contentByLocale : Content ]
}
abstract class Content {
static belongsTo = [ localizableContent : LocalizableContent ]
static constraints = {
localizableContent nullable:true
}
}
class Text extends Content {
String text
}
如您所见,我已经在使用 withDefault 技巧,但显然 Grails / Spring 没有调用它(我什至尝试在默认闭包中抛出异常以验证代码未执行)。
为了测试,我还创建了一个空的 LocalizableContentController。尽管如此,以下集成测试将失败:
void testMapDatabinding() {
def rawParams = [ 'contentByLocale[en].text': 'Content' ]
def controller = new LocalizableContentController()
controller.request.addParameters(rawParams)
controller.request.setAttribute(GrailsApplicationAttributes.CONTROLLER, controller)
def localizableContent = new LocalizableContent(controller.params)
assert localizableContent?.contentByLocale['en']?.text == 'Content'
}
它说 localizableContent.contentByLocale 是一个看起来像 ['en': null] 的映射,因此显然数据绑定正在理解映射语法并尝试为“en”键创建一个条目。但不是首先尝试获取该键的条目,因为没有调用 withDefault 。
以下测试 withDefault 工作正常,并且通过了:
void testMapByDefaultWithNoDatabinding() {
assert new LocalizableContent().contentByLocale['en']?.getClass() == Text
}
我在这里想念什么?