布団の中にいたい

Elasticsearchいじったり、Androidアプリ書いたり。最近は数学の勉強が楽しくなってきました。

flutterでfirebase authを利用しようとして環境設定でハマったのでメモ

flutterでfirebase authを使うときにハマったのでメモ。

ハマったのは各OSごとに設定しないといけない部分で今回はiOSで試していたのでそのあたりの使い方をざっくりと。

firebase_authをインストールする

firebase authを使うためにライブラリを入れる。 pubspec.yamlに以下を書く。firebase_authのversionは現時点の最新のものを指定しているが必要に応じて適宜指定してください。

dependencies:
  flutter:
    sdk: flutter
  firebase_auth: ^0.6.2+1 # ここを追加する

firebaseにアプリを追加して、GoogleService-Info.plistを入れる

firebase側のコンソールでアプリを追加してください。私はiOSでやりました。

Register AppIOS Bundle IDの部分にはiosディレクトリ配下にあるRunnerをopenして、記載されているBundle Identifierを入れてください。

そのまま手順を進めていけばGoogleService-Info.plistがダウンロードできます。

後はそれを以下の部分に入れれば問題ないです。

f:id:asahima_194h:20181104004528p:plain

まとめ

Xcode開くあたりでごちゃごちゃしたのでざっくりまとめました。このあたりはCodelabのtutorialをやっていればハマることはないのですが、特にやっていなかったので見事にハマりました。

Firebase for Flutter

実際に使う部分についてはまたそのうちまとめるかも。

flutterでTextFieldの値をmaskする

flutterで適当にログインフォームを作っていて、パスワード部分をmaskしたいなーと思って調べたのでメモ。

やり方は簡単でTextFieldにobscureText: trueを設定してあげるだけ。だいたい以下のような感じ。

new TextField(
    obscureText: true,
    controller: _passwordController
)

該当のドキュメントは以下。 docs.flutter.io

flutterで遷移後のページから値を渡す

flutterで簡単なサンプルを書いていて、遷移後のページから遷移前のページに値を渡したいなーと思って調べたら割と簡単にできました。本来であればdb使ったりしたほうがいいと思うんですが、そうするほどでもなかったので雑な感じで。

遷移先のページで値を渡します。

onPressed: () {
    Navigator.pop(context, "値");
}

後は遷移元の方で値を受け取るだけ。

onPressed: () {
   Navigator.push(
        context,
        new MaterialPageRoute(builder: (context) => new SamplePage())
   ).then((result) {
        setState(() {
            // 何かの処理
        });
  });
}

久しぶりにflutter触ってますが、やはり色々簡単にできてよいですね。

tslintの"interface name must start with a capitalized I (interface-name)"を消す

ReactをTypeScriptで書いているなかで今までtslintなどを特に使っていなかったので入れてみた所、上記のinterface name must start with a capitalized I (interface-name)で怒られた。interface名の先頭にIをつけろとのことだがあまり好きではないのでtslint側で怒られないように設定した。

tslint.jsonのrulesに以下を記載すればいい。

"interface-name": [false]

これで怒られなくなった。

go-playground/validatorでomitemptyを使う

go-playground/validatorを使って、空の値を許容するクエリパラメータのvalidationをしようとして微妙にハマったのでメモ。

go-playground/validatorのリポジトリは以下。

https://github.com/go-playground/validator

go-playground/validatorを使う場合、まずクエリパラメータに対応する構造体を定義して、validationをかけたい要素に対して、validateタグを付加する形になります。

validatorのexampleにもありますが、だいたいこんな感じ。

type QueryParam struct {
    A string `json:"a" validate:"required"`
    B string `json:"b" validate:"max=10"`
}

このときに、requiredをvalidateタグに使わなくても基本的にrequiredになるので、例えばクエリパラメータとして投げられたときはvalidationしたいけど、空のときはそのまま通したいという場合があって微妙に困りました。そんななかdocumentを漁った結果よさそうなものを発見。

https://godoc.org/gopkg.in/go-playground/validator.v9#hdr-Omit_Empty

ドキュメントにそのまま書かれている通り、validateタグにomitemptyを付加すれば、値がセットされていないときはvalidationが走らないようになりました。

エラーの分岐にpkg/errorsを使う

modelのロジックが複数の種類のエラーを返す想定で出力を変えたいなーと思っていろいろ調べたのでメモ。

どうやったらシンプルにできるかなーと考えてたんですが、pkg/errorsを使う形に落ち着きました。

github.com

だいたい以下のような感じで、独自のエラー用の構造体を作って、pkg/errorsのCauseを使って分岐するだけです。このやり方自体もpkg/errors/errors.goのコメントにかかれています。

errors/errors.go at master · pkg/errors · GitHub

package main

import (
    "log"

    "github.com/pkg/errors"
)

type SampleError struct{}

func (e *SampleError) Error() string {
    return "sample error"
}

func main() {
    err := &SampleError{}

    switch errors.Cause(err).(type) {
    case *SampleError:
        log.Println("sample")
    default:
        log.Println("default")
    }
}

シンプルですが、APIでレスポンスを出し分けたいとかに便利だと思います。

echoでmiddlewareを挟もうとしてハマった話

echoでエンドポイントにmiddlewareをはさもうとしていろいろハマったのでメモ。

echoでルーティングする場合は以下のようにecho.EchoのGET、POSTであったり、Addだったりを呼ぶわけなんですが、それとは別に直接echo.RouterのAddを使ってルーティングしたりもできます。

echo.Echoを使う場合

e.GET("/", func (c echo.Context) error {
    return c.String(http.StatusOK, "HelloWorld")
})

echo.Routerを使う場合

r := e.Router()
r.Add("GET", "/", func(c echo.Context) error {
    return c.String(http.StatusOK, "HelloWorld")
})

私の場合はecho.Routerを使っていてmiddlewareをどうやって挟もうかと考えていたのですが、ドキュメントを見ても見てもやり方が分からず諦めてソースを眺めていたら面倒くさくなりそうなことが発覚。以下がそのソース。

// Add registers a new route for an HTTP method and path with matching handler
// in the router with optional route-level middleware.
func (e *Echo) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route {
    name := handlerName(handler)
    e.router.Add(method, path, func(c Context) error {
        h := handler
        // Chain middleware
        for i := len(middleware) - 1; i >= 0; i-- {
            h = middleware[i](h)
        }
        return h(c)
    })
    r := &Route{
        Method: method,
        Path:   path,
        Name:   name,
    }
    e.router.routes[method+path] = r
    return r
}

単純な話、echo.Echoを使ってルーティングをする際にecho.Routerを内部で使っていて、そこのHandleFuncにmiddlewareを挟む処理を入れているようでした。さすがにライブラリで隠蔽されている部分を自分で実装する気にはならないので諦めてecho.Echoを使うようにしました。。。