App Engineerの開発ノート

AWS、Flutterや開発活動に役立つツール作りなど

firebase hostingからfirestoreでデータ登録・管理する

firebase hostingでCloud Firestoreを使ってデータ登録・更新・削除します。
Cloud Firestoreで扱われるデータはコレクションとコレクション内のドキュメントで構成されます。
データベースで言うとコレクションはテーブル、ドキュメントはレコードに近いかもしれません。

f:id:Simoroid:20190930232442p:plain
図1.firestore イメージ図
1.登録
ドキュメントの登録を行います。
既に存在している場合は更新として登録が行われます。

function setCity() {
    db = firebase.firestore();
    db.collection("cities").doc("LA").set({
        name: "Los Angeles",
        state: "CA",
        country: "USA"
    })
    .then(function() {
        console.log("Document successfully written!");
    })
    .catch(function(error) {
        console.error("Error writing document: ", error);
    });
}

2.更新
既存の値を新しい値に更新します。
そのフィールド自体が存在しない場合では新規追加となります。

function updateCity() {
    db = firebase.firestore();
    var docRef = db.collection('cities').doc('LA');
    var updateTimestamp = docRef.update({
        timestamp: firebase.firestore.FieldValue.serverTimestamp()
    });
}

3.参照
json形式の一般的な参照方法が使えます。

function getCity() {
    db = firebase.firestore();
    var docRef = db.collection('cities').doc('LA');
    docRef.get().then(function(doc) {
        if (doc.exists) {
            console.log("Document data:", doc.data());
            $("#name").text(doc.data().timestamp.toDate());
        } else {
            // doc.data() will be undefined in this case
            console.log("No such document!");
        }
    }).catch(function(error) {
        console.log("Error getting document:", error);
    });
}

4.削除
ドキュメントの削除を行います。

function deleteCity() {
    db = firebase.firestore();
    db.collection("cities").doc("LA").delete().then(function() {
        console.log("Document successfully deleted!");
    }).catch(function(error) {
        console.error("Error removing document: ", error);
    });
}

5.例
使用例を載せます、コピペ用です。

<a href="#" onclick="updateCity();return false;">updateCity</a>
<a href="#" onclick="getCity();return false;">getCity</a>
<a href="#" onclick="setCity();return false;">setCity</a>
<a href="#" onclick="deleteCity();return false;">deleteCity</a>

firebase hostingで画面(ページ)を配置する

firebase hostingでページを配置する手順を記載します。

1.ページの準備
 今回は特にページの中身にはこだわらずHTMLで下記の4ページを用意します。
  ・index.html(ホームにアクセスしたとき用)
  ・mypage.html(マイページ用)
  ・login.html(ログイン用)
  ・other.html(存在しないページにアクセスされた場合の「ページが見つかりませんでした。」とか用)

2.仮想、物理パスの構成
 物理パスは今回下記のような構成を行いました。
 ※ほぼfirebase initした状態と同じです。
 root/
  ├ .firebaserc
  ├ .gitignore
  ├ firebase.json
  ├ index.html
  └ public
    ├ index.html
    ├ mypage.html
    ├ login.html
    └ other.html

仮想パスには下記を構成します。
 ・https://[mydomain]//
 ・https://[mydomain]//Login
 ・https://[mydomain]//Mypage

3.マッピング
 2.で構成したfirebase上の仮想パスと物理パスのマッピングを行います。
firebase.jsonにglobパターンを使用し、ページと仮想パスのマッピングを行います。
https://firebase.google.com/docs/hosting/full-config?hl=ja#glob_pattern_matching

rewrites配列のなかにマッピングを行いたい数のオブジェクトを定義します。
sourceには仮想パス、destinationには物理パスを設定します。
「**」を指定した場合は定義されていないあらゆるパスを指定してアクセスされた場合、
表示するページを設定することができます。

実際の設定はfirebase.jsonに記述します。

{
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "/",
        "destination": "/index.html"
      },
      {
        "source": "/Login",
        "destination": "/mypage.html"
      },
      {
        "source": "/Mypage",
        "destination": "/mypage.html"
      },
      {
        "source": "**",
        "destination": "/other.html"
      }
    ]
  }
}

4.完成
 1.で用意したページを下記のようにマッピングさせることができましたー

URL ページ
https://[mydomain] index.html
https://[mydomain]/Login mypage.html
https://[mydomain]/Mypage mypage.html
https://[mydomain]/Kaniやhttps://[mydomain]/hogehogeなど諸々 other.html

firebase hostingでシングルサインオンする

firebase hostingでシングルサインオンを使用します。
今回はGoogleアカウントとの連携を行います。

1.firebase consoleで連携アカウントを選択する
Authenticationページを開き、ログイン方法タブを選択する。
許可したいプロバイダを選択し「有効にする」にチェックする。
f:id:Simoroid:20190928121127p:plainf:id:Simoroid:20190928121130p:plain
2.必要なライブラリをインポートします。
最新バージョンは公式サイト「https://firebase.google.com/docs/auth/web/firebaseui?hl=ja
を参考にすれば安全そう。

