Pergunta

Eu estou fazendo um sistema de gestão pequeno problema Elevação de aprender tanto Scala e Elevador.

Eu tenho uma visão que exibe uma única questão pertencente a um projeto. Antes de eu ligar dados para o modelo de visão, eu quero verificar que tenho exigido todos os dados, então eu quero verificar especificamente que:

  • A ID projecto param foi fornecido
  • Um projeto existe com o fornecido ID do projeto
  • Uma param questão ID foi fornecido
  • Existe um problema com o fornecido assunto ID

E estes necessidade de ser avaliada em ordem, por isso, se eu estava a escrevê-lo agora com o meu entendimento atual do Scala, eu faria o seguinte:

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")
        }
}

Então, eu estou querendo saber se existe uma maneira mais fácil de realizar isso? Eu acho que uma para a expressão pode ser capaz de realizar algo semelhante. Esteja ciente de que Project.findByID retorna uma caixa [Project].

Foi útil?

Solução

Desculpe o tão tarde para o show, mas como Daniel diz que você pode realmente usar Box e do elevador? ~ Para fazer algo assim. Por exemplo:

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")
    }
}

O que? ~ Faz é transformar uma caixa vazia em uma falha Box com o dado mensagem de erro String, mas não faz nada para uma completa (sucesso) Box. Assim, o valor de retorno de findById será completa se tudo for bem sucedido, ou falha (com o dado mensagem de erro) de outra forma. Se você quer as falhas de corrente, em seguida, usar? ~! em seu lugar.

Outras dicas

Eu não sei elevador, mas há um par de coisas que eu já vi em sua implementação. Um deles é os métodos de falha: ?~ e ?~!. Eu não sei exatamente como se poderia ir em usá-los, mas parece ser útil. Outra é open_!, para lançar exceções.

Agora, um suporte mapa Box, flatMap, filtro e foreach, para que ele possa ser plenamente utilizado dentro de uma para a compreensão:

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

Este não vai chegar as mensagens de erro. Para aqueles, eu estou supondo que os métodos que eu mencionei, ou outros como ~>, pode fornecer a resposta.

Eu não sei Elevador então não posso responder a quaisquer perguntas específicas-Lift. Eu, entretanto, veio com uma maneira de resolver um dos seu problema que é como escrever uma sequência de check-o então operar ações sem recorrer a correspondência de padrões aninhada.

O principal tipo de dados em uso aqui é opção, mas tenho certeza de que vai ser bastante fácil de se adaptar às suas necessidades. O que nós queremos realizar aqui é fazer uma seqüência de

  1. condição de verificação
  2. continuar se bem sucedida
  3. terminar e retornar algo de outra forma

O código faz uma espécie de curto-circuito, uma vez que encontra um None para que o valor de retorno é retida quando a sequência de ações retornos. Para usar, começa com uma opção, em seguida, escrever "ifSome" se Option é uma Alguns e "ifNone" se Option é um Nada, continue até que a seqüência seja concluída. Se um Nada é encontro a qualquer ponto na sequência, a opção de voltar de chamada-por-nome do parâmetro de "isNone" é retido e devolvido quando a final "toOption" é chamado. Use "toOption" para voltar o resultado Opção real.

Confira o exemplo na "principal" para alguns casos de uso. Boa sorte!

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top