Skip to content

Commit

Permalink
Parse objects from config itself with as[] (#54)
Browse files Browse the repository at this point in the history
* Parse case class from config itself

* Just use as method with dot param
  • Loading branch information
Tolsi authored and kailuowang committed Oct 18, 2017
1 parent a344ba7 commit eabc7bb
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/main/scala/net/ceedubs/ficus/FicusConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ trait FicusConfig {

def as[A](path: String)(implicit reader: ValueReader[A]): A = reader.read(config, path)

def as[A](implicit reader: ValueReader[A]): A = as(".")

def getAs[A](path: String)(implicit reader: ValueReader[Option[A]]): Option[A] = reader.read(config, path)

def getOrElse[A](path: String, default: => A)(implicit reader: ValueReader[Option[A]]): A = getAs[A](path).getOrElse(default)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class ArbitraryTypeReaderMacros(val c: blackbox.Context) extends ReflectionUtils

method.paramLists.head.zipWithIndex map { case (param, index) =>
val name = param.name.decodedName.toString
val key = q"""$path + "." + $mapper.map($name)"""
val key = q"""if ($path == ".") $mapper.map($name) else $path + "." + $mapper.map($name)"""
val returnType: Type = param.typeSignatureIn(c.weakTypeOf[T])

companionObjectMaybe.filter(_ => param.asTerm.isParamWithDefault) map { companionObject =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import net.ceedubs.ficus.{SimpleFicusConfig, FicusConfig}

trait ConfigReader {
implicit val configValueReader: ValueReader[Config] = new ValueReader[Config] {
def read(config: Config, path: String): Config = config.getConfig(path)
def read(config: Config, path: String): Config = if (path == ".") config else config.getConfig(path)
}

implicit val ficusConfigValueReader: ValueReader[FicusConfig] = configValueReader.map(SimpleFicusConfig)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import shapeless.test.illTyped
class ArbitraryTypeReaderSpec extends Spec { def is = s2"""
An arbitrary type reader should
instantiate with a single-param apply method $instantiateSingleParamApply
instantiate with a single-param apply method from config itself $instantiateSingleParamApplyFromSelf
instantiate with no apply method but a single constructor with a single param $instantiateSingleParamConstructor
instantiate with a multi-param apply method $instantiateMultiParamApply
instantiate with no apply method but a single constructor with multiple params $instantiateMultiParamConstructor
Expand Down Expand Up @@ -36,6 +37,14 @@ class ArbitraryTypeReaderSpec extends Spec { def is = s2"""
instance.foo must_== foo2
}

def instantiateSingleParamApplyFromSelf = prop { foo2: String =>
import Ficus.stringValueReader
import ArbitraryTypeReader._
val cfg = ConfigFactory.parseString(s"simple { foo2 = ${foo2.asConfigValue} }")
val instance: WithSimpleCompanionApply = arbitraryTypeValueReader[WithSimpleCompanionApply].read(cfg.getConfig("simple"), ".")
instance.foo must_== foo2
}

def instantiateSingleParamConstructor = prop { foo: String =>
import Ficus.stringValueReader
import ArbitraryTypeReader._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class CaseClassReadersSpec extends Spec { def is = s2"""
A case class reader should
be able to be used implicitly $useImplicitly
hydrate a simple case class $hydrateSimpleCaseClass
hydrate a simple case class from config itself $hydrateSimpleCaseClassFromSelf
hydrate a case class with multiple fields $multipleFields
use another implicit value reader for a field $withOptionField
read a nested case class $withNestedCaseClass
Expand All @@ -43,6 +44,11 @@ class CaseClassReadersSpec extends Spec { def is = s2"""
cfg.as[SimpleCaseClass]("simple") must_== SimpleCaseClass(bool = bool)
}

def hydrateSimpleCaseClassFromSelf = prop { bool: Boolean =>
val cfg = ConfigFactory.parseString(s"simple { bool = $bool }")
cfg.getConfig("simple").as[SimpleCaseClass] must_== SimpleCaseClass(bool = bool)
}

def multipleFields = prop { (foo: String, long: Long) =>
val cfg = ConfigFactory.parseString(
s"""
Expand Down
11 changes: 11 additions & 0 deletions src/test/scala/net/ceedubs/ficus/readers/ConfigReaderSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class ConfigReaderSpec extends Spec { def is = s2"""
implicitly read a config $implicitlyReadConfig
read a ficus config $readFicusConfig
implicitly read a ficus config $implicitlyReadFicusConfig
implicitly read a ficus config itself $implicitlyReadFicusConfigFromSelf
"""

def readConfig = prop { i: Int =>
Expand Down Expand Up @@ -51,4 +52,14 @@ class ConfigReaderSpec extends Spec { def is = s2"""
""".stripMargin)
cfg.as[FicusConfig]("myConfig").as[Int]("myValue") must beEqualTo(i)
}

def implicitlyReadFicusConfigFromSelf = prop { i: Int =>
val cfg = ConfigFactory.parseString(
s"""
|myConfig {
| myValue = $i
|}
""".stripMargin)
cfg.getConfig("myConfig").as[FicusConfig].as[Int]("myValue") must beEqualTo(i)
}
}

0 comments on commit eabc7bb

Please sign in to comment.