Я создаю некоторые грубые CMS-подобные функциональные возможности (чтобы познакомиться с Play Framework). Для этого теста я построил 2 страницы, 1 для перечисления тегов и 1 для создания / редактирования / сохранения тегов.
Поток такой (маршрут-файл):
#list tags
GET /tags Application.listTags
#view/edit existing tag
GET /tag/{<(?!new$)(.+)>name} Application.showTag
#new tag
GET /tag/new Application.showTag
страница создания / просмотра / редактирования отображает форму, которая получает свои значения из tagDTO.
Обычный поток работает без проблем, но когда форма выдает ошибки проверки (например, имя тега должно существовать), я хочу снова отобразить страницу, снова заполнив форму отредактированными значениями.
Для этого (следуя соглашениям Play Framework) я мог бы использовать 'flash' -объект, который содержит эти последние значения, но форма уже связана с tagDTO (который равен null при перенаправлении) вместо 'flash' - объект.
Сначала код:
Application.java
.....
public static void showTag(String name) {
TagDTO tagDTO = TagDTO.buildDTOFromModelOrNew(name);
render(tagDTO);
}
/**
* Save tag and redirect to Show
*
* @param name
* @param displayname
* @param isnew
*/
public static void saveTag(
@Required(message="Name is required") String name,
String displayname,
boolean isnew)
{
checkAuthenticity();
if(validation.hasErrors()) {
params.flash();
validation.keep();
showTag(null);
}
//fetch tagDTO based on backend or create new if not exist
TagDTO tag = TagDTO.buildDTOFromModelOrNew(name);
// Append / Overwrite values
tag.displayname = displayname;
tag.name = name;
//save result to model
TagDTO.buildAndSaveModelFromDTO(tag);
flash.success("Thanks for " + (isnew?"creating":"updating") + " tag " + tag.name);
//redirect to show
showTag(tag.name);
}
And ShowTag.html
#{extends 'main.html' /}
#{if flash.success}
<p class="success">${flash.success}</p>
#{/if}
#{ifErrors}
<p class="errors">Oops...</p>
#{/ifErrors}
#{form @Application.saveTag()}
#{authenticityToken /}
<p>
<label for="name">Name: </label>
<input type="text" name="name" id="name" value="${tagDTO.name}" />
<span class="error">#{error 'name' /}</span>
</p>
<p>
<label for="displayname">Displayname: </label>
<input type="text" name="displayname" id="displayname" value="${tagDTO.displayname}" />
<span class="error">#{error 'displayname' /}</span>
</p>
<p>
<input type="hidden" name="isnew" value="${tagDTO.isnew}" />
<input type="submit" value="Submit your comment" />
</p>
#{/form}
Теперь я мог бы подумать о некоторых способах заставить его работать, но ни один из них не изящен:
привязать форму к flash-объекту (или params-объекту) и заполнить объект flash / params из тега DTO
в случае сбоя проверки, повторно запустите tagDTO (больше не используется, поэтому необходим вызов DB) и перезапишите значения в tagDTO значениями, доступными во flash-объекте, свяжите форму с tagDTO.
как 2, но с использованием некоторого кеша для быстрого извлечения tagDTO (поэтому нет необходимости в db-call)
Какой-то общий механизм (де) сериализации tagDTO из / в сеанс.
Короче, мне не нравится ни один из них на самом деле.
Что вы считаете лучшей практикой в этой ситуации? Или в Play Framework есть какие-то функции, которые мне не хватает?