gem 'carrierwave' , 'mini_magick'を使用して画像投稿機能を実装してみた.。
はじめに
画像投稿機能を実装する際に初めて利用したgemなので、振り返りとしてまとめています。
環境
carrierwaveとは?
ファイルをアップロードする方法を提供してくれるgemです。
特徴としてはUploader
クラスを別に提供してくれるので、フォーマットの指定、画像のリサイズなどのロジックをモデルに書かなくて済みます。
その為、「この設定をこのモデルとこのモデルに適応する」といったことを柔軟に行えるような仕様になっています。
実装手順
今回はBoardsテーブルが事前にあり、そこにboard_image:string
を追加して作業を行っていくとします。
db/ schema.rb create_table "boards", force: :cascade do |t| t.string "title", null: false t.text "body", null: false t.integer "user_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "board_image" # <= このカラムを利用していきます!! t.index ["user_id"], name: "index_boards_on_user_id" end
Uploaderクラスを作成
今回は「BoardImage」という名前で作成していきたいと思います。
rails g uploader BoardImage
# => uploaders/board_image_uploader.rbを作成してくれます。
デフォルトの挙動を確認する
作成されたファイルの中身を確認したいと思います。
storage :file
public/
に画像が保存されることになります。def store_dir
画像が保存される先のpathを指定します。
def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end
カラムとUploaderを結びつける
今回はBoardsテーブルのboard_image
カラムと結び付けたいので
models/board.rb class Board < ApplicationRecord mount_uploader :board_image, BoardImageUploader # <= 追加する end
フォームの作成
今回は単一の画像投稿にしたいと思います。
<%= f.label :board_image %> <%= f.file_field :board_image, id: 'board_board_image' %>
ここまでで画像をアプリ側に保存するまでは終わりです。
対応するカラムがなぜstring型なのか?
DBにはファイルそのものを入れるのではなく、ファイルを参照する為のデータを保存します。これにより、DBの圧迫を抑えることができます
保存した画像を表示する
UploaderではURL,pathなどを取得する為のメソッドが用意されています。
> board = Board.last # => board_image: "sample.jpeg" が入っているとします > board.board_image.file.nil? # => false > board.board_image.url # => "/uploads/board/board_image/40/sample.jpeg" > board.board_image.path # =>"/Users/username/Desktop/sample/public/uploads/board/board_image/5/sample.jpeg" > board.board_image_identifier # => "sample.jpeg"
今回はimage_tag
を使用して画像を表示したいと思います。
<%= image_tag board.board_image.url %>
また、画像を保存していないデータの為にデフォルトのURL
も指定することができます。
uploaders/board_image_uploader.rb def default_url 'default.png' # <= app/assets/images/default.png を返す。 end
これによって、HTMLでデータ一覧を表示する際にif文を使用して画像データの有無に対しての処理を分けなくて済みます。
フォーマットのホワイトリストを指定する
以下のように指定できます。
uploaders/board_image_uploader.rb def extension_whitelist %w[jpg jpeg gif png] end
画像のリサイズを行う
mini_magick
を使用するのでbundleします。
インストールしたら、Uploaderクラスに以下のコードを追加します。
uploaders/board_image_uploader.rb class BoardImageUploader < CarrierWave::Uploader::Base include CarrierWave::MiniMagick # <= デフォルトはコメントアウトされています。 process resize_to_fill: [300, 200, "Center"] # <= 追加します end
これでリサイズが行われます。
他にもリサイズする為のメソッドはいくつかあるので試してみてください!!
おまけ プレビュー機能の追加
おまけとして以下のようなプレビュー機能を作成したいと思います。
html
<div class="form-group"> <%= f.label :board_image %> <%= f.file_field :board_image, id: 'board_board_image', class: 'form-control', accept: "image/jpeg, image/jpg, image/gif, image/png" %> </div> <!-- 以下が画像が表示される部分です --> <div class="form-group"> <%= image_tag 'board_placeholder', size: '300x200',id: 'preview_img' %> </div>
document.addEventListener('DOMContentLoaded', () => { const file_button = document.querySelector('#board_board_image'); const preview_img = document.querySelector('#preview_img'); file_button.addEventListener('change', (e) => { let file = e.target.files; let reader = new FileReader() ; reader.readAsDataURL(file[0]) reader.onload = function() { preview_img.src = reader.result; } },false); });
参考
https://rubydoc.info/gems/carrierwave/frames
GitHub - minimagick/minimagick: mini replacement for RMagick
【Rails】CarrierWaveチュートリアル | Pikawaka - ピカ1わかりやすいプログラミング用語サイト
JavaScriptでFile APIを用いたファイル操作方法ついて解説 | ELOOP(イーループ) - 開発課題に取り組んで身につける実践型プログラミング学習サービス