2015-08-17 1 views
0

Я пытаюсь получить правильное использование объектов Command. И у меня есть некоторые вопросы.Grails: объекты команд, шаблоны просмотра и поля условной формы?

Учитывая общий домен, например:

package com.foo 

class Ticket { 

    Customer customer 
    Product product 
    Defect defect 
    Solution solution 
    String comment 

    static constraints = { 
    customer nullable:false 
    product nullable:false 
    defect nullable:true 
    solution nullable:true 
    comment nullable:true 
    } 
} 

Затем, рассмотрит следующие правил с формы в билете:

  • Клиент может быть выбран только на создание. При редактировании на дисплее не должно отображаться , вместо этого отображается метка;
  • Продукт можно выбрать только при создании. Тем не менее, при редактировании, выбор должен быть отключен;
  • Дефект можно выбрать либо при создании, либо при редактировании;
  • Решение не может быть установленным в этой форме вообще.
  • Комментарий может быть сообщен только пользователям с определенной ролью (например, SpringSecurity). Если у пользователя нет такой роли, текстовая область должна быть отключена.

Теперь, что я хочу знать:

  1. Что бы быть лучшим подходом к использованию CommandObject для обработки этот сценарий?

    • 1 единственный объект CommandObject для обоих действий?
    • 1 CommandObject для каждого действия?
    • В случае одного CommandObject, как запретить пользователям взламывать программу, например, передавать запрещенный параметр?
  2. Что было бы лучшим подходом к реализации правил формы? То есть, какое поле отображается/включено/отключено в каждом случае.

    • Есть ли какой-либо образец или рекомендация для этого случая?
    • Должны ли такие правила быть записаны в реальной форме?
    • Или должна ли форма «спросить» кого-нибудь? Возможно, CommandObject? Или сам экземпляр домена?

Например, рассмотрим суть этой форме в:

<div class="fieldcontain ${hasErrors(bean:ticketInstance, field:'customer', 'error')} required"> 
    <label for="customer"> 
     <g:message code="ticket.customer.label" default="Customer" /> 
     <span class="required-indicator">*</span> 
    </label> 
    <g:if test="${ticketInstance.id}"> 
     <span class="label read-only">${ticketInstance.customer.name}</span> 
    </g:if> 
    <g:else> 
     <g:select id="customer" name="customer.id" from="${Customer.list()}" optionKey="id" 
        required="" disabled="" value="${ticketInstance?.customer?.id}" class="many-to-one"/> 
    </g:else> 
</div> 

В этом случае нет много проблем, потому что проверка довольно проста. То есть:

<g:if test="${ticketInstance.id}"> 
... 

Однако рассмотрите более сложное правило. Что-то вроде:

<g:if test="${ticketInstance.id && currentUser.granted('SOME_RULE') && ticketInstance.someField != null}"> 
    ... 

И так далее.

Теперь, есть несколько проблем с этим подходом:

  • Это довольно многословен, и, следовательно, склонны к ошибкам.
  • Предположим, что такое правило было распространено среди других полей. В этом случае мне придется каким-то образом управлять им (локальная переменная, дублировать код и т. Д.).
  • И плюс, для этого мне понадобится свойство Id в моем TicketCommand, которое я не знаю, если это хорошая идея.

И, таким образом, мне было интересно, есть ли какой-либо образец или рекомендация, которая может быть использована для улучшения этих сценариев. То есть, что-то, что инкапсулирует такую ​​сложность. Например:

<g:if test="${cmd.customerAllowed}"> 
... 

Где CommandObject может быть что-то вдоль линий:

@Validateable 
class TicketCreateCommand { 

    def currentUser //injected somehow..  

    Customer customer 
    Product product 
    Defect defect 
    String comment 

    static constraints = { 
     importFrom Ticket 
    } 

    boolean isNew() { 
     true 
    } 

    boolean isCustomerAllowed() { 
    this.new && currentUser.granted('SOME_RULE') && this.someField != null 
    //some more rules if necessary.. 
    } 

    boolean isSomeFieldAllowed() { 
    //rules for creating 
    } 
} 

И CommandObject для редактирования:

@Validateable 
class TicketEditCommand { 

