1. kamykn

    Posted

    kamykn
Changes in title
+RevelでInterceptorsを使って共通処理を書く
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,125 @@
+# まえがき
+私はGolangで開発しているときにはRevelを利用しているのですが、コントローラの機能を利用した共通処理をどこに書くのか迷ったので、個人的に至った結論をまとめていきたいと思います。
+
+
+# Overview
+RevelではInterceptorsを使ってコントローラの前処理、後処理を記述することが出来ます。
+Golangはconstructが無いため、今回のようにコントローラのアクションの前処理を実行するにはこのような仕組みを利用します。
+
+今回はコントローラ拡張によって親相当のコントローラを作成し、そこにInterceptorsをセットしていきます。
+
+# 前知識
+## Revelのコントローラ拡張
+コントローラの拡張で親相当のコントローラが作成できます。
+https://revel.github.io/quickstart/controllers.html#extending-the-controller
+
+※ 子コントローラでは、親コントローラの参照はポインタではないことに注意
+
+```go
+type (
+ BaseController struct {
+ *revel.Controller
+ }
+)
+type (
+ MyController struct {
+ BaseController
+ }
+)
+```
+
+## RevelのInterceptors
+今回はMethod Interceptorを使います。
+レシーバーに今回は親コントローラを設定するつもりです。
+下記はドキュメントサイトにあるサンプル( https://revel.github.io/manual/interceptors.html#method-interceptor )。
+
+```go
+func (c Hotels) checkUser() revel.Result {
+ if user := connected(c); user == nil {
+ c.Flash.Error("Please log in first")
+ return c.Redirect(App.Index)
+ }
+ return nil
+}
+
+func init() {
+ revel.InterceptMethod(Hotels.checkUser, revel.BEFORE)
+}
+```
+
+# 本題:共通処理を書く
+今回はMyappというアプリケーションを作成し、ログインしているアカウントデータをすべてのコントローラで扱えるようなものを作ってみましょう。
+
+## 親コントローラ作成
+
+```go:myapp/app/controllers/core/baseController.go
+package core
+
+import (
+ "github.com/revel/revel"
+ "myapp/app/models"
+)
+
+type BaseController struct {
+ *revel.Controller
+ Account struct {
+ models.Account // モデルに定義してあるAccountのデータの型
+ IsLogin bool
+ }
+}
+
+func (b *BaseController) setAccountData() bool {
+ // gormのモデルを利用している
+ accountModel := models.NewAccountModel()
+
+ // アカウント取得
+ // Revelのセッションを使ってAccountIDを取得。説明は割愛
+ accountID := b.GetAccountID()
+ b.Account.Account = accountModel.GetByID(accountID)
+
+ // ログインフラグを追加
+ b.Account.IsLogin = true
+
+ // Account型にモデルで定義しているメソッド
+ if b.Account.IsEmpty() {
+ b.Account.IsLogin = false
+ }
+
+ return nil
+}
+```
+
+
+子となるコントローラで親となるコントローラを継承します。
+
+```go:myapp/app/controllers/app.go
+package controllers
+
+import (
+ "github.com/revel/revel"
+ "myapp/app/controllers/core"
+)
+
+type App struct {
+ core.BaseController
+}
+
+func (a App) Index() revel.Result {
+ account := a.Account
+
+ // Viewでアカウント情報を使いたい
+ return a.Render(account)
+}
+```
+
+## Interceptorsを設定
+下記をベースコントローラに追記します。
+
+```go:myapp/app/controllers/core/baseController.go
+func init () {
+ revel.InterceptMethod((*BaseController).setAccountData, revel.BEFORE)
+}
+```
+
+## あとはコントローラを増やすたびに親コントローラーを継承するだけ
+これで、共通処理化の準備ができました。後はログインチェックが必要なコントローラでベースコントローラを継承していくだけで共通処理として利用できるようになっていきます。