すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Rails

更新日:

【Rails】 CarrierWaveチュートリアル

ぴっかちゃん
ぴっかちゃん

CarrierWaveとは、ファイルのアップロード機能を簡単に追加する事が出来るgemです。

CarrierWaveは、アップロードしたファイルの保存先はデフォルトでpublic/uploadsですが、外部のストレージ(例: Amazon S3)にも設定する事が出来ます。

ファイルがs3にアップロードされているか確認

この記事では、以下の2部構成になっています。

  1. Carrierwaveのローカルの使い方
  2. CarrierwaveでS3にアップロードする方法

第一部では、デフォルトのpublic/uploadsに画像をアップロードする方法を解説し、第二部では、外部のストレージであるAmazon S3にアップロードする方法を解説していきます。

Carrierwaveのローカルの使い方

この章では、ファイルアップロード機能の追加・操作・設定の基礎的な部分を解説します。
アップロードしたファイルの保存場所は、デフォルトのpublic/uploads配下です。

Carrierwaveでファイルをアップロードする方法

ユーザーを管理する事が出来るsample_appアプリケーションを作成して、Carrierwaveでユーザー登録時や編集時にアバター画像のアップロードと詳細画面で表示が出来る様にします。

sample_appアプリケーションの完成図は、以下の通りです。

sample_appの完成図

このsample_appアプリケーションを以下の手順で作成します。

  1. Gemfileにcarrierwave追加
  2. アップローダークラスの生成
  3. アップロード画像のカラムを追加
  4. アップローダークラスとカラムの紐づけ
  5. アバター画像の登録・更新
  6. アバター画像の表示

実際に手を動かしてアプリケーションを作成することで、Carrierwaveへの理解を一層深めることが出来ます。Carrierwaveを使った事が無い方は、この機会に是非アプリケーションを作成しながらマスターしてみて下さい。

前準備:サンプルアプリケーション用意

まずは、rails newsample_appアプリケーションを作成します。

ターミナル | データベースをMySQLを指定してアプリケーションを作成する -->
1
rails _5.2.1_ new sample_app -d mysql

次に、scaffoldを使ってUserモデルを作成します。
scaffoldで簡易的なユーザー登録や編集、一覧機能など一気に作る事が出来ます。

ターミナル | ユーザー管理する為の雛形を作成 -->
1
2
3
cd sample_app # ディレクトリを移動
rails g scaffold User nickname:string age:integer # scaffoldを実行
# rails g scaffold モデル名 カラム名:型 カラム名:型

そして、データベースの作成とscaffoldの内容を元にして作成されたマイグレーションを実行します。

ターミナル | データベース作成とマイグレーションを実行-->
1
bundle exec rails db:create && bundle exec rails db:migrate

rails serverでサーバーを起動させてlocalhost:3000/usersにアクセスすると、以下のようにユーザーの登録・表示・編集の簡単な機能が作成されます。

簡単な機能を持つサンプルアプリケーションの例

この登録フォームにCarrierwaveを使って、アバター画像を追加出来る様にします。

1. Gemfileにcarrierwave追加

Carrierwaveを導入するためにGemfileに以下を追加します。

Gemfile | Carrierwaveを追加-->
1
gem 'carrierwave', '~> 2.0'

そして、Carrierwaveをインストールする為に、bundle installします。

ターミナル | Carrierwaveのインストール-->
1
bundle install

インストールしたcarrierwaveのgemを読み込むために、必ずサーバーを再起動させましょう。

2. アップローダークラスの生成

Carrierwaveをインストールすると、アップローダークラスを以下のコマンドで生成する事が出来ます。

ターミナル | アップローダークラスを作成 -->
1
bundle exec rails g uploader アップローダー名

今回は、ユーザーのアバター画像用のアップローダークラスを作成するので、以下のようにAvatarを指定してコマンドを実行します。

ターミナル | Avatarアップローダークラスを作成 -->
1
bundle exec rails g uploader Avatar

コマンドを実行すると、以下のapp/uploaders/avatar_uploader.rbファイルが作成されます。

avatar_uploaderファイル

