FirebaseでTwitterログインを利用し最速で「いいね」機能をつくる　〜究極の選択をつくるサービスをリリースした話〜

# TL;DR(要約)
- Nuxt + Firebase + Twitterログイン を使ってアンケート機能をもつサービスを作りました
- [究極の選択メーカー](https://www.choice-maker.site/)はこちら
- [開発裏エピソード](https://crieit.net/posts/500-WEB-5cb48f061acbb)はこちら


# 自己紹介
個人的なプロジェクト「毎月サービスリリースで技術もノウハウもうっはうは祭り:fire:」をしています、ミツダマ(@mitudama)です。
1月の[時間割メーカー](https://qiita.com/mitsudaman/items/b30b5e905ff348bf35bc)、2月の[俳句メーカー](https://www.haiku-maker.site/)に引き続き3月は[究極の選択メーカー](https://www.choice-maker.site/)をリリースしました！
今回はTwitterログインについて勉強していいね機能、アンケート機能を実現しましたのでメモします！

# 作ったサービス

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">人生は【選択】の連続だ。<br><br>逃げるか挑むか。<br><br>生きるか死ぬか。<br><br>勝つか負けるか。<br><br>世界を半分もらうか、もらわないか🌍<br><br>あなたは何を選ぶ。<br><br>「究極の選択メーカー」リリースしました！！！🎉🎉🎉<br><br>究極の選択をつくって人生を問うていきましょう！！<a href="https://t.co/ttsLmoKzQO">https://t.co/ttsLmoKzQO</a></p>&mdash; ミツダマ@500円プログラマー (@mitudama) <a href="https://twitter.com/mitudama/status/1112365378573762561?ref_src=twsrc%5Etfw">2019年3月31日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>




#何で作ったか
・ユーザーを識別してイイねやアンケート機能をもつサービスをつくりたい
・どうやらfirebaseを使えば簡単にTwitterログインを使えるらしい
・作っちゃえ
・作った

# 使った技術と参考サイト
基本的に[時間割メーカー](https://qiita.com/mitsudaman/items/b30b5e905ff348bf35bc)や[俳句メーカー](https://qiita.com/mitsudaman/items/1956b94dc8faf8fb8c59)で使った技術と同じですが、そのほかで新たに導入した技術は以下になります。

- [Firebase](https://firebase.google.com/?hl=ja)
    - Authentication: Twitter Loginが利用できる。簡単。
    
![screenshot-2019-03-05-233315.png](https://qiita-image-store.s3.amazonaws.com/0/314105/b56bdbf8-9e09-ce83-23a7-5c5a1d355046.png)

- Twitter API
    - 皆さんご存知ツイッター情報を利用するためのAPI。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314105/8c91cc02-e12f-690d-5a33-b27fc57e44b8.png)


▼[Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ](https://qiita.com/kngsym2018/items/2524d21455aac111cdee)


# 最速でいいね機能を作るチュートリアル

## Vueのコーディング
以下コピペでOKです！

```vue:index.vue
<template>
  <div class="container_area">
    <div>
        <button 
          @click="logIn">ログイン</button>
        <button 
          @click="logOut">ログアウト</button>
      </div>
      <div class="btn_area">
        <div>
          <button 
            v-if="!likedFlg"
            @click="addLikeUsr()"
            class="btn like-btn">
              <i class="fa fa-fw fa-thumbs-up"></i> 
          </button>
          <button 
            v-if="likedFlg"
            @click="delLikeUsr()"
            class="btn like-btn">
              <i class="fa fa-fw fa-check"></i> 
          </button>
          <span class="like-count">{{likeSum}}よかね</span>
        </div>
      </div>
  </div>
</template>

<script>
import firebase from 'firebase'
import 'firebase/firestore';
var config = {
  apiKey: "",
  authDomain: "",
  databaseURL: "",
  projectId: "",
  storageBucket: "",
  messagingSenderId: ""
};
if (!firebase.apps.length) {
    firebase.initializeApp(config);
}
var db = firebase.firestore();
export default {
  components: {
  },
  data() {
    return {
      likeSum: 0,
      likedFlg: false,
      loginUser:null,
      documentId: ""  //FirestoreのdocumentIdを指定
    };
  },
  created() {
    firebase.auth().onAuthStateChanged((user)=> {
      if (user) {
        this.loginUser = user;
      } else {
      }
    });
    var docRef = db.collection("posts").doc(this.documentId);
    this.getLikeUserByDocumentId(docRef)
  },
  methods: {
    logIn() {
      var provider = new firebase.auth.TwitterAuthProvider();
      firebase.auth().signInWithRedirect(provider);
    },
    logOut(){
      firebase.auth().signOut().then(function() {
        // Sign-out successful.
        console.log("signOut")
      }).catch(function(error) {
        // An error happened.
      });
    },
    addLikeUsr(){
      var docRef = db.collection("posts").doc(this.documentId);
      docRef.update({
            "like_users": firebase.firestore.FieldValue.arrayUnion(this.loginUser.uid),
        })
      this.getLikeUserByDocumentId(docRef)
    },
    delLikeUsr(){
      var docRef = db.collection("posts").doc(this.documentId);
      docRef.update({
            "like_users": firebase.firestore.FieldValue.arrayRemove(this.loginUser.uid),
        })
      this.getLikeUserByDocumentId(docRef)
    },
    getLikeUserByDocumentId(docRef){
      // ドキュメント取得
      docRef.get().then(doc => {
          if (doc.exists) {
            this.posts = doc.data();
            this.likeSum = this.posts.like_users.length
            // すでにいいねされていないか確認用フラグ
            this.likedFlg = this.posts.like_users.includes(this.loginUser.uid)
          } else {
              console.log("No such document!");
          }
      }).catch(function(error) {
          console.log("Error getting document:", error);
      });
    },
  }
}
</script>

<style>
.container_area {
  width: 300px;
  margin-top: 50px;
  padding: 20px;
  margin-right: auto;
  margin-left: auto;
  text-align: center;
}
.btn_area{
  margin-top: 20px;
}
.like-btn{
  font-size: 20px;
  color: #55c500;
  background-color: #fff;
  border: 2px solid #55c500;
  border-radius: 90%;
  outline: none;
}
.like-count{
  color: #55c500;
}
.border-double{
  border:double 10px dimgray;
}
</style>




```
以下の画面になればOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314105/75b10c2d-e698-b1c4-b6aa-cfe0a94b494b.png)


## Twitterログイン・ログアウト
▼[(公式)JavaScript で Twitter を使用して認証する](https://firebase.google.com/docs/auth/web/twitter-login?hl=ja)


```
logIn() {
  var provider = new firebase.auth.TwitterAuthProvider();
  firebase.auth().signInWithRedirect(provider);
},
logOut(){
  firebase.auth().signOut().then(function() {
    // Sign-out successful.
    console.log("signOut")
  }).catch(function(error) {
    // An error happened.
  });
},

```

これだけでログイン時はツイッター画面へ遷移し、連携&リダイレクトまでしてくれるのです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314105/0cd8931e-c026-0fe7-7a58-3c3eacb061f5.png)


## 現在ログインしているユーザーを取得する

▼[Firebase でユーザーを管理する](https://firebase.google.com/docs/auth/web/manage-users?hl=ja)

```
firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
    this.loginUser = user;
  } else {
    // No user is signed in.
  }
});
```
これをcreatedに記載すればページが読み込まれたタイミングでユーザー情報を取得できます。

## いいね機能実装
まずはコレクションを作成。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314105/91348a27-99cb-7fda-63dc-d2b9a49399d9.png)

like_usersフィールド(配列)を用意して「いいね」を押してくれたユーザーのIDをポンポンと追加する形でいいね機能を実装していきます。
その際、配列の追加にはarrayUnionを使います。

▼[firestore で配列の検索・追加・削除がサポートされたので試してみた](https://qiita.com/zaru/items/45574cf5919441953b2e)


配列の追加

```
docRef.update({
    "like_users": firebase.firestore.FieldValue.arrayUnion(user_id),
})
```

配列の削除

```
docRef.update({
    "like_users": firebase.firestore.FieldValue.arrayRemove(user_id),
})
```
あとは追加・削除ボタンが押される度にこれらを実行するだけ。
ちなみに数のカウントは変数を用意して配列数を代入してます。

            this.likeSum = this.posts.like_users.length

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314105/c63c5de8-7d5f-e251-c10b-42cde3164934.png)


これでいいね機能が実装できました！
そしていいね機能さえできればアンケート機能も簡単に実装できます。
興味のある方はoption1_usersフィールドとoption2_usersフィールドをこねこねして作ってみてください。


# 感想
という訳であっという間にいいね機能をもつサービスができてしまいました。

それにしてもFirebaseはやっぱすごいですね。
**ログイン処理つくるのめんどくせぇな**と思ってたのが嘘のようです。
もうツイッターログインを利用しないサービスなんて考えられません。ほんとありがとうございました。

# 終わりに

ぜひ究極の選択メーカーで遊んで見てください！

こんな投稿待ってます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314105/12827006-1481-4272-8588-b14c2f346351.png)



あとは技術系ではないのでCrieitにて究極の選択メーカーの裏話エピソードを書いてます！
▼[月500円の不労所得を得るためにWEBサービスを開発した話 〜 もうやめて！とっくに個人開発者のライフはゼロよ！ 〜](https://crieit.net/posts/500-WEB-5cb48f061acbb)


[Twitter](https://twitter.com/mitudama)もフォローよろしくです！:relaxed:

ではまた来月〜:wave: