【Rails5】carrierwaveとfogでAWS S3に画像を複数アップロードする方法 #rails #画像アップロード version 2
:追加された部分
:削除された部分
(差分が大きい場合、文字単位では表示しません)
【Rails5】cariierwaveとfogでAWS S3に画像を複数アップロードする方法
![2019-11-09 (3)](https://mimemo.s3-ap-northeast-1.amazonaws.com/attachment/8ad4286e-b466-4289-bc3c-e87c9b8f0d89.png)
***
### 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
```
画像アップローダーとは以下のようなものである。
![07-17-2017-1500241058](https://mimemo.s3-ap-northeast-1.amazonaws.com/attachment/3deddc02-f39f-4c94-afcb-4d12fe38d10d.png)
### 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を入れる
$ 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'
53
54Gemfile$ 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
1
2
3
4
5/app/models/board.rbserialize「シリアル化」とは複数の並列データを直列化して送信することであり、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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34/controllers/boards_controller.rb- 一枚の画像だけをアップロードしたい場合、カラム名は「:image」となる。その場合はストロングパラメーターに以下のような実装をする。
def board_params
params.require(:board).permit(:image, :title,.......
6. アップローダーを実装したいviewと、画像を表示したいviewを編集する
<%= f.label :images, "画像:" %>
<%= f.file_field :images, multiple: true, accept: "image/*" %>
20
21/app/views/boards/new.html.erb「multiple: true」とすることで複数の画像がアップロードできる。「accept: "image/*"」とすることで画像ファイルしかアップロードできないようにする。
画像:
<% @board.images.each do |image| %>
<%= image_tag image, class: "board-images" %>
<% end %>
5
6
7
8/app/views/boards/show.html.erb.board-images {
display: inline-block;
width: 200px;
height: 200px;
}
1
2
3
4
5/app/stylesheets/styles.scss7. 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47/uploaders/image_uploader.rb8. 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:]\.\-\+]/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23/initializers/carrierwave.rb9. AWS S3へのアクセス環境変数設定をするため以下をターミナルで実行する
$ export AWS_ACCESS_KEY_ID= 自分のbucketのACCESS_KEY_IDを入れる
$ export AWS_SECRET_ACCESS_KEY= 自分のbucketのSECRET_ACCESS_KEYを入れる
※以上の実装はAWSS3にbucketを作成してからでないとできないので注意。
不明点、修正点ございましたらコメントよろしくお願いします。