「アップローダーの設定」で解説しますが、作成したアップローダークラス(AvatarUploader)では、アップロードするファイルの拡張子やサイズ、保存するパスを指定する事が出来ます。

また、デフォルトでstorage :fileが指定されているので、アップロードしたファイルはpublic/配下に保存されます。保存されるディレクトリは、store_dirで設定されます。

3. アップロード画像のカラムを追加

次に、アップロード画像の情報を保存するavatarカラムを追加する為に、マイグレーションファイルを作成します。

ターミナル | avatarカラムを追加する為のマイグレーションファイルを作成-->
1
bundle exec rails g migration add_avatar_to_users avatar:string

上記のコマンドを実行すると、以下のマイグレーションファイルが作成されます。

avatarカラムを追加するマイグレーションファイルを作成

マイグレーションを実行して、usersテーブルにavatarカラムを追加します。

ターミナル | マイグレーションを実行-->
1
bundle exec rails db:migrate

usersテーブルを確認すると、avatarカラムが追加されています。

テーブルにavatarカラムを追加されたのを確認

後ほどアバター画像の登録・更新機能を追加しますが、このavatarカラムには、以下のように「画像のデータ」ではなく「画像のファイル名」を保存します。

アップロードされた画像をusersテーブルで確認する

DBにファイル名を保存する理由とは?

ファイル名ではなく画像データを保存すると、データベースサーバーの要領が圧迫するからです。
avatarカラムには、どの画像ファイルか確認出来るようにファイル名だけを保存し、画像を表示するときに「画像が格納されてるパス」と「DBに保存されているファイル名」を使います。

最後に、データベースに保存出来る様にusers_controlleruser_paramsavatarカラムを追加します。

app/controllers/users_controller.rb | user_paramsにavatarカラムを追加-->
1
2
3
4
5
6
7
def user_params
  params.require(:user).permit(:nickname, :age) # 変更前
end

def user_params
  params.require(:user).permit(:nickname, :age, :avatar) # 変更後
end

avatarカラムを変更すると、以下のようになります。

user_paramsにavatarを追加

これで、avatarカラムに画像のパスを保存出来る様になります。

4. アップローダークラスとカラムの紐づけ

次に、「アップロード画像用のカラム」と「アップローダークラス」を紐づける為に、以下のコードをモデルに記述します。

モデル | アップローダークラスとカラムを紐づける-->
1
2
3
class モデル名 < ActiveRecord::Base
  mount_uploader [:カラム名], [アップローダークラス]
end

今回は、ユーザーのアバター画像のアップロード機能を追加するので、以下のようにUserモデルに先ほど作成したアバター画像用の「avatarカラム」と「AvatarUploaderクラス」を紐づけます。

モデル | AvatarUploaderクラスとavatarカラムを紐づける-->
1
2
3
class User < ActiveRecord::Base
  mount_uploader :avatar, AvatarUploader
end

これでアバター画像をアップロードする際に、AvatarUploaderクラスの設定を利用出来る様になりました。AvatarUploaderクラスでは、画像の保存場所がstorage :fileと指定しているので、アップロードした画像はpublic/uploads配下に保存されます。

5. アバター画像の登録・更新

ユーザー登録・編集フォームでアバター画像を追加出来る様に、app/views/users/_form.html.erbの既存のフォームに file_filedでファイル選択ボックスを作成します。

app/views/users/_form.html.erb | アバター画像のファイル選択ボックスを作成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div class="field">
  <%= form.label :nickname %>
  <%= form.text_field :nickname %>
</div>

<div class="field">
  <%= form.label :age %>
  <%= form.number_field :age %>
</div>

<!-- ここから追加するコード -->
<div class="field">
  <%= form.label :avatar %>
  <%= form.file_field :avatar %>
</div>

上記の11行目からのコードを追加してlocalhost:3000/users/newを確認すると、ファイル選択ボックスが作成されてアバター画像の登録・追加が行える様になっています。

以下は、編集画面で既存のユーザー(id=1)にアバター画像を追加してます。

既存ユーザーのアバター画像を保存する

上記のフォームから送信される情報をpry-railsを使って、以下のようにparamsメソッドで確認します。

アバター画像で送信される情報

