【Rails】Herokuで画像を投稿できるようにする方法（ActiveStorage + Amazon S3）

今回は、Rails 5.2で追加されたActiveStorageを使ってHerokuで画像をアップロードできるようにしたいと思います。

内容

- ActiveStorageって何?
- 最初に、Amazon S3でやること
- 次に、Railsでやること
- 最後に、Herokuでやること


# ActiveStorageって何?
Amazon S3, GCS, AzureStorageなどのクラウドストレージに画像などのファイルをアップロードできるRailsの機能。
以前使われていた、CarrierWaveやPaperclipなどgemの代わりになる。

[Active Storage の概要 | Railsガイド](https://railsguides.jp/active_storage_overview.html)を参照

## Rails バージョンの確認

```shell
$ rails -v
Rails 5.2.0
```

Active Storageを使うにはRails 5.2が必要です。
Rails 5.2 未満の場合は[アップグレード](https://railsguides.jp/upgrading_ruby_on_rails.html)してください。

## :beginner: ActiveStorageの使い方
わからない人のために載せておきます。
ここでは手短に、Userのアバター画像を管理する例を載せる。

```shell
$ rails active_storage:install
$ rails db:migrate
```
```ruby:user.rb
class User < ApplicationRecord
  has_one_attached :avatar
end
```
```erb:edit.html.erb
<%= form.file_field :avatar %>
```
```ruby:users_controller.rb
def create
  @user.create(...., avatar: params[:avatar])
end
```
```erb:show.html.erb
<% if @user.avatar.attached? %>
  <%= image_tag @user.avatar %>
<% end %>
```

詳しくは[ActiveStorageの使い方まとめ](https://qiita.com/hmmrjn/items/7cc5e5348755c517458a)をどうぞ。



# 手順
## 最初に、Amazon S3でやること
### 画像をアップロードする場所を用意
2. AWSコンソール → サービス → ストレージ → S3
3. 「**バケットを作成する**」<br/>バケット = 画像などのファイルをアップロードできるところ

|項目|入力・選択|
|---|---|
|パケット名|適当 ex: my-rails-app-first-bucket|
|リージョン|:flag_jp:　東京|
|パブリックアクセス許可を管理する|**このバケットに読み取りアクセス権限をする**|
|上記以外|全部デフォルトのままでok|


### アクセスキーを作る
- AWSコンソール → サービス → セキュリティ → IAM
- 「**個々の IAM ユーザーの作成**」 → 「ユーザーの管理」 → 「ユーザーを追加」

|項目|入力・選択|
|---|---|
|ユーザー名|適当 ex: TaroTanaka |
|アクセスの種類|プログラムによるアクセス|

- 「既存のポリシーを直接アタッチ」 → 「S3」で検索 → 「**AmazonS3FullAccess**」を選択 → 「次へ」 → 「ユーザーの作成」
- 表示された「**アクセスキー ID**」と「**シークレットアクセスキー**」 をメモ帳などにコピペして保管する。

## 次に、Railsでやること

### 必要なGemのインストール

```ruby:Gemfile
gem "aws-sdk-s3", require: false #追記
```

```shell
$ bundle install
```

### S3へのアクセスキーを入力

```shell
$ EDITOR=vim rails credentials:edit
```

ここで`ActiveSupport::MessageEncryptor::InvalidMessage`と言われたら `credentials.yml.enc`を削除してからもう一度実行してください。 (@kenzoukenzou104809さんありがとうございます。[参考記事](https://qiita.com/kenzoukenzou104809/items/67ac14d1c89f7c5641c1) )

```yml:
# コメントアウトを解除する
aws:
 access_key_id: #ここに自分のアクセスキーIDをコピペ
 secret_access_key: #ここに自分のシークレットアクセスキーをコピペ
```
:bulb: `i`キーで編集開始、`esc`で編集終了 、 `ZZ`で保存して終了

後から入力を確認したいときは

```shell
$ rails credentials:show
```
:information_source: 入力内容は config/master.key を使って暗号化され、 config/credentials.yml.enc が生成されます。これは中身が暗号化されているのでGitで管理しても大丈夫です。


### Herokuでの画像の保存先をAmazon S3に変更

```yml:config/storage.yml
amazon:
  # 以下3行はそのまま
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  # 以下２行は変える
  region: ap-northeast-1 #東京
  bucket: my-rails-app-first-bucket #自分で作成したS3のバケットの名前

```

```ruby:config/environments/production.rb
config.active_storage.service = :amazon #amazonに変更
```

## 最後に、Herokuでやること

```shell
$ heroku buildpacks:add -i 1 https://github.com/heroku/heroku-buildpack-activestorage-preview
$ git add .
$ git commit -m "added s3 to production"
$ git push heroku master
```

Railsプロジェックトのマスターキー(config/master.keyの中身)をコピーします

```shell
$ heroku config:set RAILS_MASTER_KEY=マスターキーをここに貼り付け
$ heroku run rails db:migrate
$ heroku open
```

これで以上です。:tada: 
お疲れ様です〜:coffee:



# 参考文献
[Rails 5.2 credentials – cedarcode – Medium](https://medium.com/cedarcode/rails-5-2-credentials-9b3324851336)
[Active Storage Overview - Ruby on Rails Guides](http://guides.rubyonrails.org/active_storage_overview.html)
[Ruby on rails Store Images on Amazon S3 Part 1 016](https://youtu.be/7V748CztbjA)
[Ruby on rails Store Images on Amazon S3 Part 2 017](https://youtu.be/v9inROFHNWA)
[herokuでCredentialsとActive Storageを使う](https://qiita.com/hirorock/items/4ec6996c29838ad63233)