    def currentUser //injected somehow..  

    Customer customer 
    Product product 
    Defect defect 
    String comment 

    static constraints = { 
     importFrom Ticket 
    } 

    boolean isNew() { 
     false 
    } 

    boolean isCustomerAllowed() { 
    this.new && currentUser.granted('SOME_RULE') && this.someField != null 
    //some more rules if necessary.. 
    } 

    boolean isSomeFieldAllowed() { 
    //rules for editing 
    } 
} 

Может CommndObject держать такую ​​ответственность? Если нет, есть ли другой лучший способ централизовать такие сложности? Кроме того, как я уже говорил, клиент недвижимости не может быть установлен на обновление. Как с этим бороться?

Ну, я считаю, что это в значительной степени.

Буду признателен за любые мнения и предложения. Любая ссылка на какой-то учебник была бы блестящей.

PS: Для тех, кто хочет посмотреть, полный проект доступен на github.

ответ

1

Что было бы лучшим подходом к использованию объекта команды для обработки этого сценария?

Для просмотра, редактирования и удаления действий потребуется простой идентификатор билета. Я чувствую, что командные объекты на этом этапе переполнены.

Как есть логика для форм, используемых в обновлении (изменить действие отправки) и Сохранить (создать действие отправки), вы должны попробовать иметь объект команды для каждого.

Мое личное предпочтение относительно структуры объекта команды заключается в том, чтобы оно отражало данные, предоставленные формой. Затем вы можете использовать метод утилиты в объекте/контроллере для создания/получения Ticket из предоставленных данных.

Что было бы лучшим подходом к реализации правил формы?

Правила для формы могут быть записаны в gsp как ряд условных операторов. Если существуют большие условные операторы или любые, которые регулярно используются повторно в приложении, то вы можете добавлять методы к своему объекту команды, который централизует это.

Поскольку объект команды находится между представлением и контроллерами, я не вижу, почему логика формы не может быть сохранена здесь.

Если поле должно быть отключено, вы можете тривиально добавить атрибут disabled="disabled" в поле формы. Или с помощью метода команды объекта:

disabled="${cmd.isFooFieldDisabled() ? 'disabled' : ''}" 

Если поле должно быть скрыто, то вы можете использовать скрытый вход, как это так, то это значение не будет виден пользователю, но будет передан в объект команды на форме представить ,

<input type="hidden" name="foo" value="${ticket.foo}"/> 

Я считаю, что are tags provided плагин безопасности яровой, чтобы показать/скрыть GSP элементов в зависимости от роли пользователя.

Чтобы предотвратить переход пользователей с недопустимыми данными, вы можете подтвердить это в своем контроллере, используя следующий код.

def foo(FooCommand cmd) 
{ 
    if(cmd.hasErrors()) 
    { 
     // Handle validation errors 
    } 
} 

Метод hasErrors проверяет объект команды, используя ограничения, которые вы определили. С этого момента вы можете либо вернуть ошибку, либо восстановить ошибку проверки, и продолжить с потоком действий.

Если пользователь изменяет ввод скрытой формы, E.G., идентификатор объекта, то код контроллера должен проверить, имеет ли пользователь право редактировать объект с данным идентификатором. Если они это сделают, политика безопасности не будет нарушена. Если нет, вы можете вернуть некоторую ошибку по вашему выбору. См. this post относительно защиты скрытых полей.

+0

Спасибо за ваш ответ. 2 Командные объекты: ОК. Теперь я уточнил свой вопрос для уточнения. В принципе, я хотел бы знать, есть ли способ/шаблон для централизации сложностей правил каждого поля формы, чтобы код формы не становился настолько загрязненным и сложным. Кроме того, в случае с двумя объектами Command, как предотвратить (на стороне сервера) из определенных полей заполняется пользователем. Я имею в виду, в моем примере: 'TicketEditCommand' пользователь мог« взломать »HTML и вставить' ', и он будет работать, это? –

+0

Я имел в виду: «код формы ** не становится настолько загрязненным и сложным». –

+1

Я отредактировал свой ответ для решения этих вопросов. –

 Смежные вопросы

  • Нет связанных вопросов^_^