GCP 自然言語処理API(natural language processing)をつかって感情分析してみた(Docker × Rails × heroku × GCP)


#前書き
RailsアプリでGCPのAPIを叩きたかったけれど、全然情報が出てこなかったのでまとめておく
あと以下の記事を参考にしても再現できなくて少し困った
https://ebi-works.com/gpc-app/
https://qiita.com/fuj1kky/items/4912ca7e821a5aafebdc
#実現したこと
###Docker + Rails + GCP + heroku
自作したWEBアプリの口コミ（コメント）を投稿したときに
![スクリーンショット 2021-11-09 15.14.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427079/46d2f091-44a7-bd16-38f0-578b05009ed7.png)

bodyの内容に対してGCPで用意されている自然言語処理の感情分析のAPIを叩き
`score`と`magnitude`を取得しDBに保存
![スクリーンショット 2021-11-09 15.16.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427079/05234abe-1b94-f99e-6fd4-84bfca409284.png)


#開発環境
```
Docker version 20.10.5, build 55c4c88
ruby 2.6.8
Rails 6.1.4.1
```
#①処理の流れ
該当プロジェクトのAPIを有効にしAPIキー（json）を取得していることを前提とする

```
gem 'google-cloud-language'
```
```app/models/concerns/google_cloud_platform_authentication.rb
module GoogleCloudPlatformAccessAuthentication
  extend ActiveSupport::Concern
  class Authorization
    def self.init
      Google::Cloud::Language.language_service version: :v1
    end
  end
end

```

```app/models/comment.rb
class Comment < ApplicationRecord
  include GoogleCloudPlatformAccessAuthentication

  belongs_to :account
  before_save :save_sentiment_analysis

  # bodyの内容をもとにGCPで用意されているNLPapiで感情分析を行いその値をDBに格納するメソッド
  # HACK: fatモデルの原因になりそう
  def save_sentiment_analysis
    client = Authorization.init

    body = read_attribute(:body)
    document = { content: body, type: :PLAIN_TEXT }
    response = client.analyze_sentiment document: document

    sentiment = response.document_sentiment

    score = sentiment.score.to_f.round(1)
    magnitude = sentiment.magnitude.to_f.round(1)

    write_attribute(:score, score)
    write_attribute(:magnitude, magnitude)
  end
end
```
```
#app/db/Schemafile

create_table "comments", id: :bigint, unsigned: true, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", comment: "アカウント情報に紐づくコメント(POSTデータ)" do |t|
  t.integer "account_id", null: false
  t.string "body", limit: 191, default: "", null: false
  t.string "ip", comment: "リモートipアドレス"
  t.integer "blacklist", default: 0, comment: "ブラックリストに入っているipアドレスかどうか判別するフラグ"
  t.float "score", comment: "コメント全体がネガティブ傾向かポジティブ傾向か"
  t.float "magnitude", comment: "コメントに感情的なワードがどれくらい含まれているか"
  t.datetime "updated_at", precision: 6, null: false
  t.datetime "created_at", precision: 6, null: false
end

```
```app/config/(gcpのページからダウンロードしたjsonファイル).json
```

```
#envファイル
#dotenv-railsを入れた

GOOGLE_APPLICATION_CREDENTIALS = config/gcpのページからダウンロードしたjsonファイル.json
```

これで一応Dockerのローカル環境では動く

#②herokuでの環境変数の扱い方について
ここで一つ疑問。
「あれ、環境変数がjsonファイルの時herokuでどうすんだ？」
以下を参考にした（全然日本語の情報出てこなかった）

ためになった記事①

https://stackoverflow.com/questions/47446480/how-to-use-google-api-credentials-json-on-heroku/56818296#56818296

ためになった記事②

https://dev.to/sylviapap/setting-heroku-config-vars-with-google-cloud-json-file-on-rails-4dnf

要約すると
①まずbuildpackをセットする必要があるわけだが、**これではなく**

https://github.com/elishaterada/heroku-google-application-credentials-buildpack

**こちら**を使うこと

https://github.com/gerywahyunugraha/heroku-google-application-credentials-buildpack

```
$ heroku buildpacks:add https://github.com/gerywahyunugraha/heroku-google-application-credentials-buildpack
```
②buildpackが実行される順番も気をつけること。
heroku/rubyよりも先に実行することが重要
![スクリーンショット 2021-11-10 17.40.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427079/15e51f74-53fe-2155-1bfe-1dec55ca064a.png)

> Note that the --index 1 and the order here are important. Heroku docs re: multiple buildpacks: "The buildpack for the primary language of your app should be the last buildpack added."(一部抜粋)

そうすればこのように設定することができる
![スクリーンショット 2021-11-10 17.44.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427079/1c252b37-f208-83d0-0a97-87bb9fe5eee4.png)