🍋
【Rails】CarrierWaveの使い方をざっくりまとめてみた
1.この記事をなぜ書いたか
CarrierWaveの使い方を忘れてしまったので、復習の意味で記事を作成しました。
記事の中で間違いがある場合、コメント頂けると嬉しいです。
2.CarrierWaveとはそもそも何か?
CarrierWaveは、Webアプリケーションにファイルアップロード機能を提供するGemです。CarrierWaveを使うことで、Webアプリケーションにファイルアップロード機能を追加できます。
3.アップローダーとは何か?
アップローダーとはクラスオブジェクトです。このクラスから生成されたオブジェクトを使って、ファイル名やファイルの保存先を取得できます。また、アップローダーにはファイルアップロードに関する設定を書くことができます。
分かりづらくなってきたので、以下にアップローダーの特徴をまとめます。
- アップローダーはクラスオブジェクトである。
- アップローダーから生成されたオブジェクトを使って、ファイル名やファイルの保存先を取得できる。
- アップローダーにはファイルアップロードに関する設定を書ける。
それぞれの特徴を順番に説明して行きます。
- アップローダーはクラスオブジェクトである。
アップローダーはCarrierWaveをインストールして、rails generate uploader アップローダー名
コマンドを実行すると作成できます。ファイルを見ると、確かにクラスオブジェクトであることが確認できました。
app/uploaders/avatar_uploader.rb
class AvatarUploader < CarrierWave::Uploader::Base
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def default_url
'sample.jpg'
end
def extension_allowlist
%w(jpg jpeg gif png)
end
end
- アップローダーから生成されたオブジェクトを使って、ファイル名やファイルの保存先を取得できる。
アップローダーを使うには、まずファイル名を保存するカラムにアップローダーを取り付ける必要があります。 こうすることで、レコードの保存時に自動的にファイルをpublic/uploads
配下に保存できるようになります。そして、DBのファイル名を保存するカラムにはファイル名
のみ保存されます。 どうやってカラムにアップローダーを取り付けるかは実装手順で説明します。また、カラムにアップローダーを取り付けることによって、モデルのインスタンス生成時に、アップローダークラスのオブジェクトを同時に生成します。そのオブジェクトはインスタンス名.ファイル名を保存するカラム名
で呼び出すことができます。そのオブジェクトをレシーバとしてurl
メソッドやavatar_identifier
メソッドを使うと、ファイル名やファイルの保存先を取得できます。文章だと伝わりづらいので、以下の画像を用いて順番に説明します。(以下の画像では、ファイル名を保存するカラム名をavatar
としています。また、ファイルは画像ファイルを使っています。)
- 画像ファイルをアップロードする時に処理を止めます。処理を止めることで、アクション内の処理を確認できます。
-
更新する
ボタンを押した時に送られるparamsを見ると、avatarキーのバリューに画像ファイルの情報があることを確認できます。
- updateアクション内の
user = User.find(current_user.id)
のuserが持つavatarカラムを見ると、アップローダークラスのオブジェクトを確認できます。
- updateアクションを実行した後にuserが持つavatarカラムを見ると、アップローダークラスのオブジェクトに画像ファイルの情報が代入されていることが確認できます。
- アップローダークラスのオブジェクトをレシーバとして、
url
メソッドやavatar_identifier
メソッドを使うと、ファイル名やファイルの保存先を取得できることが確認できました。
- 終了
- アップローダーにはファイルアップロードに関する設定を書く。
以下の画像のように、アップローダークラスでメソッドのオーバーライドをすることによって、デフォルトの設定を変更できます。
app/uploaders/avatar_uploader.rb
class AvatarUploader < CarrierWave::Uploader::Base
#アップロードしたファイルの保存先を指定する。
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
#画像がアップロードされてない時に、'sample.jpg'を表示する。この画像はassets/images配下に事前に配置しておく。
def default_url
'sample.jpg'
end
#アップロードを許可するファイル種類を指定する。
def extension_allowlist
%w(jpg jpeg gif png)
end
end
4.CarrierWaveを用いた画像ファイルアップロード機能の実装手順
今回は、既存のWebアプリケーションに画像ファイルアップロード機能を実装します。
以下に手順を示します。
- Gemfileに以下のコードを書きます。
Gemfile
gem 'carrierwave', '~> 2.0'
- ターミナルで以下のコマンドを実行します。
ターミナル
bundle install
- ターミナルで以下のコマンドを実行します。その結果、アップローダーが作成されます(Avatarはアップローダーの名前です)。アップローダーは
app/uploaders/avatar_uploader.rb
で確認できます。
ターミナル
rails generate uploader Avatar
- Avatarアップローダーに以下のコードを書きます。
app/uploaders/avatar_uploader.rb
class AvatarUploader < CarrierWave::Uploader::Base
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def default_url
'sample.jpg'
end
def extension_allowlist
%w(jpg jpeg gif png)
end
end
- アップロードした画像ファイルは、
public/uploads/モデル名/画像のカラム名/id」
配下に保存されます。アップロードした画像ファイルをGithubに上げたくないので、.gitignoreに以下のコードを書きます。
.gitignore
/public/uploads
- アップローダーをモデル内のカラムに取り付けたいです。 そのため、初めに画像ファイル名保存用のカラムをDBに作ります(カラム名はavatarにします。型はStringです)。
シェル
rails g migration add_avatar_to_users avatar:string
rails db:migrate
- モデルファイルを開き、以下のコードを書いてアップローダーをカラムに取り付けます。こうすることで、レコードの保存時に自動的に画像ファイルを
public/uploads
配下に保存できるようになります。そして、DBのavatarカラムには画像ファイル名
のみ保存されます。
app/models/user.rb(一部抜粋)
class User < ApplicationRecord
mount_uploader :avatar, AvatarUploader
end
- Userコントローラのストロングパラメータに、avatarカラムを追加します。
users_controller.rb(一部抜粋)
def profile_params
params.require(:user).permit(:email, :last_name, :first_name, :avatar)
end
- 画像ファイルを送信したいフォームに、以下のコードを追加します。
<%= image_tag user.avatar.url, class: 'rounded-circle mt-3', id: 'preview', size: '100x100' %>
はプレビュー画像を表示するコードです。
_profile_form.html.erb(一部抜粋)
<div class="form-group">
<%= f.label :avatar %>
<%= f.file_field :avatar, onchange: 'previewImage()', class: 'form-control' %>
<%= f.hidden_field :avatar_cache %>
<%= image_tag user.avatar.url, class: 'rounded-circle mt-3', id: 'preview', size: '100x100' %>
</div>
- JavaScriptでプレビュー機能を作成します。
assets/javascripts/common.js
function previewImage() {
const target = this.event.target;
const file = target.files[0];
const reader = new FileReader();
reader.onloadend = function () {
const preview = document.querySelector("#preview")
if(preview) {
preview.src = reader.result;
}
}
if (file) {
reader.readAsDataURL(file);
}
}
- 画像を表示したいビューテンプレートに以下のコードを書きます。
views/profiles/show.html.erb(一部抜粋)
<%= image_tag @user.avatar.url, class: 'rounded-circle mr15', width: '40', height: '40' %>
- 終了
実施にフォームを送信して、アップロードができることを確認できました。
5.アップローダークラスのオブジェクトが使える代表的なメソッド
以下に、アップローダークラスのオブジェクトが使える代表的なメソッドをまとめます。
- url
- avatar_identifier
順番に説明します。
- url
urlメソッドを使うと、アップローダークラスのオブジェクトが所有している画像ファイルの保存先urlを取得できます。public配下に置く画像ファイルは、Railsの仕様でブラウザに直接送信されるので、urlメソッドとimage_tagを使って画像を表示できます。
- avatar_identifier
avatar_identifierメソッドを使うと、アップローダークラスのオブジェクトが所有している画像ファイル名を取得できます。
6.MiniMagickについて
MiniMagickを使うと、画像のサイズを変更できます。事前にImageMagickのインストールが必要です。こちらのサイトで詳しく解説されています。
アップローダークラスに以下のコードを書くと、画像サイズの変更ができます。app/uploaders/board_image_uploader.rb(一部抜粋)
include CarrierWave::MiniMagick
process resize_to_limit: [300, 200]
7.終わり
アップローダーの挙動をちゃんと理解した訳ではないので、いずれコードリーディングしようと思います。
この記事が少しでも役に立てば幸いです!
8.参考文献
Discussion