【Rails5】carrierwaveとfogでAWS S3に画像を複数アップロードする方法 #rails #画像アップロード version 3
      
          :追加された部分
      
      
          :削除された部分
      
      
    (差分が大きい場合、文字単位では表示しません)
    【Rails5】cariierwaveとfogでAWS S3に画像を複数アップロードする方法 #rails #画像アップロード
***
### 1. 画像アップロード用のカラムを作成するため「rails g migration add_images_column_to_テーブル名 images:string」をターミナルで実装する
```
$ rails g migration add_images_column_to_boards images:string  
```
※今回は複数の画像を一度にアップロードさせたいためカラム名は「images」とし、テーブル名は「boards」とする。
### 2. Gemfileに'carrierwave'と'fog-aws'を追加しbundle installを実行する
'carrierwave'を利用することで手軽に画像をアップロードすることができ、fogと連携することでクラウド上にあるAWS S3への画像をアップロードできるようにする。
```:Gemfile=53
gem 'carrierwave'
gem 'fog-aws'
```
```
$ bundle install
```
### 3. 画像アップロード用のクラスを作成すつために「rails g uploader アップローダー名」をターミナルで実装する
```
$ rails g uploader image
```
画像アップローダーとは以下のようなものである。

### 4. アップローダーを実装したいクラス(ここではboardクラス)に以下のコードを記述する
```:/app/models/board.rb=1
class Board < ApplicationRecord
  mount_uploaders :images, ImgUploader
  serialize :images, JSON //複数の画像をアップロードをする場合は左の1文が必要である 
  belongs_to :user
end
```
serialize「シリアル化」とは複数の並列データを直列化して送信することであり、JSONとはJavaScript Object Notationの略でデータフォーマットの一種である。{}波括弧で括りその中にデータが入る形式であり以下のようなものになる。
```
{
    "user": "太郎",
    "age": 20,
    "gender": "男"
}
```
### 5. ストロングパラメーターに「images」カラムを追加する
* 複数の画像をアップロードする場合はデータをJSON形式で保存する必要があるため、ストロングパラメーターには{images: []}と書く。
```:/controllers/boards_controller.rb=1
class BoardsController < ApplicationController
before_action :authenticate_user!, :only => [:new, :create]
    
    def new
    @board = Board.new
    end
    def index
    @boards = Board.all
    end
    
    def create
      @board = Board.new(board_params)
      @board.user_id=current_user.id
      if @board.save
          flash[:notice] = "掲示板に新規投稿されました"
          redirect_to boards_path
      else 
          flash[:notice] = "掲示板に新規投稿できませんでした"
          render :new
      end
    end
    def show
    @board = Board.find(params[:id])
    @user = User.find(@board.user_id)
    end
   
 private 
    def board_params
      params.require(:board).permit({images: []}, :title, :book_name, :author, :isbn_num, :category, :condition, :available_period, :remarks, :user_id).merge(:user_id => current_user.id)
    end
end
```
* 一枚の画像だけをアップロードしたい場合、カラム名は「:image」となる。その場合はストロングパラメーターに以下のような実装をする。
```
   def board_params
      params.require(:board).permit(:image, :title,.......
```
### 6. アップローダーを実装したいviewと、画像を表示したいviewを編集する
```:/app/views/boards/new.html.erb=20
<%= f.label :images, "画像:" %>
<%= f.file_field :images, multiple: true, accept: "image/*" %>
```
「multiple: true」とすることで複数の画像がアップロードできる。「accept: "image/*"」とすることで画像ファイルしかアップロードできないようにする。
```:/app/views/boards/show.html.erb=5
画像:
<% @board.images.each do |image| %>
 <%= image_tag image, class: "board-images" %>
<% end %>
```
```:/app/stylesheets/styles.scss=1
.board-images {
  display: inline-block;
  width: 200px;
  height: 200px;
}
```
***
### 7. image_uploader.rbにある「storage :fog」をコメントアウトする
```:/uploaders/image_uploader.rb=1
class ImgUploader < 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
  # 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
  # Provide a default URL as a default if there hasn't been a file uploaded:
  # def default_url(*args)
  #   # For Rails 3.1+ asset pipeline compatibility:
  #   # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
  #
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  # end
  # Process files as they are uploaded:
  # process scale: [200, 300]
  #
  # def scale(width, height)
  #   # do something
  # end
  # Create different versions of your uploaded files:
  # version :thumb do
  #   process resize_to_fit: [50, 50]
  # 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
  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  # def filename
  #   "something.jpg" if original_filename
  # end
end
```
### 8. initializersのファイル直下にcarrierwave.rbを自分で作成し以下をコピペする
config.fog_directory には自分のbucket名を入れる。
```:/initializers/carrierwave.rb=1
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'
 
CarrierWave.configure do |config|
#   if Rails.env.production?
    config.storage :fog
    config.fog_provider = 'fog/aws'
    config.fog_directory  = '_bucket' #自分のbucketの名前を入れる
    config.fog_credentials = {
      provider: 'AWS',
      aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
      aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
      region: 'ap-northeast-1', #日本の場合はregionはこのように設定
      path_style: true
    }
#   else
#     config.storage :file
#     config.enable_processing = false if Rails.env.test?
#   end
end
 
CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
```
### 9. AWS S3へのアクセス環境変数設定をするため以下をターミナルで実行する
```
$ export AWS_ACCESS_KEY_ID= 自分のbucketのACCESS_KEY_IDを入れる
$ export AWS_SECRET_ACCESS_KEY= 自分のbucketのSECRET_ACCESS_KEYを入れる
```
※以上の実装はAWSS3にbucketを作成してからでないとできないので注意。
***
不明点、修正点ございましたらコメントよろしくお願いします。
      
