MeteorはTwitter連携ログインを作るのがめちゃ楽


小ネタです。作り方は割愛します。コードに興味がある方は、[GitHubレポジトリ](https://github.com/hashrock/meteor-vue-example)を直接見てください。


# 一行でログインが書けるぞ

Meteorアプリをセットアップした後に、下記手順だけでTwitter連携ログインを作ることができます。HTML側に一行足すだけです。

まず、login providerパッケージを追加します。

```
meteor add accounts-twitter
```

ログインアカウントUIパッケージを追加します。

```
meteor add accounts-ui
```

HTMLのbody内に下記のコードを挿入します。
js側にコードは必要ありません。


```
{{> loginButtons}}
```

すると、下記のボタンが表示されます。

![スクリーンショット 2015-05-05 22.48.49.png](https://qiita-image-store.s3.amazonaws.com/0/32596/0b52f952-c17e-fbec-3646-37f3fee4cae8.png "スクリーンショット 2015-05-05 22.48.49.png")


赤くて不穏なボタンなんですが、これはTwitterのAPIなどが未設定なので設定してくれよ、ということですね。このボタンをクリックすると、下記のダイアログが表示されます。

![スクリーンショット 2015-05-05 22.49.55.png](https://qiita-image-store.s3.amazonaws.com/0/32596/dd96803c-3cf0-e8d9-1b6c-1558984c8059.png "スクリーンショット 2015-05-05 22.49.55.png")

親切なことに、Twitter APIの取得方法、さらにAPIキーの入力場所までありますね。

あとはここに書いてある手順に従い、Twitterアプリを登録し、設定を済ませるだけです。
**手順はこれで全てです。**

## 動いている様子

![スクリーンショット 2015-05-05 23.36.23.png](https://qiita-image-store.s3.amazonaws.com/0/32596/9b06dca9-216f-62db-b2d7-db6a437374e3.png "スクリーンショット 2015-05-05 23.36.23.png")

`Sign in with Twitter`をクリックします。

![スクリーンショット_2015-05-05_23_36_39.png](https://qiita-image-store.s3.amazonaws.com/0/32596/a69c3f4b-3b68-b165-c2e9-c498bfe94a47.png "スクリーンショット_2015-05-05_23_36_39.png")

ポップアップでログインダイアログが出ます。

![スクリーンショット 2015-05-05 23.36.43.png](https://qiita-image-store.s3.amazonaws.com/0/32596/be14bcd4-7a51-8721-829d-50e88989d251.png "スクリーンショット 2015-05-05 23.36.43.png")

ログインユーザ名が出ましたね。以後、ユーザID及び、ログイン判定は下記コードで行います。

```
Meteor.userId()
```

# 所感

超簡単ですね。

今までpassport-twitterとかでめっちゃ頑張ってたのはなんだったんでしょうか…

さらに、TwitterのAPIキーをどこで管理するんだ問題にも対処できています。jsonに書いておくのも丸見えで嫌だし、それをgitで管理すると大変なことになるし、productionとdevelopmentで分けないといけないし、かといって、環境変数で設定するのも、動かす時になって設定忘れそうですし。

その点、初回にインストラクション付きで設定画面開いてくれるというのは、WordPressの初回設定並みに親切といえるでしょう。

## Meteorのイマイチな点

* npmじゃない。独自パッケージマネージャを持っています。[fibers前提のコードになってるから、npmなんて使ってもしょうがない](http://www.reddit.com/r/javascript/comments/2eu7nj/isobuild_why_meteor_created_a_new_package_system/)みたいなことも言ってますが、なぜそんなに何から何まで作り直さないと気が済まないんでしょうか。npmに名前空間切ればいいような。
* npmも使うことはできますが、browserifyとかじゃなく、[独自記法](https://coderwall.com/p/srvdta/using-npm-modules-in-meteor)を使います。どういう仕組みなのかとかまでは調べてませんし、調べるモチベーションも今ひとつ起きません。
* コレクション丸見え＆いじり放題な`autopublish`と`insecure`がデフォルトで有効になっています。プロトタイピングには便利ですが、脆弱性を作り込まないよう留意すべきでしょう。この辺りは[Meteor利用時に留意すべきセキュリティリスク](http://qiita.com/Hironori777/items/dd0710d925011ab54a28)という記事によくまとまっていました。
* Herokuへのデプロイは辛そうです。horseのbuildpackが用意されてます（参考:[MeteorをHerokuにデプロイする](http://qiita.com/kobarei/items/c2df840bc02391e907a1)）が、今の所動くところまでは持っていけていません。`meteor deploy`でmeteor公式へのデプロイもできますが、この前使いたかった時に落ちていたので、検証用以外に使うのはどうかなと思います。自前のVPSなどで動かすのが一番平和そうですね。

# おまけ：Vue.jsを使う

MeteorはビューにMustacheを使いますが、SPAにはちょっと非力な感じがしたので、Vue.jsを使いました。

Vue.jsの作者さんから直接おすすめされたのが、下記のパッケージです。

[zhouzhuojie/meteor-vue](https://github.com/zhouzhuojie/meteor-vue)

mustacheと衝突しないように、タグ文字が角括弧になってますが、それ以外は普通のVue.jsの記法を使えます。いままでdataに書いていたコレクションを、sync内に移動することで、リアルタイム同期するようになります。

Vue.jsもMeteorも双方ともにプロトタイピング向きなので、相性は良好です。コード量は非常に少なく（例：[Todoアプリのコード](https://github.com/hashrock/meteor-vue-example/blob/master/todo.js)）、また、やりたいことに応じて、ClientでやるのかServerでやるのか、それともDirectiveで済ませてしまうのか、という選択肢が選べるのは楽でした。

```js
if (Meteor.isClient) {

  //partial templateがレンダリングされた後にVue.jsの初期化を行う
  Template.hello.rendered = function() {
    new Vue({
      el: '#vue-demo',
      data: {
        //サーバと同期する必要のない変数はここへ
        message: ""
      },
      sync: {
        //サーバと同期したい変数はここに書く
        "tasks" : function(){
          return Tasks.find();
        }
      },
      methods: {
        addTask : function(){
          this.message = "";

          if (! Meteor.userId()) {
            this.message = "ログインしてください！";
            throw new Meteor.Error("not-authorized");
          }
          
          //認証はサーバサイドで行いたいので、callを使う。呼び出した先でMeteor.userIdによる検証を行っている。
          Meteor.call('insertTask',this.taskName);
          this.taskName = "";
        },
        removeTask : function(id){
          //今の所誰でも削除可能にしてあるが、認証必須にしたければ、insertTaskと同じようにサーバ側で実装すること。
          Tasks.remove(id)
        }
      }
    });
  }
}
```


```html
<body>
  <h1>Meteor BBS</h1>
  {{> loginButtons}}
  {{> hello}}
</body>

<template name="hello">
    <div id="vue-demo">
        <p>[[message]]</p>
        <ul>
            <li v-repeat="task : tasks">
                [[task.username]]
                [[task.name]]
                <button v-on="click: removeTask(task._id)">x</button>
            </li>
        </ul>
        <input v-model="taskName" />
        <button v-on="click: addTask(taskName)">Add Task</button>
    </div>
</template>
```


# 参考サイト

 * [How To Add a Twitter Login System to Your Meteor Application](http://meteortips.com/tutorial/twitter-login-provider/)