yukungのブログ

yukungの技術ブログ兼駄文置き場 

今こそッ、始めようGrailsブートキャンプ!!!! に行ってきた #jggug

いつもの NTTソフトウェアさんで。

jggug.doorkeeper.jp

Grails も3系になり、Spring Boot をベースに生まれ変わったということで以前ちょこっとだけ触ってみたことがありましたが、再度自分の理解を確かめる意味で参加してきました。

内容

Grails 3.0.9 を使って簡単な Todo アプリを作るハンズオンでした。@yamkazu さんの資料が素晴らしすぎて、これを読みながら手を動かしていくことでざっと Grails 3 での開発の流れを実体験できる仕上がりになっています。これ Grails 3 の日本語の入門資料として今のところ最適なんじゃないでしょうか。

github.com

成果物

私もこれに沿って Todo アプリを作ってみました。カンタン。

f:id:yukung:20151024232829p:plain

github.com

感想とかメモ

ドメインクラスを指定するだけで基本的な CRUDメソッド(save, delete, list, get)が勝手に生えてる

class Todo {
    String content
    
    static constraints = {
        content blank: false, maxSize: 20
    }
}

def todo = new Todo(content: 'hogehoge')
todo.save() // Create

def todos = Todo.list() // Multi read
def todo = Todo.get(1) // Read
todo.content = 'updated.'
todo.save() // Update
todo.delete() // Delete

環境ごとに設定を変える仕組みが最初から備わっている

  • environmentsdevelopment, test, production と環境ごとに設定ができる
// BootStrap.groovy で起動時の処理を記述できる
class BootStrap {
    def init = { servletContext ->
        environments {
            development {
                // run-app で立ち上げた時のモード
            }
            test {
                // test-app でテスト実行した時のモード
            }
            production {
                // war, jar で動かしている時のモード
            }
        }
    }
}

コントローラについて

  • Controller と Action メソッドが URL に対応している
  • renderrespond メソッドでレスポンスを返す
    • respondAccept ヘッダやリクエストパスの拡張子などから空気を読んで View を返したり JSON を返したりしてくれる
class TodoController {
    // GET /todo/list
    def list() {
        // 何も指定しないと /grails-app/views/todo/list.gsp でレンダリング
    }
    def read() {
        render view: 'index' // 指定もできる
        // -> /grails-app/views/todo/index.gsp
    }
    def json() {
        render Todo.list() as JSON // grails.converters.JSON が使われて Todo の一覧の JSON が返る
    }
}

画面からパラメータを受け取る

主に3つの方法がある。

  • 暗黙の変数 params を使ってリクエストパラメータを受け取れる
  • リクエストパラメータを Action の引数に指定
  • コマンドオブジェクトを Action の引数に指定
    • ドメインクラスをコマンドオブジェクトとして指定することもできる
    • ドメインクラスに指定されたコマンドオブジェクトが id を持ち、かつリクエストパラメータに id のパラメータがあれば自動的にそれをバインドして対応するデータを取得してくれる
    • 空気読みすぎすごい
// params で受け取る
def save() {
    new Todo(content: params.content).save()
    // または以下でもOK(params が content プロパティを持っている場合)
    new Todo(params)
}

// リクエストパラメータを Action の引数に
def save(String content) {
    new Todo(content).save()
}

// ドメインクラスをコマンドオブジェクトとして Action の引数に指定
def save(Todo todo) {
    todo.save()
}
def show(Todo todo) {
    [todo: todo] // 自動的に id パラメータからデータを取得して View に map を return
    // ドメインクラスに constraint でバリデーションを定義していれば、メソッドの処理の前にそれも適用される
}

クエリ

DB へのクエリは様々な方法が提供されている。ダイナミックファインダと where クエリはすごく楽そうだし使ってみたいと思った。

  • ダイナミックファインダ
  • クライテリア
  • where クエリ
    • Groovy の AST 変換を活用したクエリの仕組み
    • 条件式を書くようにクエリの条件を記述できる
    • 一番新しい API
  • HQL
  • 名前付きクエリ
  • ネイティブ SQL
ダイナミックファインダ
def todos = Todo.findAllByContentLike("%買い物%") // メソッドは実際には定義されていないが、Grails が自動的にクエリを生成する
クライテリア
def c = Todo.createCriteria()
def result = c.list {
    def now = new Date()
    between('period', now - 7, now)
    like('title', '%買い物%')
}
Where クエリ
Todo.where { content ==~ /%買い物%/ }.list()

懇親会

上原さん(@uehaj)と、elm の話や React の話で盛り上がってました。私 React は食わず嫌いで手を出さずにいたのですが、上原さんのお話を聞いて何だか触ってみたくなりましたw

楽しかったです!

謝辞

クオリティの高い資料&ハンズオンを提供していただいた講師の @yamkazu さんとJGGUG の皆さん、ありがとうございました!