идиома для методов сохранения и обновления в Grails - PullRequest
2 голосов
/ 17 марта 2011

Есть ли в grails какие-то идиомы, которые помогают нам сохранять доменные объекты?

Например,

Я могу захотеть сделать что-то вроде

<code>
if(candidate.hasErrors || !candidate.save)
{
candidate.errors.each {
        log it</p>

<p>}

Однако я не хочу распространять логику на все места, где я делаю domainObject.save.

Я также не хочу отдельного класса, такого как скажем репо, в который я передаю этот domainObject и помещаюв этой логике

Спасибо, Сударшан

1 Ответ

4 голосов
/ 17 марта 2011

Вот метод обслуживания, который я использовал для проверки и сохранения, но регистрировал разрешенные сообщения проверки при сбое.Полезно использовать это вместо просто println error или log.warn error, поскольку toString () для объектов ошибок очень многословно, и вы просто хотите увидеть, что будет отображаться в GSP:

class MyService {
   def messageSource

   def saveOrUpdate(bean, flush = false) {
      return validate(bean) ? bean.save(flush: flush) : null
   }

   boolean validate(bean) {
      bean.validate()
      if (bean.hasErrors()) {
      if (log.isEnabledFor(Level.WARN)) {
         def message = new StringBuilder(
            "problem ${bean.id ? 'updating' : 'creating'} ${bean.getClass().simpleName}: $bean")
         def locale = Locale.getDefault()
         for (fieldErrors in bean.errors) {
            for (error in fieldErrors.allErrors) {
               message.append("\n\t")
               message.append(messageSource.getMessage(error, locale))
            }
         }
         log.warn message
      }
      bean.discard()
      return false
   }

   return true
}

ИВот пример в контроллере:

class MyController {

   def myService

   def actionName = {
      def thing = new Thing(params)
      if (myService.saveOrUpdate(thing)) {
         redirect action: 'show', id: thing.id
      }
      else {
         render view: 'create', model: [thing: thing]
      }
   }
}

Редактировать: также можно добавить эти методы в MetaClass, например, в BootStrap.groovy:

class BootStrap {

   def grailsApplication
   def messageSource

   def init = { servletContext ->

      for (dc in grailsApplication.domainClasses) {
         dc.metaClass.saveOrUpdate = { boolean flush = false ->
            validateWithWarnings() ? delegate.save(flush: flush) : null
         }

         dc.metaClass.validateWithWarnings = { ->
            delegate.validate()
            if (delegate.hasErrors()) {
               def message = new StringBuilder(
                  "problem ${delegate.id ? 'updating' : 'creating'} ${delegate.getClass().simpleName}: $delegate")
               def locale = Locale.getDefault()
               for (fieldErrors in delegate.errors) {
                  for (error in fieldErrors.allErrors) {
                     message.append("\n\t")
                     message.append(messageSource.getMessage(error, locale))
                  }
               }
               log.warn message
               delegate.discard()
               return false
            }

            return true
         }
      }
   }
}

Это зависит от 'журналапеременная, находящаяся в области видимости, которая будет верна в любом артефакте Грааля.Это немного меняет использование контроллера:

class MyController {

   def actionName = {
      def thing = new Thing(params)
      if (thing.saveOrUpdate()) {
         redirect action: 'show', id: thing.id
      }
      else {
         render view: 'create', model: [thing: thing]
      }
   }
}

В качестве метода метакласса может иметь смысл переименовать его, например, saveWithWarnings().

...