paramsには、フォームから送信された全ての情報が格納されます。その中のavatarに、今回アップロードしたファイルの情報が入ります。

そして、@original_filenameは、アップロードしたファイルの名前で、この値が以下のようにデータベースに保存されます。

アップロードされた画像をusersテーブルで確認する

また、アップロードした画像は「public/uploads/モデル名/画像のカラム名/id」配下に保存されます。
先ほどアップロードした画像は、id=1のユーザーのアバター画像になるので、以下の配置に保存されます。

アップロードしたファイルの保存先がpublic/uploads/user/avatar/1以下になる

このpublic/uploads/配下に保存される画像は、Githubなどにアップロードする必要がないので、以下のように.gitignoreファイルに/public/uploadsを指定してGit管理下から除外します。

/public/uploadsをGit管理下から除外する

gitignoreの詳細は、「.gitignoreの書き方を図解形式で理解しよう!」を参考にしてください。

6. アバター画像の表示

アバター画像を登録しただけでは、以下のように画像は表示されません。

アバター画像を表示できるようにする

アバター画像を表示させるには、まずは画像が保存されている場所(パス)を取得する必要があります。

Userモデルに、AvatarUploaderクラスとavatarカラムを紐づけたので、以下のAvatarUploaderクラスのメソッドを使って簡単にアップロードしたファイルの情報を取得することが出来ます。

