Леса Grails 2.5 не удаляют последнее hasMany во время привязки
Я создал новый проект Grails 2.5.1 с 2 доменами и использовал generate-all для создания строительных лесов. Один из доменов имеет много другого домена: у пользователя есть много ролей. Когда я запускаю приложение, создаю нового пользователя и выбираю роль для пользователя, оно добавляет его. Я могу добавить несколько ролей для пользователя или удалить их, кроме последней. Я не могу удалить последний. Если я пытаюсь удалить все роли для пользователя, он игнорирует его и оставляет роли, которые были выбраны ранее. (Я обнаружил такое же поведение в Grails 2.4.4.)
Домены:
class Role {
String name
}
class User {
String name
static hasMany = [roles: Role]
}
Представление scaffolding создает поле выбора html с:
<g:select name="roles" from="${myapp.Role.list()}"
multiple="multiple" optionKey="id" size="5"
value="${userInstance?.roles*.id}" class="many-to-many"/>
Создание этого HTML:
<select id="roles" class="many-to-many" size="5" multiple="multiple" name="roles">
<option selected="selected" value="1">myapp.Role : 1</option>
<option value="2">myapp.Role : 2</option>
</select>
Воспроизвести:
- Запустите приложение
- Создайте несколько ролей
- Создайте нового пользователя, введите имя, выберите одну или несколько ролей и нажмите "Создать".
- Отредактируйте пользователя, отмените выбор ролей и нажмите "Обновить"
- Обратите внимание, что предыдущие роли все еще выбраны
Я понимаю, что ничего не отправлено с формой для этого поля, если ничего не выбрано. Я могу это исправить, сделав user.roles.clear()
до связывания. Это работает, но мне интересно...
Разве леса действительно не предназначены для этого случая? Или я что-то делаю не так, как в кодировании моих доменов? Есть ли лучшее решение, чем редактирование леса, чтобы очистить роли перед связыванием?
1 ответ
Я не уверен, как отменить выбор ролей, поскольку при редактировании в форме всегда будет выбрана хотя бы одна роль, если вы добавили роль при создании.
Вы должны были бы изменить представления лесов, чтобы достичь того, что вы хотите. Используйте свойство noSelection элемента g:select, чтобы указать значение по умолчанию, если пользователь не хочет выбирать какую-либо существующую роль.
Ваш тег g:select будет:
<g:select name="roles" from="${myapp.Role.list()}"
noSelection="['': '--NoSelection--']"
multiple="multiple" optionKey="id" size="5"
value="${userInstance?.roles*.id}" class="many-to-many"/>
А Scaffolding позволяет генерировать некоторые базовые интерфейсы CRUD для класса домена. Это не поддерживает много вещей, и вы должны реализовать их самостоятельно.