Rails+CarrierWave+heroku環境でAWS S3へ画像をアップロードする

Rails+carrierwave+herokuを使用してAWS S3へ画像をアップロードする方法をまとめました。

# 前提条件

- carrierwaveの設定が完了しており、ローカルで画像のアップロードができているいること。
- AWS S3でユーザ登録とバケットの作成ができていること。

※AWS S3の設定は[Rails, Laravel(画像アップロード)向けAWS(IAM:ユーザ, S3:バケット)の設定](https://qiita.com/nobu0717/items/4425c02157bc5e88d7b6)を参考にしてください


# gem `fog-aws`のインストール

`fog-aws`は外部のストレージへのアップロードを可能にするgemです。

`Gemfile`へ以下のようにグローバルに追記してください。

```ruby
# 略

gem 'fog-aws'

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
```

追加したgemをインストールします。

```ruby
bundle install
```

carrierwaveで作成したxxx_uploader.rb(本稿では`image_uploader.rb`)を編集します。
以下のように`strage :file`を`storage :fog`へ変更してください。

```ruby
# storage :file
storage :fog

def store_dir
  "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
```

# carrierwaveの設定

`carrierwave`の設定ファイルを、`/config/initializers`直下に`carrierwave.rb`というファイル名で新規作成してください。
新規作成したら以下のように編集します。

```ruby
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  = 'AWSで作成したバケット名'
  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
    aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
    region: ENV['AWS_DEFAULT_REGION'],
    path_style: true
  }
  
end
```

# 環境変数の設定

## ローカル環境
環境変数の設定には`dotenv-rails`というgemを使用すると便利です。

`dotenv-rails`のインストールは、`Gemfile`のグローバルへ`gem 'dot-env'`を記載して`bundle install`を実行してください。

使用方法は、プロジェクト直下に.envファイルを作成し、以下のように編集しましょう。
***<font color=red>注：.envがリモートリポジトリへアップされないようにgit.ignorへ追加しましょう<font>***

```ruby
AWS_ACCESS_KEY_ID='AWSで作成したAccess key ID'
AWS_SECRET_ACCESS_KEY='AWSで作成したSecret access key'
AWS_DEFAULT_REGION='ap-northeast-1'
```

これでローカル環境での環境変数の設定は完了です。

## heroku環境

### ブラウザから設定
herokuの「ダッシュボード」->「対象アプリ」->「Setting」->「Reveal Config Vars」をクリックします。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/288694/aa753895-305e-d612-bbe2-7d3f36851049.png)


「Config Vars」の下部のテキストボックスへ以下の環境変数を設定します。
設定方法は、右のテキストボックスにキーを入力し、左に値を入力してから「Add」をクリックしてください。

|キー |値  |
---|---
|AWS_ACCESS_KEY_ID|AWSで作成したAccess key ID|
|AWS_SECRET_ACCESS_KEY|AWSで作成したSecret access key|
|AWS_DEFAULT_REGION|ap-northeast-1|

### コンソールで設定

```
# herokuへログイン
$heroku login

# 環境変数を設定
$heroku config:set AWS_ACCESS_KEY_ID="AWSで作成したAccess key ID"
$heroku config:set AWS_SECRET_ACCESS_KEY="AWSで作成したSecret access key"
$heroku config:set AWS_DEFAULT_REGION="ap-northeast-1"
```

これでheroku環境での環境変数の設定は完了です。

# 確認

実際に画像を投稿して画像がAWS S3にアップロードされているか確認しましょう。

例：
![2.png](https://qiita-image-store.s3.amazonaws.com/0/288694/e21f68ee-9e2f-336a-3317-42d9ab63f342.png)


アップロードされていれば成功です。

# Tips

### 開発環境と本番環境で画像のアップロード先を自動で切り替えるには

開発環境はローカルへ、本番環境はAWS S3へアップロードしたい場合、`image_uploader.rb`の`storage`をいちいち切り替えるのは面倒です。

そこで、carrierwave設定ファイルを以下のように編集することで、環境に応じて自動でアップロード先を切り替えることができます。

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

参考： [Railsでcarrierwaveを使ってAWS S3に画像をアップロードする手順を画像付きで説明する](https://qiita.com/junara/items/1899f23c091bcee3b058)