1. 画像アップロード用のカラムを作成するため「rails g migration add_images_column_to_テーブル名 images:string」をターミナルで実装する
$ rails g migration add_images_column_to_boards images:string  
※今回は複数の画像を一度にアップロードさせたいためカラム名は「images」とし、テーブル名は「boards」とする。
2. Gemfileに'carrierwave'と'fog-aws'を追加しbundle installを実行する
'carrierwave'を利用することで手軽に画像をアップロードすることができ、fogと連携することでクラウド上にあるAWS S3への画像をアップロードできるようにする。
gem 'carrierwave'
gem 'fog-aws'
$ bundle install
3. 画像アップロード用のクラスを作成すつために「rails g uploader アップローダー名」をターミナルで実装する
$ rails g uploader image
画像アップローダーとは以下のようなものである。

4. アップローダーを実装したいクラス(ここではboardクラス)に以下のコードを記述する
class Board < ApplicationRecord
  mount_uploaders :images, ImgUploader
  serialize :images, JSON //複数の画像をアップロードをする場合は左の1文が必要である 
  belongs_to :user
end
serialize「シリアル化」とは複数の並列データを直列化して送信することであり、JSONとはJavaScript Object Notationの略でデータフォーマットの一種である。{}波括弧で括りその中にデータが入る形式であり以下のようなものになる。
{
    "user": "太郎",
    "age": 20,
    "gender": "男"
}
5. ストロングパラメーターに「images」カラムを追加する
- 複数の画像をアップロードする場合はデータをJSON形式で保存する必要があるため、ストロングパラメーターには{images: []}と書く。
class BoardsController < ApplicationController
before_action :authenticate_user!, :only => [:new, :create]
    
    def new
    @board = Board.new
    end
    def index
    @boards = Board.all
    end
    
    def create
      @board = Board.new(board_params)
      @board.user_id=current_user.id
      if @board.save
          flash[:notice] = "掲示板に新規投稿されました"
          redirect_to boards_path
      else 
          flash[:notice] = "掲示板に新規投稿できませんでした"
          render :new
      end
    end
    def show
    @board = Board.find(params[:id])
    @user = User.find(@board.user_id)
    end
   
 private 
    def board_params
      params.require(:board).permit({images: []}, :title, :book_name, :author, :isbn_num, :category, :condition, :available_period, :remarks, :user_id).merge(:user_id => current_user.id)
    end
end
- 一枚の画像だけをアップロードしたい場合、カラム名は「:image」となる。その場合はストロングパラメーターに以下のような実装をする。
   def board_params
      params.require(:board).permit(:image, :title,.......
6. アップローダーを実装したいviewと、画像を表示したいviewを編集する
<%= f.label :images, "画像:" %>
<%= f.file_field :images, multiple: true, accept: "image/*" %>
「multiple: true」とすることで複数の画像がアップロードできる。「accept: "image/*"」とすることで画像ファイルしかアップロードできないようにする。
画像:
<% @board.images.each do |image| %>
 <%= image_tag image, class: "board-images" %>
<% end %>
.board-images {
  display: inline-block;
  width: 200px;
  height: 200px;
}
7. image_uploader.rbにある「storage :fog」をコメントアウトする
class ImgUploader < 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
  # 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
  # Provide a default URL as a default if there hasn't been a file uploaded:
  # def default_url(*args)
  #   # For Rails 3.1+ asset pipeline compatibility:
  #   # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
  #
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  # end
  # Process files as they are uploaded:
  # process scale: [200, 300]
  #
  # def scale(width, height)
  #   # do something
  # end
  # Create different versions of your uploaded files:
  # version :thumb do
  #   process resize_to_fit: [50, 50]
  # 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
  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  # def filename
  #   "something.jpg" if original_filename
  # end
end
8. initializersのファイル直下にcarrierwave.rbを自分で作成し以下をコピペする
config.fog_directory には自分のbucket名を入れる。
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'
 
CarrierWave.configure do |config|
#   if Rails.env.production?
    config.storage :fog
    config.fog_provider = 'fog/aws'
    config.fog_directory  = '_bucket' #自分のbucketの名前を入れる
    config.fog_credentials = {
      provider: 'AWS',
      aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
      aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
      region: 'ap-northeast-1', #日本の場合はregionはこのように設定
      path_style: true
    }
#   else
#     config.storage :file
#     config.enable_processing = false if Rails.env.test?
#   end
end
 
CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
9. AWS S3へのアクセス環境変数設定をするため以下をターミナルで実行する
$ export AWS_ACCESS_KEY_ID= 自分のbucketのACCESS_KEY_IDを入れる
$ export AWS_SECRET_ACCESS_KEY= 自分のbucketのSECRET_ACCESS_KEYを入れる
※以上の実装はAWSS3にbucketを作成してからでないとできないので注意。
不明点、修正点ございましたらコメントよろしくお願いします。
