【问题标题】:Repeating code using Grails domain find method使用 Grails 域查找方法重复代码
【发布时间】:2014-12-03 12:45:59
【问题描述】:

最初的问题

如果您有不同的方法,基本上只有一行不同,是否有一种方法可以通过创建一个方法使其干燥。

例子:

def showA( ) {
   def instance

    try {
        instance = A.findById( params.id )
    } catch ( Exception e ) {
        def message = "Error while retrieving details for the given id ${ params.id }, $e"
        log.error message
        responseAsJson( 400, "Invalid id", message )
        return false
    }

    return checkAndRender(instance,  params.id);
}

def showB( ) {

       def instance

        try {
            instance = B.findByBId( params.BId )
        } catch ( Exception e ) {
            def message = "Error while retrieving details for the given id ${ params.id }, $e"
            log.error message
            responseAsJson( 400, "Invalid id", message )
            return false
        }

        return checkAndRender(instance,  params.id);
    }

那么,有没有办法制作一个方法并简单地作为参数传递:

  • 领域类
  • 要搜索的 ID

还是改为传递 SQL 语句会更好?

更新

根据@dmahapatro 的评论,我想出了以下内容:

def showA( ) {
        def clos = {id -> A.findByAId( id ) }
        return findAndShow(clos, params.AId, params )
    }

def showB( ) {
        def clos = {id -> B.findByBId( id ) }
        return findAndShow(clos, params.BId, params )
    }

 def findAndShow(Closure closure, def id, def p)
    {
        def instance
        try {
            instance = closure(id)
        }
        catch ( Exception e ) {
            def message = "Error while retrieving instance details for the given id ${ id }, $e"
            log.error message
            responseAsJson( 400, "Invalid Id", message )
            return false
        }

        return checkAndRender(instance,  id);
    }

剩下的问题只有:

  • 如何进一步清理/使其更清洁。
  • 如何绕过警告:

    [ApiController] 中的 [findAndShow] 动作接受一个参数 键入 [groovy.lang.Closure]。接口类型和抽象类类型 不支持作为命令对象。该参数将被忽略。

       def findAndShow(Closure closure, def id, def p)
    

【问题讨论】:

  • 你可以有一个将闭包作为参数的方法。 Like this 应该可以工作。注意tryCatchClosure方法的使用。
  • @dmahapatro 这是个好主意。我收到了一个烦人的警告:The [findAndShow] action in [ApiController] accepts a parameter of type [groovy.lang.Closure]. Interface types and abstract class types are not supported as command objects. This parameter will be ignored. 更新问题。 def findAndShow(Closure 闭包, def id, def p)
  • @dmahapatro 如果您想写下您的回复作为我投票的答案。谢谢。
  • 将 findAndShow 设为受保护而不是公开,这样可以消除警告。
  • @Gregor Petrin 是的,这行得通!

标签: grails dry findby


【解决方案1】:

如果您想要一个 DRY 代码,您首先应该担心的是定义更好的异常处理。尝试在任何地方捕获您的代码以处理对客户端的响应并不是很干燥,如果您将数据访问代码放在服务中,您可以从它们中抛出异常并使用全局控制器来捕获错误并处理响应。例如:

class ErrorController {

    def serverError() {
         if (request.format == 'json') {
            //Code for handling errors in json request, request.exception stores the data about the exception. 
        } else {
            //Code for handling errors in non-json request, e.g:
            render(view: 'error', model: [msg: 'Something went wrong']) //add an error view for this
        }
    }
}

如果您愿意,还可以为其他类型的错误(403、404 等)添加处理程序

添加到 UrlMappings.groovy

    "500"(controller: "error", action: "serverError")

现在您可以使用新的错误处理和反射重构代码:

控制器:

   class MyController {

        def myService

        def show() {
            def result = myService.myFind(params.className,params.id)
            render result as JSON //Render stuff
        }
    }

服务:

       import grails.util.Holders

       class MyService {

            def myFind(String className, Long id) {
                def result = Holders.getGrailsApplication().getDomainClass('com.mypack.'+ className).findById(id)
                if(!result) {
                    throw new ServiceException('really descriptive and usefull error msg')
                }
            }
        }

我定义了一个 ServiceException 类,因此我可以使用 instanceOf 运算符在我的 ErrorController 中为其添加自定义逻辑。

【讨论】:

  • 也许还有这个:mrhaki.blogspot.gr/2014/05/…
  • 是的,这也是一个好方法,但仅适用于控制器中的错误,您必须在每个控制器中重复该代码。我总是尽量保持我的控制器尽可能干净,只处理参数,并将所有数据访问代码移动到服务/域类,毕竟这是使用 MVC 模式的想法。您是否特别针对您的问题尝试过反射技术?
猜你喜欢
  • 2015-07-24
  • 1970-01-01
  • 2023-03-07
  • 2011-05-18
  • 1970-01-01
  • 2015-12-23
  • 2016-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多