メソッド 内容
url ファイルのURLを取得 userインスタンス.avatar.url
current_path カレントパス取得 userインスタンス.avatar.current_path
avatar_identifier ファイル名を取得 userインスタンス.avatar.avatar_identifier
コンソール | アバター画像のファイル選択ボックスを作成-->
1
2
3
4
5
6
7
8
9
10
11
12
irb(main):001:0> user = User.first
  User Load (0.6ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User id: 1, nickname: "ピカ子", age: 18, created_at: "2020-02-25 13:21:31", updated_at: "2020-02-25 13:43:54", avatar: "120185.png">

irb(main):002:0> user.avatar.url
=> "/uploads/user/avatar/1/120185.png"

irb(main):003:0> user.avatar.current_path
=> "/Users/username/directory/sample_app/public/uploads/user/avatar/1/120185.png"

irb(main):004:0> user.avatar_identifier
=> "120185.png"

アップロードした画像は、上記のurlメソッドとimgタグを生成する image_tagを使って表示します。

以下のように、app/views/users/show.html.erbにコードを追加します。

app/views/users/show.html.erb | アバター画像表示させるためのコードを追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<p>
  <strong>Nickname:</strong>
  <%= @user.nickname %>
</p>

<p>
  <strong>Age:</strong>
  <%= @user.age %>
</p>

<!-- 追加するコード-->
<% if @user.avatar? %>  <!-- アップロード画像がある場合に実行する -->
  <p>
    <strong>Avatar:</strong>
    <%= image_tag @user.avatar.url %><!-- userインスタンスの画像ファイルのURLを取得し表示 -->
  </p>
<% end %>
<!-- ここまで -->

上記は、アバター画像が無いユーザーもいるので、エラーが出ないようにif文を使って条件分岐も追加します。

ユーザー詳細ページでは、以下のようにアバター画像を表示することが出来ました。

アバター画像の表示

なぜ表示できるのか?

public以下に置くファイル(画像)は、Railsのデフォルトでブラウザに直接送信されるので、アドレスバーにpublic以下のパス(url)を指定する事で、その画像をブラウザで表示する事が出来ます。

public配下のファイルがブラウザに表示される仕組み

このブラウザで表示された画像を以下のようにimage_tagを使って、ユーザー詳細ページに表示させているのです。

image_tagを使って画像を表示している例

また、user.avatarを実行すると以下のようになります。

user.avatarの結果を表示

ファイルのメタ情報がAvatarUploaderクラスのインスタンスに格納されており、@fileには、さらにCarrierWaveクラスのインスタンスが格納されています。

作業段階でエラーが出た場合の対処法

以下のエラーが表示されたら、サーバー再起動をして下さい。

コードが反映されないでエラーになる例

また、 rails consoleする際にNameError (uninitialized constant User::AvatarUploader)エラーが発生した場合は、config/application.rbに以下の行を追加してサーバーを再起動して下さい。

config/application.rb | コンソール立ち上げでエラーが発生した場合-->
1
2
3
4
5
6
module SampleApp
  class Application < Rails::Application
    config.load_defaults 5.2
    config.autoload_paths += Dir[Rails.root.join('app', 'uploaders')]   # この行を追加
  end
end

CarrierwaveでS3にアップロードする方法

前章では、アップロードしたファイルをpublic/uploads配下に保存していましたが、このままではアップロードする毎にサーバーの容量が圧迫されます。これを解決する為に、この章ではアップロードファイルの保存先を「外部のクラウドストレージサービス Amazon S3」にする方法を解説します。

AWS設定

前提条件: AWSアカウントを作成していること

AWSアカウントをまだ作成していない方は、「AWSのアカウントを作成しよう」を参考にアカウントを作成しましょう。(※IAMユーザー作成は、本記事の手順で行います。)

1. IAMユーザーの作成

AWSでアカウント作成すると、全ての機能を扱えるルートアカウントが発行されます。

このルートアカウントを不正利用されると、高額請求や構築した環境を破壊されるケースがあるので、AWSで操作する際はルートアカウントではなく、必要な機能の権限のみ与えたIAMユーザーを作成する必要があります。

今回は、S3にアクセスする事が出来るIAMユーザーを作成します。
まずは、AWS マネジメントコンソール画面でIAMを検索してIdentity and Access Managementページを開きます。

IAM検索から

上記の様にサイドバーにあるユーザーを選択して、ページ上部にあるユーザーを追加をクリックすると、以下の動画の様に「ユーザー詳細の設定」ページが開くので、自分のユーザー名を記入して「AWSアクセスの種類」にプログラムによるアクセスを選択します。

ユーザー詳細の設定

入力後に次のステップ:アクセス権限をクリックすると、以下の「アクセス許可の設定」ページが開くので、作成するユーザーにS3のアクセス許可をするために既存のポリシーを直接アタッチを選択して、AamzonS3FullAccessにチェックを入れます。

アクセス追加

次のステップ:タグをクリックすると、以下の画面でタグを作成する事が出来ますが、ここでは飛ばして次のステップ:確認を選択します。確認画面で入力した内容に間違えがないか確認してユーザーの作成をクリックします。

タグのオプション

ユーザーが作成されると、以下の様にユーザーのアクセスキーIDシークレットアクセスキーが表示されます。
この2つの情報はCarrierwaveで利用するので、必ず.csvのダウンロードをするか、メモしてください。

アクセスキーIDとシークレットアクセスキーの表示

以上でIAMユーザー作成の手順は終わりです。

2. S3バケットの作成

次に、S3バケットを作成します。ルートアカウントのまま操作を行います。
S3バケットは、S3に保存するファイルの入れ物(Buckets = バケツ)です。

まずは、以下のようにダッシュボードでS3を検索して、Amazon S3のページを開きます。(ナビゲーションのサービスでも検索出来ます。)

S3ページ検索

そして、上記の様にバケットを作成をクリックして、以下の項目を入力して次へをクリックします。

  • バケット名 - 一意のバケット名を入力
  • リージョン - アジアパシフィック(東京)を入力[AWSで使用可能なデータセンターを設置している独立した地域]

次に以下の画面が表示されますが、デフォルトのままで次へをクリックします。

バージョニングなどの設定

そして、次のアクセス権限の設定ページでは、パブリックアクセスを全てブロックのチェックを外して、以下の項目にチェックして次へをクリックします。

アクセス許可の権限ページ

今回は、この後に設定するバケットポリシーでS3にアクセス出来るように上記の項目をチェックしました。
最後は確認ページなので、以下の画面になっている事を確認してバケット作成をクリックします。

確認画面で確認してからバケットを作成

アクセス許可の権限ページで正しくチェックが入っていないと、アップロードする際に以下のようなエラーが出てしまうので注意してください。

アクセス許可が正しく行われていない場合のエラー

3. バケットポリシーの追加

次にルートアカウントで作成したS3(所有者)に対して、IAMユーザーがアクセス出来る様にバケットポリシーを追加します。

まずは、以下の様にIAMページに移動して、サイドバーのユーザーをクリックし先ほど作成したユーザーを選択します。ページの上部にユーザーのARNがあるので、それをコピーします。

IAMのARNをコピーする

次にS3のページに移動して、以下の様に作成したバケットを選択してアクセス権限のタブを開きバケットポリシーをクリックします。

アクセス権限のタブを開く

バケットポリシーエディターに、以下の設定を記述します。AWSResourceには、先ほどコピーしたARNとバケット名を入れてください。

バケットポリシー | 設定を記述する
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt000001",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::ARNをここに貼り付ける"
            },
            "Action": "s3*",
            "Resource": "arn:aws:s3:::バケット名"
        }
    ]
}
ポリシーの要素 内容
Version ポリシー言語のバージョン
Statement 各ポリシーの要素を記述
Sid ステートメントID
Principal アクセス権限を付与 or 拒否されるユーザー
Action 許可 or 拒否する操作の内容
Resource 対象のオブジェクト


