[Rails] CarrierWaveを使った画像アップロード

学習記録

はじめに

掲示板に画像投稿機能を実装しましょう。今回は投稿前に画像表示するプレビュー機能も実装します。

CarrierWaveとは

  • Railsにおける画像アップロード用ライブラリ。
  • CarrierWaveの特徴として、Uploaderクラスを別に持つという点。

作業の流れ

  • carrierwaveのインストール
  • アップローダークラスを作成
  • アップロード画像のカラムを追加
  • アップローダークラスとカラムの紐付け
  • ストロングパラメータに追記する
  • 画像ファイルの入力フィールドを用意する
  • JavaScriptでプレビュー機能を作成する
  • アップロードした画像を表示
  • 日本語化する

carrierwaveのインストール

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

gem 'carrierwave', '~> 2.0'

そして、CarrierWaveをインストール

$ bundle install

アップローダークラスを作成

Carrierwaveをインストールすることで、以下のコマンドを使用できるようになります。

$ bundle exec rails generate uploader BoardImage

コマンドを実行すると、以下のapp/uploaders/board_image_uploader.rb が生成されます。

生成されたアップローダにデフォルト画像ファイルの設定と、アップロード可能な拡張子の設定を追記しておきましょう。

class BoardImageUploader < CarrierWave::Uploader::Base
  storage :file
  
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end
  
  def default_url # デフォルトの画像ファイル
    'board_placeholder.png'
  end
  
  def extension_whitelist # 拡張子の制限
    %w[jpg jpeg gif png]
  end
  
end

画像のアップロード先を確認

storage :file

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

また、上記のコードより、デフォルトでstorage :file が指定されているので、アップロードしたファイルはpublic/ 配下に保存されます。

.gitignoreを編集

アップロードした画像をGit管理下から外すため、下記の追記をしましょう

/public/uploads

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

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

$ bundle exec rails g migration AddBoardImageToBoards board_image:string

作成されたマイグレーションファイルを確認しましょう

class AddBoardImageToBoards < ActiveRecord::Migration[5.2]
  def change
    add_column :boards, :board_image, :string
  end
end

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

$ bundle exec rails db:migrate

なお、DBに保存されるのは「画像データ」ではなく「画像のファイル名」です。

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

アップローダークラスとカラムの紐付け

次に「board_image カラム」と「BoardImageUploader クラス」を紐付けます。

class Board < ApplicationRecord
  mount_uploader :board_image, BoardImageUploader
  belongs_to :user

  validates :title, presence: true, length: { maximum: 255 }
  validates :body, presence: true, length: { maximum: 65_535 }
end

ストロングパラメータに追記する

画像ファイルをコントローラで受けとれるようにストロングパラメータに追記する

def board_params
  params.require(:board).permit(:title, :body, :board_image, :board_image_cache)
end

画像ファイルの入力フィールドを用意する

<%= form_with model:board,  local: true do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
    <div class="form-group">
      <%= f.label :title %>
      <%= f.text_field :title, class: 'form-control' %>
    </div>
    <div class="form-group">
      <%= f.label :body %>
      <%= f.text_area :body, class: 'form-control', rows: 10 %>
    </div>
    <div class="form-group">
      <%= f.label :board_image %>
      <%= f.file_field :board_image, class: 'form-control mb-3', accept: 'image/*', onchange: 'previewImage(preview)' %>
      <%= f.hidden_field :board_image_cache %>
    </div>
    <div class="mt-3 mb-3">
		  #  以下はプレビュー画面を表示するコード
      <%= image_tag board.board_image.url, id: 'preview', size: '300x200' %>
    </div>

    <%= f.submit class: 'btn btn-primary' %>
<% end %>

JavaScriptでプレビュー機能を作成する

_form.html.erbのコードと連動し、プレビュー画面をJavaScriptで作成します。

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);
    }
  }

アップロードした画像を表示

<%= image_tag board.board_image.url, class: 'card-img-top', size: '300x200' %>

日本語化する

ロケールファイルに追記しましょう。

ja:
  activerecord:
    attributes:
      board:
        title: 'タイトル'
        body: '本文'
        board_image: 'サムネイル'

こちらからコピーしてconfig/locales/carrierwave/ja.yml ファイルを作る

https://github.com/carrierwaveuploader/carrierwave-i18n/blob/master/rails/locales/ja.yml

終わりに

忘れそうになったら、都度復習が必要ですね。

参考記事

CarrierWaveチュートリアル
CarrierWaveで「ローカルへファイルをアップロードする方法」と「S3へファイルをアップロードする方法」をアプリケーションを作成して解説します。また、AWSの設定など分かりにくい豊富な画像や動画で解説しているのでこの記事を読めばスムーズに作成する事が出来ます。

コメント

タイトルとURLをコピーしました