caseクラスの抽出

caseクラスの抽出

ディレクティブ によって実行される値の抽出は、適切な型安全性とエラー処理を備えた興味深いリクエストプロパティをルートロジックに提供するうえで便利です。 しかし、場合によってはより多くのことを望むかもしれません。 この例を考えてみましょう。

case class Color(red: Int, green: Int, blue: Int)

val route =
  path("color") {
    parameters('red.as[Int], 'green.as[Int], 'blue.as[Int]) { (red, green, blue) =>
      val color = Color(red, green, blue)
      // ... route working with the `color` instance
    }
  }

ここでは、-parameters-scala-`ディレクティブを使用して3つの ` Int``値を抽出し、 `` Color``のcaseクラスのインスタンスを構築します。 ここまでは順調ですね。 しかし、モデルクラスがいくつかのパラメータを持っているときに、モデルクラスのコンストラクタに引数を与えるためだけに引数をキャプチャーすることによってオーバーヘッドが導入されると、ルート定義がいくらか乱雑になる可能性があります。

モデルクラスがcaseクラスである場合、この例のように、Akka HTTPはさらに短くて簡潔な構文をサポートしています。 上記の例を次のように書くこともできます:

case class Color(red: Int, green: Int, blue: Int)

val route =
  path("color") {
    parameters('red.as[Int], 'green.as[Int], 'blue.as[Int]).as(Color) { color =>
      // ... route working with the `color` instance
    }
  }

任意のディレクティブを ``as(...)``で抽出して後置することができます。 モデルcaseクラスのコンパニオンオブジェクトを単に ``as``修飾子メソッドに渡すだけで、基礎となるディレクティブは、モデルクラスの型の1つの値だけを抽出する同等のものに変換されます。 リフレクションは必要ありませんし、caseクラスに特別なインターフェイスを実装する必要もありません。 唯一の要件は、 ``as``呼び出しをつけるディレクティブが適切な型と適切な順序で正しい数の抽出を生成することです。

*いくつかの*ディレクティブによって生成された抽出からcaseクラスのインスタンスを構築したい場合は、 ``as``呼び出しを使用する前にまずディレクティブを ``&``演算子で結合することができます:

case class Color(name: String, red: Int, green: Int, blue: Int)

val route =
  (path("color" / Segment) & parameters('r.as[Int], 'g.as[Int], 'b.as[Int]))
    .as(Color) { color =>
      // ... route working with the `color` instance
    }

ここで `` Color``クラスは、パラメータではなくパス要素として提供される ``name``という別のメンバを取得しました。 ``path``と ``parameters``ディレクティブを &``で結合することで、 ` Color``のクラスのメンバーリストに直接適合する4つの値を抽出するディレクティブを作成します。 したがって、 `` as``修飾子を使用して、ディレクティブを1つの `` Color``インスタンスのみを抽出するものに変換することができます。

一般に、3つ以上の抽出とともに動作するルートがある場合は、これらのcaseクラスを導入して、caseクラス抽出に頼るのが良い考えです。 特に、それはもう一つの素晴らしい機能をサポートしています:検証。

ご用心

caseクラス抽出を使用するときに注意すべき点が1つあります:実際にメンバーを追加するかどうかにかかわらず、caseクラスの明示的なコンパニオンオブジェクトを作成すると、上記の構文はほぼ機能しなくなります 。 `` as(Color) ``の代わりに `` as(Color.apply)``と呼び出す必要があります。 この動作は意図していないように見えるため、今後のScalaバージョンでは改善される可能性があります。

caseクラス検証

多くの場合、Webサービスは、実際にそれらを操作する前に、ロジックに応じて入力パラメータを検証する必要があります。 例えば、上記の例では、すべての色成分値が0から255の間でなければならないという制限があります。これは、いくつかの:ref:`-validate-`ディレクティブで行うことができますが、これはすぐに面倒で読みにくいものになります。

caseクラス抽出を使用する場合、検証ロジックをcaseクラスのコンストラクタに入れることができます。

case class Color(name: String, red: Int, green: Int, blue: Int) {
  require(!name.isEmpty, "color name must not be empty")
  require(0 <= red && red <= 255, "red color component must be between 0 and 255")
  require(0 <= green && green <= 255, "green color component must be between 0 and 255")
  require(0 <= blue && blue <= 255, "blue color component must be between 0 and 255")
}

このような検証を書くと、Akka HTTPのケースクラス抽出ロジックは、何か問題が生じた場合に、すべてのエラーメッセージを適切に拾い、ValidationRejection を生成します。 デフォルトでは、 `` ValidationRejections``は、デフォルトの:ref: `RejectionHandler <The RejectionHandler>`によって、 ``400 Bad Request``エラー応答に変換されます。

Contents