2013-12-14 6 views
7

Nella mia applicazione Gioca Ho una configurazione simile a questo:Typesafe config: come iterare elementi di configurazione

social { 
    twitter { 
     url="https://twitter.com" 
     logo="images/twitter.png" 
    } 
    facebook { 
     url="https://www.facebook.com" 
     logo="images/facebook.png" 
    } 
} 

Ho faccio a iterare su tutte le voci social per ottenere url e logo per ogni voce?

<table border="0" cellspacing="0" cellpadding="2"><tr> 
    @configuration.getConfig("social").map { config => 
     @for(item <- config.entrySet) { 
      <td><a href="item.getString("url")"> 
      <img src="@routes.Assets.at("item.getString("logo")").absoluteURL()" width="24" height="24"/></a></td> 
     } 
    } 
</table> 

Naturalmente, item.getString nel frammento qui sopra non funziona ... semplicemente mostra quello che sto cercando di realizzare.

L'obiettivo finale sarebbe quello di essere in grado di aggiungere qualsiasi ulteriore URL sociale senza dover modificare il modello di pagina.

risposta

10

Se si modifica la configurazione per:

"social" : [ 
    { 
     name="twitter" 
     url="https://twitter.com", 
     logo="images/twitter.png" 
    }, 
    { 
     name="facebook" 
     url="https://www.facebook.com", 
     logo="images/facebook.png" 
    } 
] 

Si potrebbe fare così:

@(message: String)(implicit request: RequestHeader) 
@import play.api.Play.current 

<table border="0" cellspacing="0" cellpadding="2"><tr> 
    @current.configuration.getConfigList("social").get.map { config => 
      <td><a href="@config.getString("url")"> 
      <img src="@routes.Assets.at(config.getString("logo").get).absoluteURL()" width="24" height="24"/></a></td> 
     } 
</table> 
+0

Tx, questo è esattamente quello che stavo cercando :-) – j3d

4

Ai posteri, ecco un altro modo per iterare su una configurazione annidata come hai avuto. Preferisco quel formato all'array uno e preferirei rendere il mio config cleaner rispetto al codice.

import collection.JavaConversions._ 
val socialConfig = ConfigFactory.load.getConfig("social") 
socialConfig.root.map { case (name: String, configObject: ConfigObject) => 
    val config = configObject.toConfig 
    println(config.getString("url")) 
    println(config.getString("logo")) 
} 

Sono sicuro che l'OP potrebbe convertire questo in un modello di Twirl. È pulito come posso ottenerlo.

4

Nel caso in cui si sta utilizzando Java, questa potrebbe essere una soluzione:

ConfigList socials = ConfigFactory().load.getList("social") 

for (ConfigValue cv : socials) { 
    Config c = ((ConfigObject)cv).toConfig(); 
    System.out.println(c.getString("url")); 
    System.out.println(c.getString("logo")); 
} 
0

socialConfig.root.map non funziona.

Ecco la mia soluzione -

private val firstSegmentRE = """^(\w+)[\.*].*$""".r 

// convert "aaa.bbb.ccc" to "aaa" 
private def parseFirstSegment(fullPath: String) : Option[String] = { 
    if (fullPath.contains(".")) 
    fullPath match { 
     case firstSegmentRE(segment) => Some(segment) 
     case _ => None 
    } 
    else 
    Some(fullPath) 
} 

// for all keys in white list get a map of key -> config 
protected def subConfigMap(config: Config, whiteList: List[String], 
configName: String) : ErrorOr[Map[String, Config]] = { 
    // This will traverse the whole config and flatten down to the leaves.. 
    val leafKeys : List[String] = 
    config.entrySet() 
     .asScala 
     .map(e => e.getKey) 
     .toList 
    // Remove all after the first dot 
    val nextLevelKeys : List[String] = 
    leafKeys.map(parseFirstSegment) 
     .collect { 
     case Some(firstSegment) => firstSegment 
     } 
     .distinct 
    val keysToSearch = nextLevelKeys.filter(whiteList.contains) 
    // we have a list of valid first level children 
    // parse out subconfigs and convert to map 
    keysToSearch.traverseErrorOr(key => 
    extractSubConfig(config, key, configName).map((key, _)) 
) 
    .map(_.toMap) 
} 

Dove extractSubConfig è un metodo che genera un errore/Config (una disgiunzione scalaz) e traverseErrorOr è un metodo per attraversare una lista e entrambi i processi di tutti gli elementi o fallire e ritorno disgiunzione fallita se fallita in qualsiasi momento. Questo metodo può essere fatto senza scalaz, semplicemente pubblicando una risposta per aiutare le persone se vogliono.

+0

Non è necessario utilizzare una lista bianca o ... che era il mio bisogno aziendale –