【AWS】herokuでS3に画像をアップロード(Rails)

Railsチュートリアル第13章でheroku → S3デプロイまで苦戦したためご参考先とともにメモ。
本記事に表現・内容の誤り等あればご指摘頂けると幸いです(^_^;)

# エラー
・heroku→S3へ画像投稿ができない（マイクロポストテキストはできる）
・（投稿成功後）画像のリサイズで小さくならない


※画像がheroku内かS3どうかは、マイクロポストでアップした画像を右クリックし、
`画像アドレスをコピー`でリンク先が「 **~s3.amazonaws~** 」になっていればok。


# 対処・間違っていたこと等
・IAM→S3作成ユーザー(≠これまでのEC2作業ユーザ)
・バケットポリシー変更（✔︎新ポリシーのみブロック≠全ブロック）
・uploaderのlimitサイズ変更で確認(そもそも投稿元のサイズが縦長で大きく見えただけだった)

※ 投稿後にS3を確認すると、`uploads`フォルダが作成されている

##＜ 流れ ＞

1. S3（バケット）作成
2. EC2作業ユーザとは別に新規IAMユーザ作成(Fullアクセス権限付与、バケットからAccessキー & Secretキー取得のため)
3. S3へ行きアクセス権限からパプリックアクセスを一時的に解除 & ポリシー付与
4. 再度パブリックアクセス(新規条件のブロックに✔︎)
5. herokuでS3アクセスキー等追加


### S3パブリック設定

---
パブリックアクセスをすべてブロック
オフ

新しいアクセスコントロールリスト (ACL) を介して許可されたバケットとオブジェクトへのパブリックアクセスをブロックする
オフ

任意のアクセスコントロールリスト (ACL) を介して許可されたバケットとオブジェクトへのパブリックアクセスをブロックする
オフ

新規のパブリックバケットポリシーまたはアクセスポイントポリシーを介して付与されたバケットとオブジェクトへのパブリックアクセスをブロックする
オン

任意のパブリックバケットポリシーまたはアクセスポイントポリシーを介したバケットとオブジェクトへのパブリックアクセスとクロスアカウントアクセスをブロックする
オフ

---

### ポリシー

既にEC2で開発している場合、S3用で作った新規ユーザではIDが出るわけではないので注意（元のものでok）

※ 入力に `""` や `「」`は不要

```

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "statement1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::AWSユーザのID(12桁の数字):user/新規に作ったS3用ユーザ名"
            },
            "Action": "*",
            "Resource": "arn:aws:s3:::バケット名/*"
        }
    ]
}
```

##各種作成設定ファイル 

carrier_wave

```config/initializers/carrier_wave.rb

if Rails.env.production?
  CarrierWave.configure do |config|
    config.fog_provider = 'fog/aws'  #=> 追加
    config.fog_credentials = {
      # Amazon S3用の設定
      :provider              => 'AWS',
      :region                => ENV['S3_REGION'],     # 例（東京）: 'ap-northeast-1'
      :aws_access_key_id     => ENV['S3_ACCESS_KEY'],
      :aws_secret_access_key => ENV['S3_SECRET_KEY']
    }
    config.fog_directory     =  ENV['S3_BUCKET']
    # キャッシュの保存期間
    config.fog_attributes = { 'Cache-Control' => "max-age=#{365.day.to_i}" }
  end
  # 日本語ファイル名の設定
  CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/ 
end
```
　
`store_dir`はデフォルトの保存先(S3で確認すると出てくる)

```ruby:app/uploaders/picture_uploader.rb
class PictureUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
  process resize_to_limit: [300, 300]

  # Choose what kind of storage to use for this uploader:
  if Rails.env.production?
    storage :fog
  else
    storage :file #=> ローカルストレージ
  end
  # storage :fog

  # アップロードファイルの保存先ディレクトリは上書き可能
  # 下記はデフォルトの保存先(S3で確認すると出てくる)
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  # Add a white list of extensions which are allowed to be uploaded.
  # For images you might use something like this:
  def extension_whitelist
    %w(jpg jpeg gif png)
  end
end
```
　
Gemfile

```ruby:Gemfile

group :production do
  gem 'pg', '0.20.0'
  gem 'fog-aws'#=> fogから変更
end
```
## その他

heroku関係

※ `""`は無くてもok(heroku configで確認できる)

```
$ heroku config #=> 状態確認
$ heroku logs #=> ログ確認
$ heroku config:set S3_ACCESS_KEY="CSVダウンロードしたAccessキー"
$ heroku config:set S3_SECRET_KEY="CSVダウンロードしたSecretキー"
$ heroku config:set S3_BUCKET_KEY="S3のBucketの名前"
$ heroku config:set S3_REGION="ap-northeast-1"
```

# ご参考先
[【公式】AWS Config 開発者ガイド](https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/config-dg.pdf)
[S3のバケットポリシーでハマったので、S3へのアクセスを許可するPrincipalの設定を整理する](https://dev.classmethod.jp/cloud/aws/summarize-principal-settings-in-s3-bucket-policy/)
[【Rails】S3へ『CarrierWave+fog』を使って画像アップロードする方法](http://vdeep.net/rubyonrails-carrierwave-s3)
[HerokuでS3に画像をアップロードした話[Rails][S3][CarrierWave][fog]](https://qiita.com/tanutanu/items/07e9327c1091280c3f13)
[Rails5 heroku にS3を使ってアップロードしたときに発生するエラー 403 Access denied の対処法](https://qiita.com/mugayoshi/items/c45c9bfcf8829b5f8e9a)