Heroku + CarrierWave + S3で画像投稿する方法


## 1. 作業の流れ

まず最初にS3のバケットを作成します。
最初に行う理由は後からローカルで開発しているRailsのアプリケーションにS3で決めた設定を
入力するからです。

S3のバケットの作り方ですが、参考資料をみて行うと問題なく進みます。

流れとしては、

1. まず`IAM`でユーザーを作成する。（ここで作成したアクセスキーIDとシークレットアクセスキーをcarrierwaveの設定で使用する。）  
2. S3のバケットを作成する。(画像を保存する箱を作る)
3. gemの`fog-aws`を導入して設定ファイルなどを作成する。

の様に進んでいきます。

## 1. IAMユーザーの作成
まずAWSにアカウント登録すると`root`というめちゃくちゃ強い権限を持ったアカウントが作成される。
公式ではセキュリティ上の観点から`root`ユーザーを日常的に使用するのは推奨していないので`IAM`というサービスを使用して、別の権限のユーザーを日常使い様に作成します。

つまり、自分のAWSアカウントだとしてももう一人権限が小さいユーザーを作って管理するイメージです。※作成方法は最後に書いてあるリンクに記載されています。

## 2. S3のバケットを作成
画像を保存する箱を作成します。
参考資料ではrootユーザーのままでアクセスできると、書いていますがIAMユーザーでやってもできました。
ここの設定は、すごく丁寧に参考資料にまとめられていたので、そのまま使用すれば問題ないかと思います。


## 参考資料
上記2つの参考リンクです。ここの通りにやればできます。
[【Rails】CarrierWaveチュートリアル](https://pikawaka.com/rails/carrierwave)

## 3. fog-awsを導入したRailsの設定諸々

`fog-aws`は外部のストレージサービスを使用する時に簡単にしてくれるgemくらいの認識でOK


まず`fog-aws`をインストールする

`Gemfile`
```
gem 'fog-aws'
```

`bundle install`を実行して

次はどの環境で:fog(S3)を使用するのかをRails側に設定する。

`app/uploaders/image_uploader`

```ruby

  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  include CarrierWave::MiniMagick  <= ここのコメントアウトを外す。

  # Choose what kind of storage to use for this uploader:
  このIf文を追加することで、環境毎にどこに保存するかを指定している。
  この場合はproduction環境のみS3を使用する。

  if Rails.env.development?
    storage :file
  elsif Rails.env.test?
    storage :file
  else
    storage :fog
  end

  ....
```
次に、事前にAWSで作成したIAMユーザーの情報とS3の情報を設定する。
まず設定ファイルである`carrierwave.rb`を`config/initializers`いかに作成する。
この場所におけば、初期化に必要なものと判断されて、自動で読み込まれるので作成してしまって構いません。

```
touch config/initializers/carrierwave.rb
```

上記コマンドでファイルを作成して設定を記載します。

`config/initializers/carrierwave.rb`

```ruby
unless Rails.env.development? || Rails.env.test? <= プロダクション環境のみ動作する。
  require 'carrierwave/storage/abstract'
  require 'carrierwave/storage/file'
  require 'carrierwave/storage/fog'

  CarrierWave.configure do |config|
    config.storage :fog
    config.fog_provider = 'fog/aws'
    config.fog_directory = 'carrierwave-test-app' <=作成したS3のバケット名を記入
    config.fog_credentials = {
        provider: 'AWS',
        aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id), #最初にコピーしたIAMユーザーのaccess_key
        aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key), #最初にコピーしたIAMユーザーのaws_secret_access_key
        region: 'ap-northeast-1' <=作成したS3のリージョンを記入。
    }
  end
end
```
コメントを入れているところを細かく説明していくと

```ruby
unless Rails.env.development? || Rails.env.test? <= プロダクション環境のみ動作する。
```
ここはそのままです。

```ruby
config.fog_directory = 'carrierwave-test-app' <=作成したS3のバケット名を記入
```

最初に作成したS3のページに行って確認してみると良いです。
タイポがないか確認もしましょう。

```ruby
aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id), #最初にコピーしたIAMユーザーのaccess_key
aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key), #最初にコピーしたIAMユーザーのaws_secret_access_key
```

ここでは`credentials.yml.enc`にIAMユーザーの`access_key`と`aws_secret_access_key`を指定している。
理由はここに直接記入してしまうとgithubなどでファイルを共有できなくなってしまうので環境変数に入れて外からわからない様にしています。

今回は`credentials.yml.enc`を使用しましたが参考記事では`dotenv-rails`が使用されています。
要は外部からキーの中身を見えなくするという目的がある事を抑えておくと良いです。

■参考資料  
[【Rails】dotenv-railsの導入方法と使い方を理解して環境変数を管理しよう！](https://pikawaka.com/rails/dotenv-rails)

## production環境でテストする。

ここまで、設定し終わったらproduction環境でS3に画像がアップされているかテストしてみようと思います。

production環境の設定方法を現場Rails(p274〜)に記入されているのでそちらを参考にしてやってください。

最初にアセットプリコンパイル。

`ターミナル`
```
bin/rails assets:precompile
```

静的ファイル配信サーバを設定

`cofig/environments/production.rb`
```
config.public_file_server.enabled = ENV[:RAILS_SERVE_STATIC_FILES]
```
これを`true`にしたいので

`~/.bash_profile`
```
export RAILS_SERVE_STATIC_FILES = 1
```

とするとtrueになる。

production環境のデータベース作成

`rails db:create`ではデフォルトではdevelopmentとtestしかDBが作成されないので
production用も作成する。

postgresqlの場合
```
createuser -d -P アプリ名
パスワードを聞かれるので確認用も含めて2回記入して終了
```

`config/database.yml`に反映させる作業

`~/.bash_profile`
```
export App名_DATABASE_PASSWORD = 設定したパスワード
```

ここまでやるとproduction環境でサーバーを立ち上げてみましょう。

`ターミナル`

```
bin/rails s --environment=production
```
これでサーバーが立ち上がるはずです。この辺りは現場Railsを買って読むと、詳しく書いています。
[現場Rails](https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Ruby-Rails-5%E9%80%9F%E7%BF%92%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%E5%A4%A7%E5%A0%B4%E5%AF%A7%E5%AD%90/dp/4839962227)

ここで画像を投稿して正しく表示されれば設定が間違っていなければS3にもアップロードされているはずです。

長々と読んでいただきありがとうございます。
間違いなどありましたら、教えていただければありがたいです。

## その他

ここではあくまで、carrierwaveとS3の連携に対して話をしましたのでherokuなどの設定には触れていません。
下記に参考になる記事を載せておきますので役立ててください。

■Railsアプリのデプロイ  
[【初心者向け】railsアプリをherokuを使って確実にデプロイする方法【決定版】](https://qiita.com/kazukimatsumoto/items/a0daa7281a3948701c39)  
■master_keyのコピーの仕方(最後に乗ってる)  
[Herokuで画像を投稿できるようにする方法（ActiveStorage + Amazon S3）](https://qiita.com/hmmrjn/items/479c9e9ce82771f1b6d7)