Pergunta

Digamos que eu já tenha um aplicativo baseado na estrutura Play 2.0 em funcionamento no Scala que serve uma URL como:

http://localhost:9000/aniversários

que responde com uma lista de todos os aniversários conhecidos

Agora quero aprimorar isso adicionando a capacidade de restringir resultados com parâmetros opcionais de solicitação "de" (data) e "para", como

http://localhost:9000/birthdays?from=20120131&to=20120229

(datas aqui interpretadas como aaaaMMdd)

Minha pergunta é como lidar com a ligação e interpretação de parâmetros de solicitação no Play 2.0 com Scala, especialmente considerando que ambos os parâmetros devem ser opcionais.

Esses parâmetros deveriam ser expressos de alguma forma na especificação de "rotas"?Alternativamente, o método Controller respondente deveria separar os parâmetros do objeto de solicitação de alguma forma?Há outra maneira de fazer isso?

Foi útil?

Solução

Codifique seus parâmetros opcionais como Option[String] (ou Option[java.util.Date], mas você terá que implementar seu próprio QueryStringBindable[Date]):

def birthdays(from: Option[String], to: Option[String]) = Action {
  // …
}

E declare a seguinte rota:

GET   /birthday       controllers.Application.birthday(from: Option[String], to: Option[String])

Outras dicas

Uma maneira talvez menos limpa de fazer isso para usuários Java é definir padrões:

GET  /users  controllers.Application.users(max:java.lang.Integer ?= 50, page:java.lang.Integer ?= 0)

E no controlador

public static Result users(Integer max, Integer page) {...}

Mais um problema, você terá que repetir os padrões sempre que vincular sua página no modelo

@routes.Application.users(max = 50, page = 0)

Além da resposta de Julien.Se você não quiser incluí-lo no rotas arquivo.

Você pode obter esse atributo no método do controlador usando RequestHeader

String from = request().getQueryString("from");
String to = request().getQueryString("to");

Isto lhe dará os parâmetros de solicitação desejados, além de manter seu rotas arquivo limpo.

Aqui está o exemplo de Julien reescrito em java, usando F.Option:(funciona a partir do jogo 2.1)

import play.libs.F.Option;
public static Result birthdays(Option<String> from, Option<String> to) {
  // …
}

Rota:

GET   /birthday       controllers.Application.birthday(from: play.libs.F.Option[String], to: play.libs.F.Option[String])

Você também pode escolher parâmetros de consulta arbitrários como strings (você mesmo precisa fazer a conversão de tipo):

public static Result birthdays(Option<String> from, Option<String> to) {
  String blarg = request().getQueryString("blarg"); // null if not in URL
  // …
}

Para parâmetros de consulta opcionais, você pode fazer desta forma

No arquivo de rotas, declare API

GET   /birthdays     controllers.Application.method(from: Long, to: Long)

Você também pode fornecer algum valor padrão, caso a API não contenha esses parâmetros de consulta, ela atribuirá automaticamente os valores padrão a esses parâmetros

GET   /birthdays    controllers.Application.method(from: Long ?= 0, to: Long ?= 10)

No método escrito dentro do aplicativo do controlador, esses parâmetros terão valor null se nenhum valor padrão for atribuído, outros valores padrão.

Minha maneira de fazer isso envolve usar um costume QueryStringBindable.Desta forma expresso parâmetros em rotas como:

GET /birthdays/ controllers.Birthdays.getBirthdays(period: util.Period)

O código para Período é assim.

public class Period implements QueryStringBindable<Period> {

  public static final String PATTERN = "dd.MM.yyyy";
  public Date start;

  public Date end;

  @Override
  public F.Option<Period> bind(String key, Map<String, String[]> data) {
      SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);

      try {
          start = data.containsKey("startDate")?sdf.parse(data.get("startDate")  [0]):null;
          end = data.containsKey("endDate")?sdf.parse(data.get("endDate")[0]):null;
      } catch (ParseException ignored) {
          return F.Option.None();
      }
      return F.Option.Some(this);
  }

  @Override
  public String unbind(String key) {
      SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
      return "startDate=" + sdf.format(start) + "&amp;" + "endDate=" + sdf.format(end);
  }

  @Override
  public String javascriptUnbind() {
      return null;
  }

  public void applyDateFilter(ExpressionList el) {
      if (this.start != null)
          el.ge("eventDate", this.start);
      if (this.end != null)
          el.le("eventDate", new DateTime(this.end.getTime()).plusDays(1).toDate());
  }

}

applyDateFilter é apenas um método de conveniência que uso em meus controladores se quiser aplicar a filtragem de data à consulta.Obviamente você poderia usar outros padrões de data aqui, ou usar algum outro padrão que não seja nulo para data de início e término no bind método.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top