Edited at

Rails、carrierwaveの使い方。インストール方法

More than 1 year has passed since last update.


はじめに

CarrierWaveの備忘録。

Railsは5。


Brew

ImageMagickをあらかじめ入れておく。

画像をS3に置くだけなら要らないけど、たいていの場合は加工するはず。

brew install imagemagick


Gemfile

RailsからS3にアクセスするためのGemと画像加工用にRMgickを入れておく。

# 画像保存

gem 'carrierwave'
# For Carrierwave(S3用)
gem 'fog'
# 画像加工用
gem 'rmagick'


設定ファイル

S3の設定を記載しておく。


initializers/carrierwave.rb

# S3を使用しているかを判定するためのメソッド。(ローカル環境ではS3を使わないため)

def use_s3?
ENV['S3_ACCESS_KEY'] && ENV['S3_SECRET_KEY'] && ENV['S3_REGION'] && ENV['S3_BUCKET']
end

## CarrierWaveの設定
CarrierWave.configure do |config|
# S3の設定
if use_s3?
config.fog_credentials = {
:provider => 'AWS',
:aws_access_key_id => ENV['S3_ACCESS_KEY'],
:aws_secret_access_key => ENV['S3_SECRET_KEY'],
:region => ENV['S3_REGION'],
# :host => '必要なら設定する'
# :endpoint => '必要なら設定する'
}

# S3のバケットを指定。
config.fog_directory = ENV['S3_BUCKET']
# 一般公開させて無いS3の場合は以下の設定を行う。
config.fog_public = false
# 一般公開されていない場合は以下の設定をする事で60秒間有効なURLを発行してくれる。
config.fog_authenticated_url_expiration = 60
CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
end

# public配下にキャッシュができると参照されてしまうので、予め変えておく。
config.cache_dir = "#{Rails.root}/tmp/uploads"
end



モデル

画像はString型で定義する。


migrate.rb

class Images < ActiveRecord::Migration[5.0]

def change
create_table :images do |t|
# 管理したい画像
t.string :image
# etc...

t.timestamps
end
end
end



model.rb

# 画像をアップロードする際のルール(別ファイルにしておけば汎用的に使える。)

class ImageUploader < CarrierWave::Uploader::Base
# S3を使用するか?
if use_s3?
storage :fog
else
storage :file
end

# S3やローカルの保存先。(以下の書式をそのまま書いておけば大抵問題無い)
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end

# 以下のようなことができる。

# リサイズしたり画像形式を変更するのに必要
include CarrierWave::RMagick

# 画像を100x100にリサイズする。
process :resize_to_fill => [100, 100]

# 保存形式をJPGにする
process :convert => 'jpg'

# サムネイルを生成する設定
# version :thumb do
# process :resize_to_fill => [40, 40, gravity = ::Magick::CenterGravity]
# end

# jpg,jpeg,gif,pngしか受け付けない
def extension_white_list
%w(jpg jpeg png)
end

# 拡張子が同じでないとPNGをJPGとかにコンバートできないので、ファイル名を変更
def filename
super.chomp(File.extname(super)) + '.jpg' if original_filename.present?
end

# 別のバケットにアクセスする場合は以下のようにする。
# https://blog.hello-world.jp.net/ruby/1449/
# def fog_directory
# config = YAML.load_file("#{Rails.root}/config/carrierwave.yml")[Rails.env]
# config['fog_another_directory']
# end

end

# 画像用モデル
class Image < ApplicationRecord
# ファイルアップロード処理
mount_uploader :image, ImageUploader
end



View

特に大した事はせず。

= simple_form_for(@image) do |f|

-#アップロードする画像(確認画面を作ることもできるけど、本記事では割愛)
= f.input :image, as: :file
-#アップロードした画像を表示
= image_tag f.image
-#カラム名にremoveをつけてデータを送ると画像を消せる。
= f.input :remove_image, as: :boolean
= f.submit "画像アップ"


Controller

StrongParamsなどいろいろ割愛。。。

def post_image

Image.new(params[:image]).save
end


まとめ

今まで自分でこれらのことをしてたけど、CarrierWaveを使うととても楽だった。

ただし、openなどでデータを取得して画像を設定したい場合にはややイレギュラーなことをする必要があった。

また、DBにblobとして格納する場合はCarrierWaveは使えない。

なので、要件に合わせて頑張る必要がある。


おまけ

URLから画像を拾ってきて画像を保存する方法。

もっといい方法があったら知りたい。

open(path, :allow_redirections => :safe) do |file|

# 一時的にテンポラリーファイルを作る必要があった。
temp_img_file = Tempfile.new('ファイル名')
temp_img_file.binmode
temp_img_file << file.read
temp_img_file.rewind
# UploadedFileもしくはCarrierWave::Uploader::Base形式にする必要がある。
uploaded_file = ActionDispatch::Http::UploadedFile.new(
filename: 'ファイル名',
type: file.content_type,
tempfile: temp_img_file)
image.image = uploaded_file
image.save
end


画像が横になる場合

以下のコードを記載する。


ImageUploader

  process :fix_rotate

# 画像の向きを調整する。
def fix_rotate
manipulate! do |img|
img = img.auto_orient
img = yield(img) if block_given?
img
end
end