Meteorが1.0になったので入門してみた(1/2)


##Meteorってなに

NodeJSのフルスタックなリアクティブ・フレームワークです。
裏でWebSocketを使っており、構築中にWeb画面がリアルタイムに変わっていく様子はかなり新鮮です。

すごいところは、フレームワーク内にMongoDBが内蔵されており、そのdbにクライアントサイドでもアクセスできます。(MiniMongoというclientサイドのDB機能が含まれているので、そういうことが可能であるみたいです。)

Baasのfirebaseも感動しましたが、あれはサーバサイドのCollectionとクライアントサイドのCollectionの同期は手動で紐付ける必要がありました。
MeteorはサーバからのCollectionの変更もクライアントからの変更も瞬時にお互いにミラーされ、
 **サーバサイドも含めての一つのアプリ**を作っているみたいです。

リアクティブプログラミングが可能なフレームワークでもあり、
例えばSessionの特定の値を監視して、変更された時だけログ出力するといったことも簡単にできます。


最近1.0になったよってアナウンスがあったので、チュートリアルをやってみました。

まだ書きかけでチュートリアルやりながらメモしつつという感じです。



##DiscoverMeteorをやってみる

[DiscoverMeteor](https://book.discovermeteor.com/chapter/introduction)をやりながらチュートリアルしてみます
**尚、[DiscoverMeteor日本語訳版](http://ja.discovermeteor.com/)が出来つつあります。**



### インストール
インストールはすごく簡単ですがNodeJsはインストール済みであることが前提かもしれません。

```sh:インストールコマンド
curl https://install.meteor.com | sh
```


まずはチュートリアルに従い「microscope」とかいう「ソーシャルニュース」アプリを作ってみます。

```sh:環境作り
$ meteor create microscope
```


``meteor create <<プロジェクト名>>``でプロジェクトを作ります。プロジェクト名のディレクトリが作られます。


### アプリ起動の仕方

```sh:起動
$ cd microscope
$ meteor

```

簡単なアプリが動き出しましたね。
[localhost:3000](http://localhost:3000)にアクセスします。
``Ctrl+C``でアプリを終了します。

### パッケージの使い方を学ぶ

meteorのパッケージ管理ツールでパッケージを追加していきます。


```sh:パッケージ追加
meteor add mizzao:bootstrap-3
meteor add underscore
```
mizzao:botstrap-3はこちらを[参照](https://github.com/mizzao/meteor-bootstrap-3)
underscore packageの方はofficialなパッケージです。

meteorにはパッケージは５種類があります

1. platform package：Meteor coreから分割された
2. First-party package：Meteorチームがメンテしてる
3. Third-party package:[ここ](https://atmospherejs.com/)で探すパッケージ
4. Local package:自作の``/packages``に置いたカスタムパッケージ
5. NPM package:NodeJsのモジュールパッケージ


### ファイル構造

作ったばかりの構成はこんな感じです。

```sh:作成時のファイル構成
.meteor
microscope.css  
microscope.html 
microscope.js
```

上記のうち``.meteor``以外は削除します。

代わりに以下のデイレクトリを作成します。


| 作成デイレクトリ | 役割 |
|:-----------|------------:|
| /server    | サーバサイドで動くコードを置きます |
| /client    | クライアントサイドで動くコードを置きます |
| /public    | 画像とか静的なファイルを置きます |
| /lib    | 後述します |


Meteorにおいて、あるルールで自動でファイルがロードされます。
なのでそのルールに従ってファイルをおけば勝手に読み込まれて組み込まれます。

ちなみに``/server``と``/client``でjsファイルを置くと、
それぞれサーバサイドとクライアントサイドでロードされますが、
それ以外のデイレクトリに置いた場合は **両方で**ロードされます。

ロードされるルールは以下となります。

1. /libに置いたファイルが最優先でロード
2. main.*のファイルがその次にロード
3. ファイル名のアルファベット順にロード


あと``.meteor`` の中についてですが、
``.meteor/packages`` ``.meteor/release``がそれぞれ、
インストールされているパッケージ情報、meteorのバージョンがわかります。
それ以外はさわらないほうがいいとのこと。
 

以下のCSSファイルを作成しておきます。

```css:client/stylesheets/style.css

.grid-block, .main, .post, .comments li, .comment-form {
  background: #fff;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  -ms-border-radius: 3px;
  -o-border-radius: 3px;
  border-radius: 3px;
  padding: 10px;
  margin-bottom: 10px;
  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15);
  -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15);
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); }

body {
  background: #eee;
  color: #666666; }

.navbar {
  margin-bottom: 10px; }
  /* line 32, ../sass/style.scss */
  .navbar .navbar-inner {
    -webkit-border-radius: 0px 0px 3px 3px;
    -moz-border-radius: 0px 0px 3px 3px;
    -ms-border-radius: 0px 0px 3px 3px;
    -o-border-radius: 0px 0px 3px 3px;
    border-radius: 0px 0px 3px 3px; }

#spinner {
  height: 300px; }

.post {
  /* For modern browsers */
  /* For IE 6/7 (trigger hasLayout) */
  *zoom: 1;
  position: relative;
  opacity: 1; }
  .post:before, .post:after {
    content: "";
    display: table; }
  .post:after {
    clear: both; }
  .post.invisible {
    opacity: 0; }
  .post.instant {
    -webkit-transition: none;
    -moz-transition: none;
    -o-transition: none;
    transition: none; }
  .post.animate{
    -webkit-transition: all 300ms 0ms;
    -webkit-transition-delay: ease-in;
    -moz-transition: all 300ms 0ms ease-in;
    -o-transition: all 300ms 0ms ease-in;
    transition: all 300ms 0ms ease-in; }
  .post .upvote {
    display: block;
    margin: 7px 12px 0 0;
    float: left; }
  .post .post-content {
    float: left; }
    .post .post-content h3 {
      margin: 0;
      line-height: 1.4;
      font-size: 18px; }
      .post .post-content h3 a {
        display: inline-block;
        margin-right: 5px; }
      .post .post-content h3 span {
        font-weight: normal;
        font-size: 14px;
        display: inline-block;
        color: #aaaaaa; }
    .post .post-content p {
      margin: 0; }
  .post .discuss {
    display: block;
    float: right;
    margin-top: 7px; }

.comments {
  list-style-type: none;
  margin: 0; }
  .comments li h4 {
    font-size: 16px;
    margin: 0; }
    .comments li h4 .date {
      font-size: 12px;
      font-weight: normal; }
    .comments li h4 a {
      font-size: 12px; }
  .comments li p:last-child {
    margin-bottom: 0; }

.dropdown-menu span {
  display: block;
  padding: 3px 20px;
  clear: both;
  line-height: 20px;
  color: #bbb;
  white-space: nowrap; }

.load-more {
  display: block;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  -ms-border-radius: 3px;
  -o-border-radius: 3px;
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.05);
  text-align: center;
  height: 60px;
  line-height: 60px;
  margin-bottom: 10px; }
  .load-more:hover {
    text-decoration: none;
    background: rgba(0, 0, 0, 0.1); }

.posts .spinner-container{
  position: relative;
  height: 100px;
}

.jumbotron{
  text-align: center;
}
.jumbotron h2{
  font-size: 60px;
  font-weight: 100;
}

@-webkit-keyframes fadeOut {
  0% {opacity: 0;}
  10% {opacity: 1;}
  90% {opacity: 1;}
  100% {opacity: 0;}
}

@keyframes fadeOut {
  0% {opacity: 0;}
  10% {opacity: 1;}
  90% {opacity: 1;}
  100% {opacity: 0;}
}

.errors{
  position: fixed;
  z-index: 10000;
  padding: 10px;
  top: 0px;
  left: 0px;
  right: 0px;
  bottom: 0px;
  pointer-events: none;
}
.alert {
          animation: fadeOut 2700ms ease-in 0s 1 forwards;
  -webkit-animation: fadeOut 2700ms ease-in 0s 1 forwards;
     -moz-animation: fadeOut 2700ms ease-in 0s 1 forwards;
  width: 250px;
  float: right;
  clear: both;
  margin-bottom: 5px;
  pointer-events: auto;
}
```


### Templateの使い方を学ぶ


Meteorの開発手法としてガワから作っていって最後に内部を作り込むという手法がオススメだそうです。


まずは``/client``の中で作業します

以下のHTMLファイルを作成

```html:client/main.html
<head>
  <title>Microscope</title>
</head>
<body>
  <div class="container">
    <header class="navbar navbar-default" role="navigation"> 
      <div class="navbar-header">
        <a class="navbar-brand" href="/">Microscope</a>
      </div>
    </header>
    <div id="main" class="row-fluid">
      {{> postsList}}
    </div>
  </div>
</body>
```

ポイントは``{{> postsList}}`` です。

ここには postsListテンプレートが入ります。
この後にpostsListテンプレートを作ります。

まずはテンプレートを置くディレクトリを作成しますね。

``client/templates``
さらに``client/templates/posts``も作って以下のファイルを置いていきます。


```html:client/templates/posts/posts_list.html

<template name="postsList">
  <div class="posts">
    {{#each posts}}
      {{> postItem}}
    {{/each}}
  </div>
</template>
```

```html:client/templates/posts/post_item.html
<template name="postItem">
  <div class="post">
    <div class="post-content">
      <h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
    </div>
  </div>
</template>
```

注意点としてtemplateエレメントのnameである``postsList``はどのテンプレート上でも使えます

このテンプレートエンジンは``Spacebars``と言います。詳細は[こちらで](https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md)


まあ他のテンプレートエンジンに似ているので、なんとなく見てれば動きはわかります。


これを実際に動かすには、``posts``オブジェクトをどこかで用意しないと・・・


ということで、以下のファイルを作成します。

```js:client/templates/posts/posts_list.js

var postsData = [
  {
    title: 'Introducing Telescope',
    url: 'http://sachagreif.com/introducing-telescope/'
  }, 
  {
    title: 'Meteor',
    url: 'http://meteor.com'
  }, 
  {
    title: 'The Meteor Book',
    url: 'http://themeteorbook.com'
  }
];
Template.postsList.helpers({
  posts: postsData
});
```

ポイントは```Template.postsList.helpers```です。
templateの```postsList```と紐づいています。

ちなみに``post_item.html``を見ていただくと
``{{domain}}``が足りません。``domain helper``を作りましょう

```js:client/templates/posts/post_item.js
Template.postItem.helpers({
  domain: function() {
    var a = document.createElement('a');
    a.href = this.url;
    return a.hostname;
  }
});
```

ちなみに

```js:js技
    var a = document.createElement('a');
    a.href = this.url;
    return a.hostname;
```

上記部分はDomain部分だけを取り出せるというjs技だそうです。

それと上記コードの **``this``**について言及する必要があります。
これは、``posts_list.html``内の``{{#each posts}}``にて取り出される各要素が``this``に代入されています。

### Meteor Collectionについて学ぶ

さっきまではクライアントサイドだったのでサーバサイドってことですね。

ちょっとここで感動ポイントきました。いったいなんなんだこれはッッ！！


まずは、以下のようにファイルを作成します。

```js:lib/collections/posts.js
Posts = new Mongo.Collection('posts');
```

ここであれ？っとなりました。/serverに置いてない・・・。

まずはアプリが起動中だと思うんで別タブを開いて新規Terminalから該当デイレクトリに移動します。

```sh
$ cd microscope
$ meteor mongo
```

これでmeteor専用のmongo環境に入ります。

以下のように
``db.posts.insert({title: "A new post"});``,
``db.posts.find();``とコマンドを打ってみてください。

```sh:mongodbShell
> db.posts.insert({title: "A new post"});

> db.posts.find();
{title: "A new post", _id: ObjectId("..")};
```

次におもむろにブラウザのコンソールを開いてください。

``Posts.findOne();`` と打ち込みます。

```js:ブラウザコンソール
Posts.findOne();
{title: "A new post", _id: LocalCollection._ObjectID};
```

すごくないですか・・・どういう仕組みかわからないですが、
一気にブラウザまで反映されてます。

もしかして・・・・と思いおもむろに、ブラウザのコンソールから以下を叩きます。


`` Posts.insert({title:"Second post"});``

```js:ブラウザコンソール
Posts.insert({title:"Second post"});
"tsCY2Wk4L2p7GvGnn"
```
なんかIDっぽいのが返ってきた・・・。


Terminalに戻ってコマンド``db.posts.find()``を打ちます。

```sh:mongodbShell
meteor:PRIMARY> db.posts.find();
{ "_id" : ObjectId("545439d965f913c98bf37b97"), "title" : "A new post" }
{ "title" : "Second post", "_id" : "tsCY2Wk4L2p7GvGnn" }
```

サーバにも反映された・・・・すごすぎ。
このクライアントサイドで動いているmongoDBはminiMongoというらしいです。


引き続きチュートリアルを続けるため、作ったDBの情報をリセットします。
アプリが起動中のTerminalで``ctrl+C``で抜けて以下のコマンドを実行します。

```sh:reset
$ meteor reset
$ meteor #再起動
```

以下のファイルを作成


```js:server/fixtures.js
if (Posts.find().count() === 0) {
  Posts.insert({
    title: 'Introducing Telescope',
    url: 'http://sachagreif.com/introducing-telescope/'
  });

  Posts.insert({
    title: 'Meteor',
    url: 'http://meteor.com'
  });

  Posts.insert({
    title: 'The Meteor Book',
    url: 'http://themeteorbook.com'
  });
}
```

``client/templates/posts/posts_list.js``を書き換えます。



```js:client/templates/posts/posts_list.js
Template.postsList.helpers({
  posts: function() {
    return Posts.find();
  }
});
```

書き換えた瞬間に変わるのはすごい・・・。


ところで、ちょっと復習なんですが

```js:lib/collections/posts.js
Posts = new Mongo.Collection('posts');
```

変数宣言に``var``が付いてないのわかりますでしょうか？
``var``をつけると **そのファイル内でスコープが閉じられる**そうです。この``Posts``はアプリ全体で使いたいので、
``var``は付けずに変数宣言を行います。

もう一点。

```js:client/templates/posts/posts_list.js
Template.postsList.helpers({
  posts: function() {
    return Posts.find();
  }
});
```

上記の``Posts.find()``では実はArrayではなくcursorが返ります。今流行りのリアクティブプログラミングというものらしいです。cursorはまだこの段階ではDBから値を取得しておらず、テンプレートエンジンでレンダリング直前に取得するようです。
このようにして透過的にサーバからの変更内容をクライアントに通知するわけですね。


なので、ログ出力する場合は``Posts.find().fetch()``でArrayに変換してください。
詳細は[こちら](https://docs.meteor.com/#/full/find)



### CollectionがClientと全共有されている問題の解決

標準では、``autopublish``パッケージが有効になっています。
autopublishはclientのCollectionとServerのCollectionがミラーリングされます。

```sh:
meteor remove autopublish
```

削除することによってこの機能をOffにします。

代わりに以下のファイル追加によってCollection単位で有効化します。

この辺の詳しい仕組みは[discovermeteor:Publications and Subscriptions](https://book.discovermeteor.com/chapter/publications-and-subscriptions)を読むと良さそうです。（そのうち翻訳したい）

サーバサイドの公開処理

```js:server/publications.js
Meteor.publish('posts', function() {
  return Posts.find();
});
```

クライアントサイドの受け入れ処理

```js:client/main.js
Meteor.subscribe('posts');
```

### ルーテイングの設定を行います。

以下のコマンドでルーテイングのパッケージを導入します。

```sh:terminal
meteor add iron:router
```

ルーテイングを行うにあたりヘッダやポスト一覧の表示などは
urlが変わっても基本的に同じ構成にしたいです。

![構成イメージ](https://book.discovermeteor.com/images/diagrams/router-diagram@2x.png)


まずはmain.htmlファイルを作成します。
今回使うiron-routerはbodyタグの中を作りこんでいきますので、それ以外をmain.htmlに作成します。


```client/main.html
<head>
<title>Microsope</title>
</head>
```

次は"layout" Templateを作成します。

```js:client/templates/application/layout.html
<template name="layout">
  <div class="container">
    <header class="navbar navbar-default" role="navigation"> 
      <div class="navbar-header">
         <a class="navbar-brand" href="{{pathFor 'postsList'}}">Microscope</a>
      </div>
    </header>
    <div id="main" class="row-fluid">
      {{> yield}}
    </div>
  </div>
</template>

```

ルーテイングの設定で常に上記Templateが呼ばれるように設定します。そしてurlによって``{{> yield}}``の箇所が変わるようにします。


以下のファイルを追加

```js:lib/router.js
Router.configure({
  layoutTemplate: 'layout'
});

Router.route('/', {name: 'postsList'});
```

``name``プロパティに設定したTemplateが``{{> yield}}``に入るようになります。



それにしても``router.js``は``lib``に入れるんですね。``/server``か``/client``のどちらかに入れると思ってました。

``/lib``に入れるのはアプリが何かする前に呼ばれることを保証するためだそうです。でも共用コードに含まれることになるのは気持ちが悪いような・・・・。


### ローディングインジケータを表示

ページを最初に開いたとき、``Meteor.subscribe('posts')``が実行完了するまで時間がかかるため（サーバからデータを取得するまで完了しないため）空欄表示になってしまいます。

それを防ぐための処理を追加していきます。
``Iron Router``の機能を利用します。

まずはmain.js内の``Meteor.subscribe('posts');``をこちらに **移動させます**。

```diff:lib/router.js
  Router.configure({
    layoutTemplate: 'layout',
+   waitOn: function() { return Meteor.subscribe('posts'); }
  });

  Router.route('/', {name: 'postsList'});
```
この変更によって、``Iron Router``はそのルートへの表示準備が完了したことが
わかるようになったわけです。

さて準備中は組み込みのローディング中表示が出るわけですが、こちらも自分好みに当然修正可能です。

また、``lib/router.js``を変更します。

```diff:lib/router.js
  Router.configure({
    layoutTemplate: 'layout',
+   loadingTemplate: 'loading',
    waitOn: function() { return Meteor.subscribe('posts'); }
  });

  Router.route('/', {name: 'postsList'});
```

ちなみににこの設定は全ルート共通にwaitOn関数を定義しているため、
本アプリに一番最初にアクセスした瞬間にだけ実行される点に注意してください。
ブラウザに記憶されたら、以後実行されません。

``loading Template``を設定しましょう。

スピナー表示のためのモジュールを導入します。

```sh:Terminal
$ meteor add sacha:spin
```

以下のファイルも作成

```js:client/templates/includes/loading.html
<template name="loading">
  {{>spinner}}
</template>

```

ですがスピナーの変化わからない・・・

### post詳細画面の追加

postの詳細画面を追加してみます。

まずRouteを追加します。

```diff:lib/router.js
	Router.configure({
	  layoutTemplate: 'layout',
	  loadingTemplate: 'loading',
	  waitOn: function() { return Meteor.subscribe('posts'); }
	});

   Router.route('/', {name: 'postsList'});
+  Router.route('/posts/:_id', {
+	  name: 'postPage',
+     data: function(){return Posts.findOne(this.params._id);}
+	});

```
``lib/router.js``の``data``関数で取得した結果が
``postPage`` Templateの``this``と紐付きます。

``/posts/:_id``の記述はよくあるやつですね。
urlの``:_id``に対応する文字列が``this.params._id``で取得できると。




対応するTemplateを追加


```js:client/templates/posts/post_page.html
<template name="postPage">
  {{> postItem}}
</template>
```

全然詳細画面じゃない。postItem Template流用ですね。


ところで``this``とtemplateの対応について補足があります。

```js
{{#each widgets}}
  {{> widgetItem}}
{{/each}}
```
 上記の場合widgetsがCollectionで各要素がwidgetItem Templateの``this``に入ります。
これはいつものやつですね。

他にもありまして、


```js
{{#with myWidget}}
  {{> widgetPage}}
{{/with}}
```
と

```js
{{> widgetPage myWidget}}
```
は全く同じ意味で、　``myWidget``が``widgetPage``Templateの``this``に入ります


これでとりあえず詳細画面はできましたが、そこに遷移するためのリンクがないです。
それを作ります。


まずはpostsList画面にDiscussボタンを作りそこからリンクします。

```diff:client/templates/posts/post_item.html
	<template name="postItem">
	  <div class="post">
	    <div class="post-content">
	      <h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
	    </div>
+	    <a href="{{pathFor 'postPage'}}" class="discuss btn btn-default">Discuss</a>
	  </div>
	</template>
```

これで動くようになります。・・・
でも実はちょっと変なところがあります。
``a href="{{pathFor 'postPage'}}"``って変換されると``a href="/posts"``ですよね・・・。
これで動くって変じゃないですか・・。
これは``Iron Router`` が頭がいいことにrouter設定を元にidが必要だということを読み取って対応してくれたらしいです。

### NotFoundページへの遷移を追加
Templateから作成

```js:client/templates/application/not_found.html
<template name="notFound">
  <div class="not-found jumbotron">
    <h2>404</h2>
    <p>Sorry, we couldn't find a page at this address.</p>
  </div>
</template>
```

ルーテイング変更

```diff:
 Router.configure({
   layoutTemplate: 'layout',
   loadingTemplate: 'loading',
+  notFoundTemplate: 'notFound',
   waitOn: function() { return Meteor.subscribe('posts'); }
 });

//...

```

[適当](http://localhost:3000/nothing-here)に遷移してみてちゃんと表示されることを確認します。

でもこれだと[localhost:3000/posts/xyz](http://localhost:3000/posts/xyz)にアクセスしてもNotFoundにならないです。

データが存在しない場合にもNotFoundに行きたい場合は以下のように追加します。

```js:lib/router.js
//一番下に追記
Router.onBeforeAction('dataNotFound', {only: 'postPage'});
```
これは``data``関数がnull, false, undefined,emptyのいずれかを返した場合に
notFound 扱いにします。

### sessionの話

sessionはグローバル変数みたいで嫌うことも多いですが、クライアント固有の情報、
例えば一時的にクライアント上非表示にしているなど、クライアント固有の情報保存には必要です。

使い方は簡単です。
ブラウザのコンソールから以下のように実行してください。

```js:ブラウザコンソール
Session.set('pageTitle', 'A different title'); //値の設定
Session.get('pageTitle'); //値の取得
```

ここですごい``Session.set``の話。
セットする値が設定済みの値と同じ場合は関数呼び出しを避ける仕組みになっているそうです。（仕組みが想像できない）

もう一つ、内部的な仕組みが想像できないけどすごい機能です。
``Autorun``です。

以下のコードをブラウザコンソールから実行してみてください。

```js:ブラウザコンソール
Tracker.autorun( function() { console.log('Value is: ' + Session.get('pageTitle')); } );
Session.set('pageTitle', 'Yet another value');
Value is: Yet another value
```
設定した瞬間に出力されとる・・・。


``autorun``ブロック内のコードが内部の``Session.get('pagetitle')``の変更状態を監視して、変更されると自動実行されるというものです。

ドキュメント曰くsessionは``reactive data sources``だから可能とのこと。[詳細はこちらで](https://docs.meteor.com/#/basic/Tracker-autorun)

あと最後に補足です。 **開発中はリロードボタンを押すとセッション情報消えます。**
### ユーザ管理

ユーザ管理の使い方です。
bootstrapを使っているので以下のモジュールを導入します。

```sh:Terminal
meteor add ian:accounts-ui-bootstrap-3 #accounts-uiのbootstrap版
meteor add accounts-password
```
headerを拡張してアカウントログインボタンを組み込みます。

以下のようにファイルを変更

```diff:client/templates/application/layout.html
 <template name="layout">
   <div class="container">
-    <header class="navbar navbar-default" role="navigation">
-      <div class="navbar-header">
-         <a class="navbar-brand" href="{{pathFor 'postsList'}}">Microscope</a>
-      </div>
-    </header>
+   {{> header}}
     <div id="main" class="row-fluid">
       {{> yield}}
     </div>
   </div>
```

``header Template``を追加


```js:client/templates/includes/header.html
<template name="header">
  <nav class="navbar navbar-default" role="navigation">
    <div class="container-fluid">
      <div class="navbar-header">
        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navigation">
          <span class="sr-only">Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="{{pathFor 'postsList'}}">Microscope</a>
      </div>
      <div class="collapse navbar-collapse" id="navigation">
        <ul class="nav navbar-nav navbar-right">
          {{> loginButtons}}
        </ul>
      </div>
    </div>
  </nav>
</template>
```
ポイントは``{{> loginButtons}}``の箇所ですね。[詳細はこちらで](https://github.com/ianmartorell/meteor-accounts-ui-bootstrap-3/)

これで組み込みのaccount-ui画面が出るようになります。

実際にアカウントを作ってログインしてみましょう
アカウントは作成できましたか？

実は``accounts``パッケージを入れることで、自動でCollectionが作成されます。``Meteor.users``です。

実際にブラウザコンソールからアクセスしてみましょう。

```js:ブラウザコンソール
Meteor.users.findOne();
Object {_id: "foRHJjMWe8L9H4Bdi", profile: Object, username: "abe"}
```
帰ってきた結果を見てみましょう。
_isとusername,profileくらいしかないのが確認できると思います。
ちなみに``Meteor.user()``でも同じ結果が返ります。

サインアウトしてもう一つアカウントを作ってみます。
そのアカウントで再ロングインしてください。

今度は以下のコマンドをブラウザコンソールから実行します。

```js:ブラウザコンソール
Meteor.users.find().count();
1
```
2じゃなくて1が返ってきます。

今度はMongoshell(Terminalから``meteor mongo``)から見てみましょう

```sh:mongoShell
meteor:PRIMARY>db.users.count()
2
```
 こっちはちゃんと2が返ってきました。
これはなんでか？

実は``autopublish``パッケージを削除したことを覚えていますか？
これを削除することによってサーバ側のCollectionとクライアント側のCollectionのミラーを停止させたはずです。

そして``publication``と``subscription``の設定を行ったことも。
なのに``Meteor.users``Collectionは見えましたね。

実は``account``パッケージがやってくれたんです。便利ですね。
``account``パッケージは現在のユーザ情報だけを``publish``にしてくれたわけです。クライアントからは自分以外の情報が見えてはいけないですからね。
それだけではなくフィールドのフィルタも行ってくれてます。
見てみましょう

```sh:mongoShell
meteor:PRIMARY> db.users.findOne()
{
	"_id" : "55vyZRn3Na2uietY8",
	"createdAt" : ISODate("2014-11-01T13:49:52.625Z"),
	
//なんかたくさんでる・・
	}
}
```
これでクライアント側はフィールドがフィルタされてるってことがわかったかと思います。

[詳細はこちらで](https://docs.meteor.com/#/full/meteor_users)

### リアクティブプログラミングを学ぶ


リアクティブプログラミングについて調べると、
大抵例としてExcelの話が出ます。Excelの各Cellには値だけでなく関数を記述すると思います。
そして依存しているCellの値を書き換えると瞬時に関連するCellの値が再計算されます。
これをフレームワークとしてプログラミングの世界でも適用しようというのがMetelorの思想になります。

javascriptで値監視をする場合は``.observe()``関数を使うと思います。

例えばこんな風に書くとか

```js:例
Posts.find().observe({
  added: function(post) {
    // when 'added' callback fires, add HTML element
    $('ul').append('<li id="' + post._id + '">' + post.title + '</li>');
  },
  changed: function(post) {
    // when 'changed' callback fires, modify HTML element's text
    $('ul li#' + post._id).text(post.title);
  },
  removed: function(post) {
    // when 'removed' callback fires, remove HTML element
    $('ul li#' + post._id).remove();
  }
});
```

もう見ただけで将来破綻することが目に見えています。

Meteorでは宣言的アプローチを行います。
オブジェクト間の関係性を記述し、自動で値監視を行うようにします。
例えば以下のように記述します。


```html:
<template name="postsList">
  <ul>
    {{#each posts}}
      <li>{{title}}</li>
    {{/each}}
  </ul>
</template>
```

```js:
Template.postsList.helpers({
  posts: function() {
    return Posts.find();
  }
});
```

上記のように記述しておくことによってMeteorが``.observe()``関数をつかって値の変化とHTMLの要素の対応を覚えてくれます。

計算処理についてもmeteorは監視してくれます。
計算処理の中に``reactive data source``が含まれていればその計算は該当する``reactive data source``の変化に影響を受けることは明らかなので依存対象に自動で含めてくれます。


例を挙げてみます。

```js:
Meteor.startup(function() {
  Tracker.autorun(function() {
    console.log('There are ' + Posts.find().count() + ' posts');
  });
});
```

上記の``Meteor.startup()``ブロック内のコードはPost Collectionがロード完了した際に一度だけ実行されます。

見るべきポイントは``autorun``ブロックです。
``Posts.find()``は``reactive data source``である``cursor``を返します。つまりブロック内の計算は``Posts.find()``の変化に影響するため、依存対象に含まれます。

結果、``posts``の内容が変化するたびに自動で実行されるわけです。

以下実行例を示します。

```
> Posts.insert({title: 'New Post'});
There are 4 posts.
```


長くなったので続きは[こっちで](http://qiita.com/abe00makoto/items/d67fc9b732f0d3737470)