0

TypeSafe アクティベーター テンプレートをアプリ (play+reactivemongo+knockoutJS) の基礎として使用しています。

ユーザーを作成しようとしていますが、作成中に、提供された国が既に DB にあることを検証したいと考えています。しかし、プログラムの構造上、その検証を行うのが難しいと感じています。

コード

Object UserContoller extends Controller {
  case class UserForm(
      firstName: String, 
      midName: Option[String], 
      lastName: String, 
      addr1: String,
      addr2: Option[String],
      addr3: Option[String],
      city: String,
      state: Option[String],
      zip: String, 
      country: String,
      email: String,
      phone: String
      ) {

    def toUser: User = User(
      BSONObjectID.generate, 
      Name(firstName, midName, lastName), 
      Vector(Email(email)), 
      Vector(Phone(phone)), 
      Address(addr1, addr2, addr3, city, state, zip, CountryDao.find(country))
    )
  }

  implicit val userFormFormat = Json.format[UserForm]

  def save = Action(parse.json) { req =>
    Json.fromJson[UserForm](req.body).fold(
      invalid => {
        BadRequest("Bad form").flashing(Flash(Map("errors" -> JsError(invalid).toString)))
      },
      form => Async {
        UserDao.save(form.toUser).map(_ => Created.flashing(Flash(Map("result" -> "success"))))
      }
    )
  }
}

私の問題は折りたたむことです:国がDBに存在することを確認する必要があり、ユーザーを作成するために国を取得する必要があります(これは非同期アクションです)。

私の最善のアイデアは、UserForm に「fold」メソッド (Json...fold のように) を提供するものを実装させることです。そのため、国が見つからない場合は無効を返すことができます。存在することがわかっている場合は、MongoDB クエリを作成し、それを待って、Option で .get を実行する方がおそらく簡単です。

私が自分自身を明確にしたことを願っています。

何か案は?

[編集] いくつかの変更を加えて、以下の提案を受け入れました: あなたは私に方向性を与えましたが、私はそれを少し修正しました: [文字列] 国名の代わりに国をパラメータとして取るように UserForm クラスを変更しました。リストをレンダリングするテンプレートにリストを渡すと、選択した国が JSON 化され、そのままアップロードされると考えました (国には json.format があります)。

私は CountryDao に exists(c: Country) メソッドを作成しました。これは、DB を検索して結果を返すだけです。

次に、saveUserを次のように変更しました:

...
      form => Async {
        CountryDao.exists(form.country) match {
          case c if c==true => {
            UserDao.save(form.toUser map {_ => 
              Created.flashing(Flash(Map("result" -> "success")))
            }          
          }
          case c if c==false => {
            Future(BadRequest("Invalid Country").flashing(
              Flash(Map("errors" -> "Invalid Country"))))
          }
        }
      }

そしてコンパイルします。それも機能するかどうか見てみましょう:)

とにかく、今のところ解決したと思います。ありがとうございます

4

1 に答える 1

1

1 つのオプションは、次のようなことを行うことです。

def save = Action(parse.json) { req =>
  Json.fromJson[UserForm](req.body).fold(
    invalid => {
      BadRequest("Bad form").flashing(Flash(Map("errors" -> JsError(invalid).toString)))
    },
    form => Async {
      CountryDao.find(form.country).map { c => // assuming find returns an Option
        UserDao.save(form.toUser(c) /* or form.toUser() */).map(
          _ => Created.flashing(Flash(Map("result" -> "success"))))
      }.getOrElse(
          BadRequest("Invalid Country").flashing(
            Flash(Map("errors" -> "Invalid Country")))) // or something else more appropriate
    }
  )
}

国を 2 回検索したくない場合はtoUser、country 型の引数を取るように関数を変更できます。Country

def toUser (country: Country): User = User(
  BSONObjectID.generate, 
  Name(firstName, midName, lastName), 
  Vector(Email(email)), 
  Vector(Phone(phone)), 
  Address(addr1, addr2, addr3, city, state, zip, country)
)
于 2013-12-05T13:34:37.803 に答える