
def quadrado = {it**2}     // parâmetro implícito
println quadrado(5)        // retorna 25
def soma = { a, b -> a+b }
println soma(4, 10)        // retorna 14
                        
                        Regra: tudo que não for nulo, vazio, zero (ou explicitamente FALSE, óbvio), será avaliado para TRUE
// True                      | // False
def a = true                 | def b = false
def numbers_full = [1,2,3]   | def numbers = []
def s = 'abc'                | def s = ''
def n = 1                    | def n = 0
def obj = new Object()       | def obj = null
                        
                    Forma reduzida do operador ternário
a ?: b
equivalente à
a != null ? a : b
                        
                        
                            
                        
// Múltiplas linhas
"""
Este é um
texto muito
longo
"""
// Interpolação de variáveis e expressões
"1 + 1 = ${1+1}"
// Expressões regulares
"12345 world!".replaceAll(/\d+/, 'Hello')
                        
                        
                    
// Estruturas nativas para manipulação de coleções
def list = [5, 6, 7, 8]
def range = 5..8
def map = [cidade:"Porto Alegre",
           estado:"RS",
           pais:"Brasil",
           cep:90000001]
map.get("cidade")    // "Porto Alegre"
                        
                    
trait FlyingAbility { String fly() { "I'm flying!" } }
trait WalkAbility { String walk() { "I'm walking!" } }
class Thing implements FlyingAbility { }
def a = new Thing()
assert a.fly() == "I'm flying!"
class Thing { }
def b = new Thing() as FlyingAbility
assert b.fly() == "I'm flying!"
def c = new Thing()
def d = c.withTraits FlyingAbility, WalkAbility
d.fly(); d.walk()
                        
                        @Mixins estão deprecated a partir da versão 2.3, em favor dos Traits.

Fonte: chrisdail.com
#1
#2
#3
#4
#5
#6
#7
#8
#9
#1
					
                
// Cria a aplicação
~ grails create-app MinhaApp
                        
                        
// Executa a aplicação
 ~ cd MinhaApp
 ~ grails run-app MinhaApp
                        
                    
//// Convention-over-configuration
|- grails-app
|--- assets          // Conteúdo gerenciado pelo Asset Plugin
|--- conf            // Arquivos de configuração
|--- controllers
|--- domain
|--- i18n            // Internacionalização
|--- services
|--- taglib
|--- utils
|--- views           // Telas, templates
|- src
|--- groovy
|--- java
|- test              // Testes unitários
|- web-app           // Imagens, CSS, JS, HTML ...
                        
                        
                    
                        
                    
// Scaffolding dinâmico, gera as GUIs para CRUD
// em tempo de execução:
//    index, show, edit, delete, create, save, update
class BookController {       | class AnotherController {
    static scaffold = true   |     static scaffold = Book
}                            | }
// Scaffolding estático: cria fisicamente os arquivos das
// interfaces CRUD, de acordo com o template padrão
~ grails generate-views [domain-class-name]
~ grails generate-all [domain-class-name]
// Customizar os templates:
~ grails install-templates
                        
                        
					
                        
// Exemplo de uso:
${flash.message}
 
                        
                    * na versão 2.4 substituiu o plugin Resources
// Gera um controller para CRUD (template pré-definido)
~ grails generate-controller [domain-class-name]
// Ou pode ser criado diretamente
package org.sample
class SampleController {
    def world() {
        render "Hello World!"
    }
}
// Por convenção, o mapeamento para as
// seguintes URL e view será:
Requisição -> grails-app/sample/world
Retorno    -> grails-app/views/sample/world.gsp
                        
                        
                    
class SomeController {
    def find() {
        def findBy = params["findBy"]
        def appContext = request["foo"]
        def loggedUser = session["logged_user"]
    }
}
                        
                        
                    /controller/action/idgrails-app/conf/UrlMappings.groovy
//
// Mapeamento padrão de uma aplicação recém criada
//
class UrlMappings {
        static mappings = {
        "/$controller/$action?/$id?(.$format)?"{
            constraints {
                // apply constraints here
            }
        }
        "/"(view:"/index")
        "500"(view:'/error')
        }
}
                        
                    grails-app/services/Dê preferência por serviços para orquestrar interações entre recursos da aplicação (domain objects) ou externas (IO).
class SomeService {
    void someMethod(param) {
        // do something
    }
}
/******************************/
class FirstController {
    def someService
    def someAction() {
        try {
            someService.someMethod(params.id)
        } catch(e) {
            log.error e
        }
    }
}
                        
                    grails-app/conf/DataSource.groovy
/// DataSource.groovy
dataSource {
    pooled = true
}
hibernate {
    cache.use_second_level_cache = true
    cache.use_query_cache = false
    cache.region.factory_class=
            'org.hibernate.cache.ehcache.EhCacheRegionFactory'
}
environments {
    development {
        dataSource {
            dbCreate = "create-drop"
            url = "jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
            driverClassName = "org.h2.Driver"
            ...
        }
    }
    production {
        dataSource {
             dbCreate = "update"
             url = "jdbc:postgresql://192.168.0.1/SOME_DATABASE"
             driverClassName = "org.postgresql.Driver"
             ...
        }
    }
}
                    
class Book {
    String title
    static belongsTo = Author
    static hasMany = [authors : Author]
    static constraints = {name nullable: false}
}
class Author {
    String name
    static hasMany = [books : Book]
}
def a = new Author(name:"Author One")
a.addToBooks(new Book(title:"Book One"))
a.addToBooks(new Book(title:"Book Two"))
a.save()
                        
                    
// Acesso direto por id
def book = Book.get(1)
// Dynamic Finders
def book = Book.findByTitle("Book One")
def books = Book.findByTitleIlike("Book%")
def books = Book.findByAuthor(Author.get(1))
// Where Queries
def query = Book.where{title like "Book%"}
def aQuery = query.where{authors {name == "Author One"}}
Book b = aQuery.find()
// Criteria Queries
def c = Book.createCriteria()
def results = c.list(max:4, sort:"title") {
    and {
        ilike("title", "Book%")
        authors{
            eq("name", "Author One")
        }
    }
    maxResults(10)
    order("holderLastName", "desc")
}
                        
                    
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                            
                        
                           .-.
                           | |
                           | |   .-.     > Por hoje é só, pessoal!
                           | |-._| |
                           |_| | | |
                          / )|_|_|-|
                         | | `-^-^ |
                         |     ||  |
                         \     '   /
                          |       |
                          |       |