【備忘録】Rails＋MongoDBを使ったページがHeroku環境でMongoDBの接続ができるまでの手順

[【備忘録】Rails＋MongoDBを使用を想定したアプリの雛形作成からGitHubとHerokuにデプロイするまで](https://qiita.com/giosc103/private/3246e6ac93d767d32cbd)
の続きです。
Heroku環境でRailのページからMongoDBの接続しDBの読み書きができるとこまで行います。

#前提
前回の雛形作成で、GitHubにソース管理が行われていて、
Herokuにデプロイまで行っている。


#準備
今回はDBにローカル、Heroku共にMongoDBを使用することにします。(Herokuが公式にサポートしているのはPostgreSQLですのでMongoDBは少し手順が複雑です)
また、MongoDBをRailsから使用するためにはORマッパーのMongoidを使用する必要があります。


###MongoDBとは
MongoDBはドキュメントDBの一種です。ドキュメントDBはNoSQLデータベースの一種で、RDBとは違いJSONをスキーマ定義なしで保存することができます。

###Mongoidとは
[mongoDBとmongoidの関係性](https://teratail.com/questions/120889)
> MongoidはMongoDBのO/RMapper（正しくはMongoDBはDocumentなのでODMapperらしいですが・・・）です。
O/RMapperって何って言われると長くなっちゃうんで下記のとことかググったりしてもらうといいんですが・・・
http://e-words.jp/w/O-Rマッピング.html
Ruby側のオブジェクトとDB(今回だとMongo)を関連付けてくれて保存や検索とかの機能を提供してくれてるものです。


# MongoDBのインストール
ローカルや、Heroku環境でのDBの状態をターミナルで確認するために、下記を参考にMongoDBをインストールします。
[MongoDBのインストール](https://qiita.com/yoh-nak/items/f0c429f10347ae7ec98b)

#Gemfile
BootstrapとMongoDBを使用するためにGemfileをいじり、`$bundle update`を行います
[Rubygems](https://rubygems.org） からGemライブラリを検索し、Gemfileに追記します。

![スクリーンショット 2018-12-22 17.47.08.png](https://qiita-image-store.s3.amazonaws.com/0/238856/1d4fdd32-fb18-a6b4-e63d-0b3b738c78e4.png)


```Gemfile:Gemfile
# mongoid(DB:ローカル、heroku共にMongodbを使用することを想定)
group :development, :test, :production do
  gem 'mongoid', '~> 7.0', '>= 7.0.2'
end
```

Gemfileを編集した後にbundle installを行います。

```cmd：ターミナル
$ bundle install
```

(一回--path vendor/bundleでパスを指定すると次回以降はこのパスにインストールしにいきます)

### Heroku環境内のMongoDB接続準備
次にHeroku環境でMongoDBに接続する準備をします。まず、Herokuのアプリの管理ページからアドオン:mLab MongoDBを追加していきます。
configure Add-onsからアプリ管理画面にいきます。
![スクリーンショット 2018-12-24 15.33.20.png](https://qiita-image-store.s3.amazonaws.com/0/238856/6f74a293-6043-1f6a-79ad-6a060af4364c.png)

次にアプリ管理画面からmLab MongoDBを追加します。
この時Plan nameを聞かれますが、`SandBox - Free`を選択します。
![スクリーンショット 2018-12-24 15.35.37.png](https://qiita-image-store.s3.amazonaws.com/0/238856/19942a71-0de2-7f9a-a46f-e2591e1f8a64.png)
![スクリーンショット 2018-12-24 15.36.03.png](https://qiita-image-store.s3.amazonaws.com/0/238856/f5b6d37a-2708-2e20-45bf-b48fd8755c51.png)

次にターミナルからHerokuから接続先のMongoDBのURIを取得します。

```cmd/ターミナル
$ heroku config -a {アプリ名}　|grep MONGODB_URI
```

取得したURLをmongoid.ymlに設定します。

```yml:config/mongoid.yml
production:
 clients:
   default:
    uri: (取得したuri)
    options:
      connect_timeout: 15
  options:
    raise_not_found_error: false
```

余談:　アプリによりますが、DBのテーブルに何も入っていない状態も想定する場合、optionsのraise_not_found_errorをfalseに設定しないと、MongoDB　からレコードを取得する際にDocument not foundエラーとなります。。productionおよびdevelopment、test環境にraise_not_found_errorをfalseに設定しておきましょう(デフォルトではtrue)


#Heroku環境確認
さてDBに読み書きするページを作成しましたら、デプロイしてHeroku環境でDB読み書きができるか確認です。

下記コマンドでHerokuにデプロイできます

```cmd:ターミナル
$git add -A
$git commit -m "Heroku環境からDB接続するで"
$git push heroku master
```

アプリ上からDBに書き込みます。

例:簡易掲示板を作成しました。投稿すると下記のコレクション(テーブル)を想定して書き込みに行きます。
コレクション名:chat

フィールド（カラム)|型
---|---
UserName|string
Contents|string

![画面収録 2018-12-28 16.06.47.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/238856/6cc117fa-96b5-1e69-2682-fde2be324aeb.gif)


最後にターミナルからheroku環境のMongoDBを確認します。
接続情報を取得し、mongoに接続しDB内を確認します。

なお、mLabの管理画面からもコマンドを確認することもできます。ただしUserNameとPasswordはHerokuのconfigを確認する必要があります。
以下では、chatコレクションにレコードが存在するか確認してます。

```cmd:ターミナル

$ heroku config | grep MONGODB_URI
#適時読み替えてください 
mongodb://heroku_dxxxxx:pppppppppppppppppppppppp@dxxxxx.mlab.com:3xxxx/heroku_dxxxxx
          UserName      Password                 Address         Port  Database

#configをもとに書き換えてください
$ mongo <Address>:<Port>/<Database> -u <UserName> -p <Password>

> db.chats.find();
{ "_id" : ObjectId("Hoge"), "userName" : "test1", "comments" : "testcontents1", "updated_at" : ISODate("datedate"), "created_at" : ISODate("datedate") }

```


無事HerokuからDBを接続できたようです。


#バージョン
執筆時点でのバージョンです

サービス|バージョン
---|---
MongoDB|v4.0.2 
Mongoid|v7.0.2 


#参照
[Rails + MongoDBのメモ](https://qiita.com/oggata/items/58c3c8ef399b690853ba)
ここら辺の自分なりのまとめです。ありがとうございます。

[世界第4位！最有力NoSQLデータベースMongoDBはRDBとどう違うのか？特徴と使い分け](https://tracpath.com/works/development/nosql_mongodb/)