Railsで画像をリサイズしてS3にアップロードする方法（CarrierWave＆Fog＆RMagick）

## 画像をリサイズしてS3にアップロード

今回は、画像をアップロードの定番である　[「CarrierWave」](https://github.com/carrierwaveuploader/carrierwave) と S3にあげるために[「fog」](https://github.com/fog/fog)、そしてリサイズするために [「Rmagick」](https://github.com/rmagick/rmagick)を使う方法を備忘録として。


Userモデルに画像をアップロード。まずは、必要なGemをインストールする。

```ruby:Gemfile
source 'https://rubygems.org'

gem 'carrierwave'
gem 'rmagick'
gem 'fog'
```
bundle installする。

```
$ bundle install --path vendor/bundle
```

ImageMagick がないとエラーが出たりするので。

```
$ yum -y install libcurl-devel
$ yum -y install -y libxml2 libxml2-devel libxslt libxslt-devel
$ yum -y install ImageMagick ImageMagick-devel
```
などなど。

## モデルを作成

Userモデルをつくって、userの画像をDBに保存できるようにする。

```
$ bundle exec rails generate model user name:string image:string
```

```
$ bundle exec rake db:migrate

      invoke  active_record
      create    db/migrate/20141211093435_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
```

```ruby:app/models/user.rb
class User < ActiveRecord::Base
 
  mount_uploader :image, ImageUploader
....
end
```

User テーブルに画像を保存するために、 mount_uploader を追記する。

```
$ bundle exec rails g uploader image

    create  app/uploaders/image_uploader.rb
```

## Controllerを作成

続いて、homeコントローラーを作成する。

```
$ bundle exec rails g controller home index uploader

      create  app/controllers/home_controller.rb
       route  get 'home/uploader'
       route  get 'home/index'
      invoke  erb
      create    app/views/home
      create    app/views/home/index.html.erb
      create    app/views/home/uploader.html.erb
      invoke  test_unit
      create    test/controllers/home_controller_test.rb
      invoke  helper
      create    app/helpers/home_helper.rb
      invoke    test_unit
      create      test/helpers/home_helper_test.rb
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/home.js.coffee
      invoke    scss
      create      app/assets/stylesheets/home.css.scss
```


Rails4以降は strong params を指定

```ruby:app/controllers/home_controller.rb

class HomeController < ApplicationController
  def index
  end

  def uploader
    begin
      user = User.new
      user.image = params['image']
      user.name  = params['name']
      user.save!
    rescue => e1
      logger.error('user image save error')
      logger.error(e1.message)
    end
  end

private
  def user_params
    params.require(:user).permit(:name, :image)
  end

end

```

config/initializers/carrierwave.rbで storage を設定するので下記ではコメントアウト。

```ruby:app/uploaders/image_uploader.rb

# encoding: utf-8

class ImageUploader < CarrierWave::Uploader::Base

 # リサイズや画像の形式を変えるため
  include CarrierWave::RMagick

  # 画像の形式をJPGに変換
  process :convert => 'jpg'

  # 画像のサイズを変更
  process :resize_to_limit => [500, 500]

  # Include RMagick or MiniMagick support:
  # include CarrierWave::MiniMagick

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

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_white_list
    %w(jpg jpeg gif png)
  end

...
end

```

※リサイズについては、[こちら](http://noodles-mtb.hatenablog.com/entry/2013/07/08/151316) のサイトが、わかりやすくまとめてくれています。

## Routing

```ruby:config/routes.rb
Rails.application.routes.draw do

  root "home#index", as: :root
  post 'home/uploader', to: "home#uploader", :as => :uploader

....
end

```

これで home/uploader に画像をポストすると、Userテーブルに画像が保存される。

## s3にアップロードする設定

[AWSのS3](https://console.aws.amazon.com/s3/home)から「CreateBucket」をおして、Bucketを作成する。

![createbucket.png](https://qiita-image-store.s3.amazonaws.com/0/36485/ec8a4899-806f-4d6f-5589-030d874216c8.png)

下記で必要な「your_access_key_id」と「your_secret_access_key」の部分は「securitycredentials」をクリックして確認してください。


![securitycredentials.png](https://qiita-image-store.s3.amazonaws.com/0/36485/7e1d03a5-986c-a83b-cfef-ed9945779988.png)


ここではproductionであれば、s3に保存、そうでなければローカルに保存する仕様。


```ruby:config/initializers/carrierwave.rb
if Rails.env.production?
  CarrierWave.configure do |config|
    config.storage = :fog
    config.fog_credentials = {
        :provider              => 'AWS',
        :aws_access_key_id     => 'your_access_key_id',
        :aws_secret_access_key => 'your_secret_access_key',
        :region                => 'ap-northeast-1',
    }

    config.fog_directory = 'your_s3_bucket_name'
    config.fog_public = true
    
  end
else
  CarrierWave.configure do |config|
    config.storage = :file
  end
end
```

「your_s3_bucket_name」に、上記でつくったBucket の名前を当てはめます。

Backetを作成する際に Tokyo を選んだ場合 region は ap-northeast-1 にします。

## regionのリスト

* us-east-1 : バージニア（北部） 
* us-west-2 : オレゴン
* us-west-1 : カリフォルニア（北部）
* eu-west-1 : アイルランド
* eu-central-1：フランクフルト
* ap-sourtheast-1 :シンガポール
* ap-northeast-1 :東京
* ap-sourtheast-2 : シドニー
* sa-east-1 : サンパウロ


画像をリサイズしてS3にアップロードする方法でした。