君が代

基本的にワイの忘備録(コードとかで誤りやもっと良い方法があるぞというのはコメントしてくれたらうれC)

【Rails忘備録】画像のアップロード機能を追加するの巻

今回は店舗情報の新規登録に画像をアップロードできるようにする。

セットアップ

まずMiniMagickを利用するためにImageMagickをインストール。

$ brew install imagemagick

このImageMagickは画像のサイズ調整やその他の編集などが行える画像処理のライブラリです。

次に画像をアップするためのGemをインストールします。

gem 'mini_magick'
gem 'carrierwave'
$ bundle

このMiniMagickはImageMagickRuby用に使いやすくしたものの一つのようです。

MiniMagick is a Ruby wrapper for ImageMagick command line. MiniMagick gives you convenient access to all the command line options ImageMagick supports.

imagemagick.org

Carrierwaveはファイルをアップロードするためのgemです。

続いて画像投稿用のアップローダーを作成します。

$ rails g uploader image

実装

ここからアップローダーをモデルに紐付けていきます。

以下を実行してstoreにimageを追加します。

$ rails g migration AddImageToStores image:string
$ rails db:migrate

店舗情報への画像追加なのでstoreモデルに今回は追記します。 app/models/store.rb

class Store < ApplicationRecord
   mount_uploader :image, ImageUploader

stores/_form.html.slim

= form_with model: store, local: true do |f|
  = render 'shared/error_messages', object: f.object
  .form-group
    = f.label :name
    = f.text_field :name, class: 'form-control'
  .form-group
    = f.label :address
    = f.text_field :address, class: 'form-control'
  .form-group
    = f.label :business_hours
    = f.text_field :business_hours, class: 'form-control'
  .form-group
    = f.label :regular_holiday
    = f.text_field :regular_holiday, class: 'form-control'
  .form-group
    = f.label :description
    = f.text_area :description, class: 'form-control', rows: 10
  .form-group
    = f.label :image
    = f.file_field :image, class: 'form-control'
    = f.hidden_field :image_cache
  .mt-3.mb-3
    = image_tag store.image.url, id: 'preview', size: '300x200'
  = f.submit class: 'btn btn-primary'

= f.hidden_field :image_cacheに関して

こちらについてはバリデーションエラー等で画像のアップロードに失敗した時に、再度画像を添付してなくても済むように画像を保持することができるようにするものです。

次に画像の値を送れるようにストロングパラメーターを更新します。 stores_controller.rb

def store_params
    params.require(:store).permit(:name, :address, :business_hours, :regular_holiday, :description, :image, :image_cache)
 end

最後に店舗一覧画面にアップした画像を表示できるようにします。 stores/_store.html.erb

.col-sm-12.col-lg-4.mb-3
  .card
    = image_tag store.image_url,  class: 'card-img-top', size: '300x200'
    .card-body
      h4.card-title
        = link_to store.name, store_path(store.id)
      .mr10.float-right
        a[href="#"]
          = icon 'fas', 'trash', class: 'pr-1'
        a[href="#"]
          = icon 'fa', 'pen'
      p.card-text
        = store.description

また画像が無い場合のデフォルトの画像の設定も行います。 こちらはviewにelseの処理を記載するのではなく、default_urlを設定します。 uploaders/image_uploder.rb

def default_url
  'sample.jpg'
end

以上です。