Могу ли я добавить закрытие к другому в Groovy? - PullRequest
5 голосов
/ 17 января 2011

У меня есть два очень похожих метода в Grails, что-то вроде «вычислить статистику по ОС» ​​и «вычислить статистику по браузеру» - эффективно обе подготовить некоторые вещи, затем выполнить аналогичный запрос в БД, а затем выполнить действия с результатами. Единственная часть, где методы различаются, это запрос, который они выполняют в середине моего метода -

def summary = c.list {
    eq('browser', Browser.get(1)) // OR eq('os', OS.get(1))
    between('date', dates.start, dates.end)
}

Мне пришло в голову, что идеальным способом рефакторинга было бы передать первую строку замыкания в качестве параметра метода. Как

doStats (Closure query) {
    ...
    def summary = c.list {
        query
        between('date', dates.start, dates.end)
    }
}

Я пробовал это, но "запрос" игнорируется. Вместо этого я попробовал query (), но затем условие запроса выполняется там, где оно определено, так что это тоже не работает. Я полагаю, что мог бы просто передать все замыкание в качестве параметра, но это кажется неправильным - запрос может также усложниться в будущем.

У кого-нибудь есть идеи получше?

Ответы [ 3 ]

3 голосов
/ 06 ноября 2014

Я нашел оператор leftShift, полезный для составления замыкания из двух отдельных.Что вы можете сделать:

Closure a = { /*...*/ }
Closure b = { /*...*/ }
Closure c = a << b

Взгляните на этот пример:

def criteria = {
    projection Projections.distinct(Projections.property('id'))
    and {
        eq 'owner.id', userDetails.id

        if (filter.groupId) {
            eq 'group.id', filter.groupId
        }
    }
}

List<Long> ids = Contact.createCriteria().list(criteria << {
    maxResults filter.max
    firstResult filter.offset
})

Integer totalCount = Contact.createCriteria().count(criteria)

Здесь вы можете видеть, что я создаю criteria для подсчета муравьевГОРМ объекты.Критерии для обоих случаев почти одинаковы, но для целей перечисления мне также необходимо включить ограничение и смещение от объекта команды.

3 голосов
/ 17 января 2011

Вы используете критерии DSL, которые могут отличаться от простых замыканий.

Чтобы сделать то, что вы просите, вы можете использовать метод, описанный здесь -

http://mrhaki.blogspot.com/2010/06/grails-goodness-refactoring-criteria.html

и поместите ваш запрос в приватный метод.

Более элегантным решением для этого является использование именованных запросов в граалях -

http://grails.org/doc/latest/ref/Domain%20Classes/namedQueries.html

Посмотрите на

  recentPublicationsWithBookInTitle {
       // calls to other named queries…
       recentPublications()
       publicationsWithBookInTitle()
  }

пример -

2 голосов
/ 17 января 2011

Не уверен, что со сборщиком Grails Criteria, но с другими строителями вы можете сделать что-то вроде:

doStats (Closure query) {
    def summary = c.list {
        query( it )
        between('date', dates.start, dates.end)
    }
}

И позвонить через:

def f = { criteria ->
    criteria.eq( 'browser', Browser.get( 1 ) )
}
doStats( f )

Если нетвероятно, лучше всего смотреть на именованные запросы , как говорит Томас

...