2

与我的上一个问题(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
   }

我在这里想念什么?

4

1 回答 1

0

withDefault 只不过value是一种模式,可以在您遇到未知情况时提供有效的key。例如,考虑以下用例:

def map = [:].withDefault{k-> 
    println k //Should print 'a'
    10
}

map.test = 32

assert map.test == 32
assert map.a == 10

它将未知键作为参数,您不能向其传递任何值,这有点合乎逻辑,因为它提供了默认值而不是提供的值。

Text在您的情况下,如果将值设置为like ,则数据绑定将起作用:

Map contentByLocale = [:].withDefault { locale -> 
    //locale is the key. 'en' in this case
    new Text(locale: locale, text: 'Content') 
}

前提是您将 Text 类定义为

class Text extends Content{
    String locale
    String text
}
于 2013-07-09T18:38:43.767 回答