以下のように設定を記述出来たら、保存を選択してください。

バケットポリシーエディターの例

これで、AWSでの設定は以上です。

▼ AWSの用語や技術について不安がある方は、図解を使って丁寧に解説している以下の参考書を利用すると良いでしょう。クラウドやネットワークの基礎から学べます。

aws参考書
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

IT業界などへの転職・就職を目指す人、駆け出しエンジニアがAWS関連の用語、しくみ、クラウドとネットワークの基礎技術などを一通り学べます。

Carrierwave設定

前提:Carrierwaveのインストールやアップローダーのカラム紐付けまで完了していること
上記が終わっていない方は、Carrierwaveでファイルをアップロードする方法で各設定を行なってください。

「Carrierwave設定」では、fog-awsの追加とAWSで作成したIAMユーザーバケットの情報を設定ファイルに記述してS3にファイルをアップロード出来る様にします。

1. Gemfileにfog-awsを追加

まずは、Gemfilefog-awsを追加します。
fog-awsは、ファイルの保存先を外部のストレージする際にサポートしてくれるgemになります。

Gemfile | fog-awsをGemfileに追加する -->
1
gem 'fog-aws'

fog-awsを追加したらbundle installします。

2. アップローダーのストレージを変更

次に、app/uploaders/avatar_uploader.rbstorage :fileの箇所をstorage :fogに変更します。

app/uploaders/avatar_uploader.rb | storageをfogへ変更-->
1
2
3
class AvatarUploader < CarrierWave::Uploader::Base
  # storage :file # コメントアウト、もしくは削除してください
  storage :fog

storage :fogに変更する事で、fogを使ってファイルの保存先を外部のストレージにする事が出来ます。

3. IAMユーザーとバケットの情報を設定する

AWSで作成したIAMユーザーバケットの情報を設定する為に、config/initializers/配下にcarrierwave.rbのファイルを作成します。config/initializers/配下のファイルは、フレームワークとgemの読み込み完了後に自動で読み込まれます。

ターミナル | touchコマンドを使ってcarrierwave.rbのファイルを作成-->
1
touch config/initializers/carrierwave.rb

carrierwave.rbファイルには、以下の設定を記述します。

config/initializers/carrierwave.rb | S3の設定 -->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
    config.storage :fog
    config.fog_provider = 'fog/aws'
    config.fog_directory  = 'バケット名' # 作成したバケット名を記述
    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',   # アジアパシフィック(東京)を選択した場合
      path_style: true
    }
end 

carrierwave.rbファイルの主な各項目は、以下の通りです。

項目 内容
config.fog_directory S3で作成したバケット名
region バケット作成の際にリージョンをアジアパシフィック(東京)
選択した場合ap-northeast-1
aws_access_key_id IAMユーザー作成時のアクセスキーID
aws_secret_access_key IAMユーザー作成時のシークレットアクセスキー

リージョンがアジアパシフィック(東京)以外の場合は、Regions, Availability Zones, and Local Zonesから確認して下さい。

また、aws_access_key_idaws_secret_access_keyは、第三者に漏洩すると悪用される危険性があるので、そのまま記述せずに必ず環境変数を使う必要があります。

