Pregunta

Estoy haciendo un pequeño sistema de gestión de problemas en la elevación de aprender tanto Scala y Ascensor.

Tengo una vista que muestra un solo tema que pertenece a un proyecto. Antes de enlazar datos a la plantilla de vista, quiero comprobar que he exigido a todos los datos, por lo que quiero comprobar específicamente que:

  • A PARAM ID proyecto se ha suministrado
  • existe un proyecto con el suministrado ID del proyecto
  • Un parámetro número de identificación ha sido proporcionada
  • existe un problema con la cuestión suministrado ID

Y estos deben ser evaluados con el fin, por lo que si tuviera que escribirlo ahora con mi comprensión actual de la Scala, haría lo siguiente:

class Project {
    def findByID(xhtml:NodeSeq): NodeSeq = 
        param("projectID") match {
            case Full(projectID) =>
                Project.findByID(projectID) match {
                    case Full(projectID) =>
                        param("issueID") match {
                            ....
                        }
                    case _ => Text("Project does not exist")
                }
            case _ => Text("projectIDNotSupplied")
        }
}

Así que estoy preguntando si hay una manera más fácil para llevar a cabo esto? Creo que para la expresión podría ser capaz de realizar algo similar. Tenga en cuenta que Project.findByID devuelve una caja [Proyecto].

¿Fue útil?

Solución

En este momento estoy muy tarde para el espectáculo, pero como dice Daniel que de hecho puede usar la caja y de elevación? ~ A hacer algo como esto. Por ejemplo:

import net.liftweb.util.Box
import net.liftweb.util.Box._

class Project {
  def findByID(xhtml:NodeSeq): NodeSeq = 
    (for {
      projectID <- param("projectID") ?~ "projectIDNotSupplied"
      project <- Project.findById(projectID) ?~ "Project does not exist"
      issueID <- param("issueID") ?~ "issueIDNotSupplied"
      ...
    } yield {
      ...
    }) match {
      case Full(n) => n
      case Failure(msg, _, _) => Text(msg)
      case _ => Text("fail")
    }
}

¿Qué? ~ Hace es a su vez una caja vacía en una caja de fracaso con el mensaje de error cadena dada, pero no hace nada para un completo (éxito) Box. Por lo que el valor de retorno de findByID será completa si todo tiene éxito o fracaso (con el mensaje de error dada) en caso contrario. Si desea que los fracasos en cadena, a continuación, utilizar? ~! en su lugar.

Otros consejos

No sé Ascensor, pero hay un par de cosas que he visto en su implementación. Uno de ellos es los modos de fallo: ?~ y ?~!. No estoy seguro exactamente cómo se puede ir sobre el uso de ellos, pero parece ser útil. Otra es open_!, a lanzar excepciones.

Ahora, un mapa de la ayuda del compartimento, flatMap, filtro y foreach, por lo que puede ser utilizado plenamente dentro de una comprensión de:

for(projectID <- param("projectID");
    if Project.findByID(projectID).isDefined;
    issueID <- param("issueID");
    if Issue.findByID(issueID).isDefined)
yield ...

Esto no va a conseguir que los mensajes de error. Para aquellos, supongo que los métodos que he mencionado, u otros como ~>, podría proporcionar la respuesta.

No sé ascensor, así que no puedo responder a cualquier pregunta específica-Lift. Yo, sin embargo, ocurrió una manera de resolver uno de su problema, que es la forma de escribir una secuencia de registro de entrada después de operar acciones sin recurrir a la coincidencia de patrones anidados.

El tipo de datos principal utilizada aquí es la opción, pero estoy seguro de que será bastante fácil de adaptar a sus necesidades. Lo que queremos lograr aquí es hacer una secuencia de

  1. condición de comprobación
  2. continuar si tiene éxito
  3. terminar y devolver algo de lo contrario

El código hace una especie de corto circuito, una vez que se encuentra con una Ninguno de modo que se mantiene el valor de retorno cuando la secuencia de declaraciones de acciones. Para utilizar, comienza con una opción a continuación, escribir "ifSome" si la opción es una parte y "ifNone" si es una opción Ninguno, continúe hasta que termine la secuencia. Si un Ninguno es encuentro en cualquier punto de la secuencia, la opción de volver de parámetro de llamada por nombre de "isNone" se retiene y se devuelve cuando el final "toOption" se llama. Use "toOption" para recuperar el resultado real opción.

Salida el ejemplo de "principal" para algunos casos de uso. Buena suerte!

object Options {

  class RichOption[A](a: Option[A]) {

    def ifSome[B](f: A => Option[B]): RichOption[B] = a match {
      case Some(x) => new RichOption(f(x))
      case None => this.asInstanceOf[RichOption[B]]
    }

    def ifNone[B](f: => Option[B]): RichOption[B] = a match {
      case Some(_) => this.asInstanceOf[RichOption[B]]
      case None => new RichNone(f)
    }

    def toOption[A] = a
  }

  class RichNone[A](a: Option[A]) extends RichOption[A](a) {

    override def ifSome[B](f: A => Option[B]): RichOption[B] = this.asInstanceOf[RichOption[B]]

    override def ifNone[B](f: => Option[B]): RichOption[B] = this.asInstanceOf[RichOption[B]]
  }

  implicit def option2RichOption[A](a: Option[A]): RichOption[A] = new RichOption(a)

  def main(args: Array[String]) {
    println(Some("hello") ifSome(s => Some(s.toUpperCase)) toOption) // prints Some(HELLO)
    println(Some("hello") ifNone(Some("empty")) toOption) // prints Some(hello)
    println(Some("hello") ifSome(s => Some(s.toUpperCase)) ifNone(Some("empty")) toOption) // prints Some(HELLO)
    println(Some("hello") ifNone(Some("empty")) ifSome(s => Some(s.toUpperCase)) toOption) // prints Some(HELLO)
    println((None: Option[String]) ifSome(s => Some(s.toUpperCase)) toOption) // prints None
    println((None: Option[String]) ifNone(Some("empty")) toOption) // prints Some(empty)
    println((None: Option[String]) ifSome(s => Some(s.toUpperCase)) ifNone(Some("empty")) toOption) // prints Some(empty)
    println((None: Option[String]) ifNone(Some("empty")) ifSome(s => Some(s.toUpperCase)) toOption) // prints Some(empty)
    println(Some("hello world") ifSome(s => Some(s.toUpperCase)) ifNone(Some("empty")) ifSome(s => Some(s.length)) ifNone(None) toOption) // prints Some(11)
    println(Some("hello world") ifSome(_ => None) ifNone(Some("goodbye world")) ifSome(s => Some(s.length)) ifNone(None) toOption) // prints Some(goodbye world)
    println((None: Option[String]) ifSome(s => Some(s.toUpperCase)) ifNone(Some("empty")) ifSome(s => Some(s.length)) ifNone(None) toOption) // prints Some(empty)
    println((None: Option[String]) ifSome(_ => None) ifNone(Some("goodbye world")) ifSome(s => Some(s.length)) ifNone(None) toOption) // prints Some(goodbye world)
  }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top