Rails Diary

プログラミングの学習記録です。

画像のアップロード

carrierwave

  • ファイルアップロード用のgem
  • ファイルのアップロード機能を簡単に追加できる。
  • Railsの画像投稿の仕組みでよく使われる。

mini_magick

画像を加工してくれるgem

mini_magickを使う前提としてImage_magickをインストールする必要がある???

ImageMagick さまざまな画像処理ができる。

  • 画像サイズ変更
  • 画像反転
  • 画像回転
  • 画像フォーマット変換
  • 色調整
  • グラデーション

brew install imagemagick

gem 'carrierwave' gem 'mini_magick'

rails g uploader image app/uploadersgディレクトリ以下にimage_uploader.rbが作成される

作成したアップローダーを関連するモデルと紐付ける Board

Boardモデル

class Board <ApplicationRecord
  mount_uploader :image, ImageUploader
end

アップローダーファイル

class ImageUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
  process resize_to_fit: [400, 200]
end

minimagick経由で画像のリサイズが行えるようにする

carrierwaveの使い方

① gemインストール
gem 'carrierwave'
アップローダークラス作成
bundle exec rails g uploader アップローダー名
# ユーザー画像を設定したいのならuser_imageなど

これでuser_image_uploader.rbという名前のアップローダークラスが生成される。

③ 対象のモデルに画像のファイル名を保存するカラムを追加

DBにファイル名を保存する理由
画像データそのものを保存するとDBサーバーの容量を圧迫してしまうため。作成したカラムにはどの画像ファイルか分かるようにファイル名だけを保存し、ビューで表示する際に画像が格納されているパスとDBに保存されているファイル名を用いて画像データを呼び出す。

bundle exec rails g migration AddUserImageToUsers

★ 今まで現場Railsに倣ってキャメルケースでマイグレーションファイルの雛形を作成してきたけど、スネークケースで作ってみても生成されるみたい。

bundle exec rails g migration add_user_image_to_users user_image: string

また↑のように末尾にuser_image:stringと加えることで、ファイル内のchangeメソッドが自動的に記載されていた。

class AddUserImageToUsers < ApplicationRecord::Migration[5.2]
  def change
    add_column :users, :user_image, :string
  end
end
④ DBに画像のファイル名が保存できるように、コントローラ内のストロングパラメータを変更する
# 追加したカラムが許可されるよう変更

def user_params
  params.require(:user).permit(:name, :age, :user_image)
end
⑤ 対象のモデルにアップローダークラスとカラムを紐付けを記載する
class User < ActiveRecord::Base
  mount_uploader :user_image, :UserImageUploader
end

# mount_uploader :カラム名, :アップローダークラス

この記載によって、画像をアップロードする際、記載したアップローダークラスの設定を利用できるようになる。

アップロードクラス内の記載

carrierwaveを通じた画像のアップロード先をどこにするのかが指定されているらしい。

# データの保存先をfileと指定している
# この記述によってpublic配下に保存されるらしい(???)
storage :file


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

↑model.class.to_s.underscore
モデルのクラスを表示し、stringに変換し、クラス名からファイル名に変換している。

細かく分からないので割愛

https://i.gyazo.com/944c9c2e9047095d5b94c6afe91f5d64.png

このクラスには上述した画像のアップロード先の設定の他、アップロード可能なファイル種別を指定したり、画像がアップロードされなかった際の初期画像の指定などをする。

def default_url
  '初期画像ファイル名指定.png'
end

# コメントアウトで記載されているので#を外せばOK
def extension_whitelist
  %w(jpg jpeg gif png)
end
⑥ 画像の追加フォーム作成

file_fieldの記載でファイル選択ボックスを生成

<div class="form-control">
  <%= f.label :user_image %>
  <%= f.file_field :user_image, class: 'form-control' %>
</div>

まだビューを追加していないが、試しに画像をアップロードしてみるとDBにファイル名、public配下に画像データが追加されている。

params内の@original_filenameにファイル名が入っている。

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

画像の保存場所(パス)の取得

アップロードしたファイルの情報取得

コンソール

適当にuserを取得

irb(main):004:0> user = User.first

ユーザーのuser_imageファイルURLを取得

irb(main):005:0> user.user_image.url
=> "/uploads/user/user_image/26/****.png

user_imageのカレントパスを取得

irb(main):006:0> board1.board_image.current_path
=> "/Users/****/workspace/runteq/rails_2/5118_*****_runteq_curriculum_normal/public/uploads/user/user_image/26/****.png"

user_imageのファイル名を取得

irb(main):007:0> board1.board_image_identifier
=> "****.png"
⑦画像の表示

上記のurlメソッドをimage_tagを使って表示

    <%= image_tag @user.user_image.url %>

★ ひとまず、ブラウザからリクエストを送った際、記載した画像URLをもとに画像データのレスポンスが返り、表示されるという認識でいる。

参考にしたサイト

【Rails】CarrierwaveとMiniMagickを使って画像を投稿する方法|TechTechMedia

【Rails】 CarrierWaveチュートリアル | Pikawaka

CarrierWave 拡張子とサイズ制限 - Qiita

【Rails】 image_tagを使って簡単に画像を表示させよう! | Pikawaka

Rails:CarrierWaveで画像のプレビュー機能を実装 | Boys Be Engineer 非エンジニアよ、エンジニアになれ

後々使えそうなメモ

【Rails】 CarrierWaveチュートリアル | Pikawaka

CSVのアップロード機能を追加する場合はCSV用のカラムとアップローダーを 生成してモデルで紐づける必要があります。