【AWS】Railsで本番環境のみS3へ画像アップロードする分岐文【S3】

##開発環境

- Rails 5.2.1
- ruby 2.5.1
- AWS(EC2)
- Web Server Nginx
- Application Server Unicorn
- capistrano 3.11.1
- carrierwave
- fog-aws

##前提
AWSの設定やcapistranoを使用した自動デプロイが成功している段階
バケット作成、バケットポリシーなどS3の準備はできている状態。


##修正するファイル

deploy.rb（必要であれば）
image_uploader.rb
carrierwave.rb

###①deploy.rb
Capistranoを使用した自動デプロイについての設定ファイルを確認。
環境変数については明示的に呼び出しをする必要がある場合があるので、環境変数を使用する場合は要確認。
restartについては、今回学びがあったため、併せて記載しています。

```deploy.rb

#Capistranoのバージョンを固定
lock "~> 3.11.1"
set :application, .....
#~~~~中略~~~~~

#secrets.ymlではリリースバージョン間でシンボリックリンクにして共有
#credentials.yml.encではmasterkeyにする（今回）
set :linked_files, %w{config/master.key}

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do

 task :restart do
   invoke 'unicorn:restart'
 end
# restartだとキャッシュが残るので下記の書き方でも良い
# task :restart do
#   invoke 'unicorn:stop'
#   invoke 'unicorn:start'
# end

 desc 'upload master.key'
 task :upload do
   on roles(:app) do |host|
     if test "[ ! -d #{shared_path}/config ]"
       execute "mkdir -p #{shared_path}/config"
     end
     upload!('config/master.key', "#{shared_path}/config/master.key")
   end
 end
 before :starting, 'deploy:upload'
 after :finishing, 'deploy:cleanup'
end

# 必要に応じて/環境変数をcapistranoでの自動デプロイで利用
set :default_env, {
  rbenv_root: "/usr/local/rbenv",
  path: "/usr/local/rbenv/shims:/usr/local/rbenv/bin:$PATH",
  AWS_ACCESS_KEY_ID: ENV["AWS_ACCESS_KEY_ID"],
  AWS_SECRET_ACCESS_KEY: ENV["AWS_SECRET_ACCESS_KEY"]
}

```

###②image_uploader.rb

CarrierWave導入時に作成するはずのファイル。
初期値にコメントアウトで入っているstorageの記述を修正。
保存先`file`であればpublic下に`fog`であればS3に保存される。
今回は、本番環境の画像投稿のみ、バケットへ保存します。

```uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
#~~~~~前略~~~~~

  # 画像リサイズ/mini_magickなど入れていればデフォルトのコメントアウト外して記載
  include CarrierWave::MiniMagick
  process resize_to_fit: [300, 300]

  # 環境ごとに保存先変更/デフォルトではstorage :fileがコメントアウトで入っている
  if Rails.env.development?
    storage :file
  elsif Rails.env.test?
    storage :file
  else
    storage :fog
  end

  # ちょっとリファクタリング
  if Rails.env.development? || Rails.env.test? 
    storage :file
  else
    storage :fog
  end

#~~~~~後略~~~~~
end
```

###③carrierwave.rb

ない場合は**config/initializers直下**に`carrierwave.rb`を作成。
取得コードは、環境変数の設定に合わせて記述する必要があるので注意。
(rails5.2以前の環境では`credentials`ではなく`secret`に変更してください)

```config/initializers/carrierwave.rb

# CarrierWaveの設定呼び出し
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

# 保存先の分岐
CarrierWave.configure do |config|
  if Rails.env.production? # 本番環境:AWS使用
    config.storage = :fog
    config.fog_provider = 'fog/aws'
    config.fog_credentials = {
      provider: 'AWS',
      aws_access_key_id: Rails.application.credentials.aws[:access_key_id],
      aws_secret_access_key: Rails.application.credentials.aws[:secret_access_key],
      region: 'your_region' # 東京はap-northeast-1
    }
    config.fog_directory  = 'your-bucket-name' #S3のバケット名
    config.asset_host = 'https://s3-your_region.amazonaws.com/your_bucket_name'
  else
    config.storage :file # 開発環境:public/uploades下に保存
    config.enable_processing = false if Rails.env.test? #test:処理をスキップ
  end  
end
```
上記で呼び出せる`credentials.yml.enc`の書き方

```ruby:credentials.yml.enc

 aws:
   access_key_id: １２３hogehoge
   secret_access_key: ４５６hogehoge
```



##おまけ
環境変数やシークレットキーを設定したあとは、コンソールで取得できるか確認してからファイルへ書き込むと安心です。

`credentials.yml.enc`に書き込んだ時

```irb
$ rails c
irb(main):001:0> Rails.application.credentials.aws[:access_key_id]
=> １２３hogehoge
irb(main):002:0> exit
```

##最後に
勉強中につき、誤った記述があればお手数ですがお知らせください！