環境変数が分からない方は、「環境変数とは?」を参考にしてください。

4. 環境変数の設定

次に、環境変数を管理してくれるdotenv-railsのgemを追加します。
以下のように、Gemfiledotenv-railsを追加したらbundle installします。

Gemfile | dotenv-railsをGemfileに追加する -->
1
gem 'dotenv-rails'

そして、アプリケーションのルート直下に.envファイルを作成して、以下のようにアクセスキーとシークレットアクセスキーを環境変数に定義します。

.env | 環境変数の設定 -->
1
2
3
4
5
6
AWS_ACCESS_KEY_ID = 'IAMユーザー作成時のアクセスキーIDをここに記述'
AWS_SECRET_ACCESS_KEY = 'IAMユーザー作成時のシークレットアクセスキーをここに記述'

# 使い方
# ENV['AWS_ACCESS_KEY_ID']
# ENV['AWS_SECRET_ACCESS_KEY']

.envファイルで設定した環境変数を反映させる為にrails serverでサーバーを再起動させてください。

ざっと解説しましたが、dotenv-railsについて詳しくは、dotenv-railsの導入方法と使い方を参考にして下さい。

4. .envファイルをgitignoreする

.envファイルに記述したaws_access_key_idaws_secret_access_keyの情報を漏洩させない為に必ずGit管理下から除外する必要があります。

.gitignoreファイルに以下のように.envファイルを指定してgitignoreします。

.gitignore | .envファイルをGit管理下から除外
1
/.env

これで、.envファイルはGit管理下から除外されたので、Githubに間違ってアップロードされずに済みます。

以上でS3にアップロードする設定は終わりです。

5. S3にアップロードされているか確認

それでは、アプリケーションを起動してファイルがS3にアップロードされているか確認してみましょう。
以下では、ユーザー登録の際にアバター画像を選択して、id=12のユーザーを作成します。

ファイルがs3にアップロードされているか確認

上記の様に、ユーザー作成後にS3のバケットを確認すると、uploads/user/avatar配下にid=12のフォルダが作成されてuploads/user/avatar/12配下にファイルがアップロードされています。

また、ユーザー詳細ページにアクセスすると以下のようにアップロードした画像を表示する事が出来ました。

ユーザー詳細ページに画像が表示された例

なぜ表示されるのか?

S3の外部ストレージサーバーに保存したファイル(画像)は、アドレスバーに保存先(オブジェクト URL)を指定する事で、その画像をブラウザで表示する事が出来ます。

オブジェクトURLをブラウザで表示させた結果

このブラウザで表示された画像を以下のようにimage_tagを使って、ユーザー詳細ページに表示させているのです。

s3の画像をユーザー詳細ページに表示する事が出来る仕組み

今回は、開発環境でもS3にファイルをアップロードする事が出来ますが、本番環境でのみS3にアップロードしたい場合は、以下のように設定する事が出来ます。

app/uploaders/avatar_uploader.rb | 本番環境のみstorageをfogへ変更-->
1
2
3
4
5
6
class AvatarUploader < CarrierWave::Uploader::Base
  if Rails.env.production?
    storage :fog # 本番環境のみ
  else
    storage :file # 本番環境以外
  end

その他の操作と設定

Carrierwaveのその他の操作と設定について解説します。

手動でアップロード画像を削除する方法

アップロードしたファイルを手動で削除する場合は、remove_avatar!を使う事が出来ます。

userインスタンスを取得してremove_avatar!でアバター画像を削除すると、以下のようにavatarカラムがnilになります。saveメソッドを実行すると保存されます。

コンソール | アップロード画像を削除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
user = User.first # id=1のユーザーを取得
=> #<User id: 1, nickname: "ピカ子", age: 18, created_at: "2020-02-25 13:21:31", updated_at: "2020-02-25 13:43:54", avatar: "120185.png">

user.remove_avatar! # アバター画像を削除
=> []

user # avatarカラムがnilになっていることを確認
=> #<User id: 1, nickname: "ピカ子", age: 18, created_at: "2020-02-25 13:21:31", updated_at: "2020-02-25 13:43:54", avatar: nil>