<script src="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.css" />

3.HTML/Javascriptソースコード追加
今回は認証状況に応じて、サインイン/サインアウトのボタンを表示するよう実装します。
まずはHTMLで画面に表示する部品の準備

    <!-- signinのボタン用 -->
    <div id="auth-component"></div>
    <!-- signoutのボタン用 -->
    <input type="button" id="signout-button" value="Signout" onclick="signout()"/>

次にJavascriptで認証用の処理を記載
認証用の処理の記載はライブラリの定義が見つからないことを防ぐため、
「DOMContentLoaded」イベントの後が安全そうです。

    <script>
      document.addEventListener('DOMContentLoaded', function() {
        try {
             var ui = new firebaseui.auth.AuthUI(firebase.auth());
             var uiConfig = {
               signInOptions: [
                 firebase.auth.GoogleAuthProvider.PROVIDER_ID
               ],
               callbacks: {
                 signInSuccess: function(currentUser, credential, redirectUrl) {
                   // リダイレクトさせない
                   return false;
                 }
               },
             };

             // 認証状態の変更を監視するイベントリスナー
             firebase.auth().onAuthStateChanged((user) => {
                if (user) {
                  // サインインに変更された為、サインアウト用のUIを表示
                  document.getElementById('signout-button').style.display = "block";
                  document.getElementById("name").innerHTML=`${user.displayName}さん`;
                  document.getElementById("email").innerHTML=`${user.email}`;
                } else {
                  // サインアウトに変更された為、サインイン用のUIを表示
                  document.getElementById("name").innerHTML=``;
                  document.getElementById("email").innerHTML=``;
                  document.getElementById('signout-button').style.display = "none";
                  
                  ui.start('#auth-component', uiConfig);
                }
              }, (error) => {
                console.log(error);
              }
            );
            } catch (e) {
              console.error(e);
              document.getElementById('load').innerHTML = 'Error loading the Firebase SDK, check the console.';
            }
          });

      // サインアウトする
      function signout(){
          firebase.auth().signOut();
      }
    </script>

Android Studio で git を使う ~Pull~

チームメンバーの追加・変更内容を取り込みたい場合はpullを行います.
また自分がソースコード修正中であった場合(リモートリポジトリと差異がある状態),取り込みに失敗することがあります,その場合はstash(修正内容の待避),またはrevert(修正内容の破棄)を行います.

f:id:Simoroid:20180612115723p:plain

git を使った開発フロー

1.Pull(取り込み)

リモートリポジトリに対して行われたソースコード変更の取り込み
Android Studio の操作: VCS -> Git -> Pull
⇒Pullボタンをクリック

f:id:Simoroid:20180612122405j:plain

Pullの確認ダイアログ

2.Git Pull Failedが表示された場合

2-1.Revert(修正内容の破棄)
Android Studio の操作: VCS -> Git -> Revert
⇒修正内容を破棄して問題無いことを確認してRevertボタンをクリック

f:id:Simoroid:20180612122835j:plain

Revertの確認ダイアログ

2-2.Stash(修正内容の待避)
Android Studio の操作: VCS -> Git -> Stash Changes...
⇒Messageに修正内容を思い出せるようなキーワードやタイトルを入力しておきCreate Stashボタンをクリック

f:id:Simoroid:20180612122841j:plain

Stashの確認ダイアログ

Android Studio で git を使う ~Push~

Git を使ったソースコードの取り込み、修正を反映させるという作業を行いたい場合,流れは下図となります.

※事前にGithubやBitbucketを利用しリモートリポジトリを作成しておく必要があります

今回はAndroid Studio を使った場合の手順を書きます.

f:id:Simoroid:20180109235032p:plain

git を使った開発フロー
  1. Clone (リモートリポジトリを複製しローカルリポジトリを作成)
    この操作でローカルリポジトリワークスペースが作成される.
    Android Studio の操作: File -> New -> Project from Version Control -> Git

    f:id:Simoroid:20180109235644p:plain
    ※1.手順後にイベントログに【 Error Loading Project 】が表示されたとき
    File -> Open... からプロジェクトを開き直す
    ※2.手順後にイベントログに【 Unregistered VCS root detected 】が表示されたとき
    VCS -> Enable Version Control Integration... を選択
    Gitを選択して[OK] 

  2. Commit (ローカルリポジトリへ変更を反映)
    適当にソースコードを修正し、ローカルリポジトリに反映。
    Android Studio の操作: VCS Commit Changes...

    f:id:Simoroid:20180109235647p:plain

     

  3. Push (リモートリポジトリへ変更を反映)
    ローカルリポジトリに反映した修正内容をリモートリポジトリに反映.
    Android Studio の操作:VCS -> Git -> Push...f:id:Simoroid:20180109235651p:plain