Skip to content

Instantly share code, notes, and snippets.

@gakuzzzz
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gakuzzzz/0149504e99a371974539 to your computer and use it in GitHub Desktop.
Save gakuzzzz/0149504e99a371974539 to your computer and use it in GitHub Desktop.
validation dsl

spec

  • 氏名は必須
  • メアドはオプショナル
    • だけど入力されていたら簡易な正規表現でチェック
  • 開始日と終了日は必須
    • 開始日 < 終了日 である必要がある
  • 全てのバリデーションが通ったら Subscription(name: String, mail: Option[String], interval: Interval) というオブジェクトにする
  • 氏名とメアドと開始日と終了日のvalidationはどれががこけても全て実施して全てのエラーを返す必要がある

code

case class Subscription(name: String, mail: Option[String], interval: Interval)

val validator = 
      required[String]("name")
  |@| oprional[String]("mail").verifying("mail", "error.mailFormat") {_.matches("""^.*@.*$""")}
  |@| (
            required[LocalDate]("start")
        |@| required[LocalDate]("end")
        apply ((_,_))
      ).verifying("end", "error.beforeStart") {
        case (s, e) => s < e
      }.map {
        case (s, e) => Interval(s, e)
      }
  apply Subscription.apply

type FieldName = String
type Message = String
type Error = (FieldName, Message)

result: Either[Seq[Error], Subscription] = validator(httpRequest)

Haskell like Applicative Stype

val validator = Subscription.apply
  <$> required[String]("name")
  <*> oprional[String]("mail").verifying("mail", "error.mailFormat") {_.matches("""^.*@.*$""")}
  <*> (
        Tuple2.apply[LocalDate, LocalDate]
        <$> required[LocalDate]("start")
        <*> required[LocalDate]("end")
      ).verifying("end", "error.beforeStart") {
         case (s, e) => s < e
      }.map {
         case (s, e) => Interval(s, e)
      }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment