RubyでFirebaseのFirestoreからデータ取得と追加する方法

# RubyでFirestoreからデータを取得したり追加したり
今回は、RubyでFirestoreからデータを取得する際のクエリ発行してくれるコードやデータを追加するコードに関してまとめます。

## Firestoreとは
Firebaseが用意しているNo SQLのクラウドデータベースです。

## 用語
Firestoreにおける用語はとりあえず、下記の３つを知っておけば大丈夫だと思います。

[Cloud Firestore データモデル](https://firebase.google.com/docs/firestore/data-model?hl=ja)

#### コレクション
データ（ドキュメント）を格納する大枠。FirebaseコンソールのサイドバーにあるCloud Firestoreをクリックすると、画面の1番左にあるのがコレクションになる。1つのコレクションに、それに関するデータ（ドキュメント）が保存されていく。

#### ドキュメント
コレクションに格納されていくデータ。データは一意のドキュメントIDというもので管理されており、そのドキュメントIDに紐づけられたフィールドが存在する。

#### フィールド
1つのドキュメントに紐づけられたデータ。1つのドキュメントに複数紐づけることが可能である。

上記のような入れ子構造がFirestoreのデータモデルになります。ですので、「コレクションからドキュメントへ、そしてフィールドの中にある値を取ってくる」というのがFirestoreのデータを取得する行為になります。結構段階踏まないといけないような印象を受けますね。

下記に書くメソッドは、Firestoreのメソッドを使用できるようにする必要があります。

## firebaseをRailsと連携させる
　mysqlのORMであるActiveRecordを使用するでなく、fiestoreへデータアクセスするためのgemを使って連携させます。

## firesotreを使えるようにする
　firestoreを使えるようにするgemが用意されており、

```Gemfile
gem 'google-cloud-firestore'
```

を使います。

## Firestoreのオブジェクトを作る
[firestoreの設定](https://firebase.google.com/docs/firestore/quickstart?hl=ja#ruby_1)

[class_attributeについて](https://qiita.com/cuzic/items/ffd115f1e17458020b1b)

```firebase.rb
class Firesbase
  require 'google/cloud'

  class_attribute :connecting
  self.connecting = Google::Cloud.new(コンソールで作成したプロジェクトネーム).firestore
end
``` 

## コレクションを指定する
まず、どのコレクションからデータを取得するかを確定させます。collectionメソッドを使い、引数にFirebaseコンソール上で作成したコレクション名を指定すると、そのコレクションに対して、メソッドを使ってデータを取得できるようになります。

```collection.rb
  hogehfuges_colleciton = connecting.collection 'hogefugas'
```

## データを取得する
取得用のメソッドでメインとして使うのは下記の３つだと思われます。

#### document

```get_by_document.rb
  hoge = hoge_collection.document(ドキュメントID).get      #Google::Cloud::Firestore::DocumentSnapshot
  fuge = fuge_collection.document(ドキュメントID).get.data # Hash
```

documentはドキュメントIDを引数にしてあげることで、そのドキュメントIDに紐づいたデータを取得してきます。getメソッドを使用すれば、Google::Cloud::Firestore::DocumentSnapshotというオブジェクトで取得できますが、このままでは中のフィールドのデータを扱えないので、dataメソッドを使います。dataメソッドを使うと、取得してきたドキュメントに紐づいたフィールドをキーにしたハッシュにしてくれて、下記のようにハッシュの操作で簡単にデータにアクセスできるようになります。

```data.rb
  fuge[:fugefuge_name]
```

#### where
whereは条件にあったものを取得します。whereの場合、getメソッドを使用すると、オブジェクトの型がEnumeratorになるので、ループ処理か、Rubyの標準ライブラリにあるループ処理を内包したメソッド（例えばmapとか）を使用する必要があります。ループして取り出したデータには、dataメソッドを使うことができるので、データにアクセスすることができます。

whereの条件式に入れるときはいつもの比較演算子を用いることができます。
条件になる文字列はダブルクォーテーションで囲います。

例

```sample.rb
where("createdAt", ">=", Today)
```



```get_by_where.rb
  snap = hogefugas_collection.where(条件).get #Enumerator
  snap.map do |hoge|
    {
      "hoge_name" => hoge.data[:hoge_name],
      "update_at" => hoge.data[:update_at]
    }
  end
```

#### order
orderは引数にフィールドを指定し、そのフィールドが存在するドキュメントを取得します。orderもgetメソッドを経由すると、オブジェクトの型がEnumratorになるので、ループさせてからデータアクセスします。
下記のコードでは、dataメソッドの代わりにdocument_idメソッドを使用しています。これによってフィールドではなく、そのドキュメントのドキュメントIDを取得することができます。

```get_by_oder.rb
  hoges = hogefugas_collection.order('updatedAt').get.map { |hoge| hoge.document_id }
```

## データを追加
setメソッドを使用します。保存したいフィールドをハッシュのキーにする形で、データを作ります。それをsetメソッドの引数にしてあげれば、指定したコレクションへドキュメントIDを自動生成しつつ、Firestoreへ保存してくれます。

```set.rb
def save(id, hoge)
    huge = {
      id: id,
      hogehoge: hoge,
      update_at: DateTime.now.strftime("%Y-%m-%d-%H:%M")
    }
    collection.doc.set(huge)
  end
```

## データを更新する
updateメソッドを使います。更新したいコレクション内のドキュメントIDを指定し、そのフィールドをupdateメソッドの引数にすることでデータの更新をすることができます。

```update.rb
  def edit(id, hoge)
    document_id = collection.where("id", "=", id).get.first.document_id
    collection.document(document_id).update(
      hogehoge: hoge,
      update_at: DateTime.now.strftime("%Y-%m-%d-%H:%M")
    )
  end
```