Herokuで、Rails＋carrierwave/fogを使ってAWS S3にファイルをアップロードする

#はじめに
HerokuでRailsサイトを作る際、別途用意しなければいけないのがストレージ。
Herokuをそのまま利用すると、時間が経つと消えてしまいます。
その対応策として、AWS S3を利用する際の設定方法をサンプルプロジェクトを作って、手順まとめておきます。

# 環境
Ruby 2.5.3
Rails 5.2.2
AWS S3の設定は完了済み

# プロジェクトの作成
```terminal
rails new sample_asws3
```
プロジェクトが作成できたら、Gemfileを修正します

◆修正

```ruby
gem 'sqlite3', '~> 1.3.6'
```
※sqlite3の問題があるので、一緒に修正

◆追加

```ruby
gem "carrierwave"
gem "fog-aws"
```

# アップロード用のモデル作成
サンプルなので簡単なモデルのみ

```terminal
rails g scaffold Item name:string image:string
```

```terminal
rake db:create
rake db:migrate
```

「[http://localhost:3000/items](http://localhost:3000/items)」にアクセスして、画面が表示されればひとまずOK！

<img width="236" alt="スクリーンショット 2019-03-16 13.10.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/118481/ab2b8862-619d-88af-dcbc-02194f3f9187.png" >

# CarrierWaveの設定
Uploaderクラスを追加します。名前は好きにつけてください。
※今回は、「Images」としました。

```terminal
rails generate uploader Images
```

設定は、デフォルトでいきますが、
storageの設定だけは、「:file」から「:fog」に変更

```ruby
class ImagesUploader < CarrierWave::Uploader::Base
  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  # include CarrierWave::MiniMagick

  # Choose what kind of storage to use for this uploader:
  #storage :file
  storage :fog
```

読み込めるようにapploication.rbに以下を追加

```ruby:config/application.rb
config.autoload_paths += Dir[Rails.root.join('app', 'uploaders')]
```

モデルの関連づけ

```ruby:app/models/item.rb
class Item < ApplicationRecord
  mount_uploader :image, ImagesUploader
end
```

scaffoldで作られた「image」用のフォームは、
「form.text_field」になっているので、「form.file_field」に変更

```erb:app/views/items/_form.html.erb
  <div class="field">
    <%= form.label :image %>
    <%= form.file_field :image %>
  </div>
```

<img width="247" alt="スクリーンショット 2019-03-16 13.36.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/118481/f2785684-9ad3-bef4-e1f6-3bc2eed89320.png">

# CarrierWaveの設定ファイル
新しく設定ファイルを作成します。

```ruby:config/initializers/carrierwave.rb
CarrierWave.configure do |config|
  config.fog_provider = 'fog/aws'
  config.fog_directory = ENV['AWS_S3_BUCKET']
  config.fog_credentials = {
    provider:              'AWS',
    aws_access_key_id:     ENV['AWS_S3_ACCESS_KEY_ID'],
    aws_secret_access_key: ENV['AWS_S3_SECRET_ACCESS_KEY'],
    region:                ENV['AWS_S3_REGION'],
  }
  config.fog_public     = false                                                 # optional, defaults to true
  config.fog_attributes = { cache_control: "public, max-age=#{365.days.to_i}" } # optional, defaults to {}
end
```
キー情報など、重要な項目については、必ず環境変数を使うようにしましょう！！

|キー|説明|
|:-----------------|:------------------|
|AWS_S3_ACCESS_KEY_ID|アクセスキー|
|AWS_S3_SECRET_ACCESS_KEY|シークレットキー|
|AWS_S3_REGION|転送先のリージョン（us-east-1など）|
|AWS_S3_BUCKET|転送先のバケット名|

# 動作確認
ファイルを選択して、登録してみます。
<img width="283" alt="スクリーンショット 2019-03-16 13.38.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/118481/a23f40e5-c33c-d757-8476-3759b00f0607.png">

表示部分を変更していないので、URLが表示されますが、アップロード部分はこれで完成です。

![スクリーンショット 2019-03-16 13.39.44.png](https://qiita-image-store.s3.amazonaws.com/0/118481/64434445-1c00-a646-f446-57d86cffa6d1.png)

画像を表示するために、ビューを変更

```erb:app/views/items/show.html.erb
<p>
  <strong>Image:</strong>
  <%= image_tag(@item.image.to_s) %>
</p>
```

と変更すると、画像が表示されます。

<img width="516" alt="スクリーンショット 2019-03-16 13.45.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/118481/cb095dcd-ca91-6db7-4517-d0f1f9e87350.png">

以上、ありがとうございました。
ソース一式、GitHubにあげておきました。よかったらどうぞ。
　https://github.com/newburu/SampleAwss3