user.save # 保存する
   (3.4ms)  BEGIN
  User Update (31.8ms)  UPDATE `users` SET `updated_at` = '2020-02-26 05:48:08', `avatar` = NULL WHERE `users`.`id` = 1
   (3.5ms)  COMMIT
=> true

usersテーブルを確認すると、id=1avatarカラムのデータが削除されている事がわかります。

usersテーブルを確認

また、public/uploads/user/avatar/1配下に保存されていた画像も削除されています。 

id=1のアバター画像が削除される

アップローダーの設定項目

アップローダーで設定出来る主な項目を紹介します。

app/uploaders/avatar_uploader.rb | アップローダーの設定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class AvatarUploader < CarrierWave::Uploader::Base
  storage :file

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_whitelist
    %w(jpg jpeg gif png)
  end

   version :thumb do
    process resize_to_fit: [50, 50]
  end
end
項目 内容
storage アップロードファイルの保存場所を指定
store_dir アップロードファイルの保存するディレクトリを指定
extension_whitelist アップロードするファイルの許可する拡張子を指定
version 同じファイルの違うバージョンを追加する
リサイズでサイズを指定する事が出来る

modelを経由せずにアップロードする方法

modelに紐づかない画像をアップロードする場合に、store!メソッドを使うとmodelを経由せずに直接アップロードする事が出来ます。

例えば、ユーザー登録の際にアバターをアップロードしていますが、これはUserモデルに紐づいているユーザーのファイルをアップロードしています。

しかし、以下のPikawakaのサイトのロゴは、特にmodelに紐づいていません。
この様な場面でmodelを経由せず、store!メソッドでファイルを直接アップロードする事が出来ます。

pikawakaロゴ

まず、アップローダーファイルapp/uploaders/avatar_uploader.rbstore_dirメソッドを変更します。

以下のif model.present?は、modelが存在するならuploads/モデル名/画像のカラム名/modelのidのディレクトリにファイルが保存されて、modelが存在しない(直接アップロード)ならuploads/content_image/にファイルを保存する様にします。(present?メソッドについては、present?メソッドの使い方へ)

app/uploaders/avatar_uploader.rb | store_dirメソッドを変更
1
2
3
4
5
6
7
8
9
10
class AvatarUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick # ここも追加
   def store_dir
      if model.present?
        "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
      else
        'uploads/content_image/'
      end
    end
end

また、store!メソッドを使う際にMiniMagickが無いとエラーになってしまうので2行目のinclude CarrierWave::MiniMagickも追加します。

それでは、以下のロゴをS3のuploads/content_image/にアップロードしていきます。
※ 本来ロゴは、白背景ですが分かりやすくする為青色の背景にしています。

pikawakaのロゴをアップロードする

rails consoleでコンソールを起動させて以下のコマンドを実行します。自分の環境で行う場合は、user名ファイル名の箇所を変更してください。

コンソール | ファイルを直接アップロードする
1
2
3
uploader = AvatarUploader.new
uploader.store!(File.open("/Users/user名/Downloads/log.png", "r"))
=> [:store_versions!] # 返り値

コマンド実行後に以下のようにS3を確認すると、バケットの中にuploads/content_image配下にlog.pngがアップロードされています。

直接s3にアップロードした結果

このように、modelに紐づかないファイルをアップロードしたい場合は、store!メソッドを利用する事で直接アップロードする事が可能です。

今回は、Carrierwaveでファイルをアップロードする方法を解説しましたが、Rails5.2から追加されたActive Storageという画像アップロード機能もあります。シンプルに画像のアップロード機能を追加するならActive Storage、細かい設定をしたい場合はCarrierwaveにして上手く使い分けましょう。

他にも実務向けのややハイレベルなRuby on Railsの知識について学びたい方は、こちらの参考書が良いでしょう。Rails 6.0も含めて広い範囲を体系的に学ぶことができます。

この記事のまとめ

  • Carrierwaveとは、ファイルのアップロード機能を簡単に追加する事が出来るgemのこと
  • デフォルトでは、ローカルのpublic/uploads配下にアップロードファイルが保存される
  • AWSの情報とfog-awsAmazon S3にファイルをアップロードする事が出来る