Rails 画像投稿機能の導入

CarrierWaveとMiniMagickを使って画像を投稿できるようにしていきます。この2つはインストール済みということを前提にして進めていきます。

画像のアップローダーの作成

% rails g uploader image

を実行すると、app/uploadesディレクトリにimage_uploader.rbが作成されます。

アップローダーとモデルの紐付け

次に、作成したアップローダーと関連するモデルを紐付けます。Boardモデルのboard_imageカラムと紐付けることを仮定します。board_imageカラムはstring型で生成します。カラムの生成方法は、

rails g migration AddBoardImageToBoards board_image:string

を実行。

class Board < ApplicationRecord
  mount_uploader :board_image, ImageUploader
end

これで紐付けが完了しました。 生成されたアップローダーにデフォルトの画像と、アップロード可能なファイルの種類を指定します。

class ImageUploader < CarrierWave::Uploader::Base

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

  def default_url
    '〇〇.png'
  end

  def extension_whitelist 
    %w(jpg jpeg gif png)
  end

end

アップロード先のファイルを.gitignoreに登録しておきます。

/public/uploads

画像の設定

image_uploader.rbを編集して、MiniMagick経由で画像のリサイズを行えるようにします。

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

としてあげるとリサイズすることができます。

view側の記述

ラベルと画像投稿用のフォームを作ります。

<%= f.label :board_image,"サムネイル" %>
<%= f.file_field :board_image %>

投稿が許可されるようにpermitするカラムの追加もします。

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

フォームに送信した画像を呼び出すには、

<%= image_tag board.board_image_url %>

で呼び出すことができます。

画像を保存しないときはデフォルトにしたい

def default_url
  '〇〇.png'
end

これをimageアップローダーに記述していたため、画像を載せないときはデフォルトで、〇〇.pngが乗ることになる。

参考

https://techtechmedia.com/carrierwave-minimagick-image/ https://ecolotta.hatenablog.com/entry/2020/12/31/175419 https://note.com/hajime38/n/ne2650fdf4559

gem 'mini_magick'の導入

gem 'mini_magick'とは

画像を加工してくれるgemです。使うためには、gemfileに

gem 'mini_magick'

と記述し、

% bundle install

を実行するとインストールできます。さらに、MiniMagickをしようするためには、ImageMagickというものが必要になるため、これもインストールしましょう。

% brew install imagemagick

これでMiniMagickが使えるようになりました。

MiniMagickでできること

MiniMagickでできることは画像処理のあれこれです。

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

など様々な画像処理を行えます。

参考

https://techtechmedia.com/carrierwave-minimagick-image/

Railsのバージョン指定インストール

Railsのバージョンを指定してインストールをしたいため、調べたことをまとめる。

Railsのバージョン確認

現在、インストール済みのRailsを調べる。

% gem list rails

これで現在インストール済みのRailsのバージョンを確認できる。

現在のRailsのバージョン確認

% rails -v

をする。

指定したバージョンをインストール

% gem install -v 5.2.3 rails

これで5.2.3のRailsをインストールできる。が、

% bundle install

も忘れずにしよう。

参考

qiita.com

https://qiita.com/dawn_628/items/93aa9a06bdedadf328f8

M1macでrbenvを使ってrubyのインストール

% rbenv install 2.6.3

などrubyのバージョンをインストールしたいときにBUILD FAILEDが出てしまってインストールできないことがある。 そんなときはこれ!

% RUBY_CFLAGS=-DUSE_FFI_CLOSURE_ALLOC rbenv install 2.6.3 

なんかわからないけどインストールできる。神

errorメッセージを個別で出したい

色々と調べながらやってるうちに知らない間にerrorメッセージを出せるようになってしまったが、やったことに自分の頭がついていっていないので、落ち着いてまとめてみる。

エラーメッセージ用のテンプレートの作成

まずはじめに全てのエラーメッセージを配列で取得します。が、エラーメッセージ用の部分テンプレートを作成するのが先です。いろいろなところで使うので、viewに書き込むと直すのが手間になってしまいます。views/shared/_error_messages.html.erbとしておきましょう。

<% if model.errors.any? %>
  <div class="alert alert-warning">
    <ul>
      <% model.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>

さて、上のように書くことで、エラーメッセージを配列で取得でき、複数のエラーメッセージがある可能性がある(自分で作っていれば)ので、eachを使って、全て取得します。一行ずつ丁寧にみていきます。

1行目 <% if model.errors.any? %>

<% if model.errors.any? %>

errors.any?はエラーがあるかどうかの真偽を出してくれるメソッドです。じゃあ、modelは?というと、呼び出す先で指定しているものになります。呼び出し先をviews/users/new.html.erbとでもしましょう。

<%= form_with model: @user, local: true do |f| %>
  <%= render 'shared/error_messages', model: f.object %>
...

<%= render 'shared/error_messages', model: f.object %>の部分で呼び出しをしていて、model: f.objectmodelの部分が、<% if model.errors.any? %>のmodelと対応しています。では、f.objectってなんだろう?ということで調べていきます。

model: f.objectとは

fはフォームビルダー変数といい、

<%= form_with model: @user, local: true do |f| %>

form_withで生成された|f|の部分です。このフォームビルダー変数には様々なメソッドがあり、text_field(一行のテキスト投稿フォーム)やselect(選択肢を作成)など様々ある。f.objectには、入力したデータが入っています。つまり、model: @userの情報をもっていることになるので、userコントローラーのnewアクションとつながっていることになる。かなり遠いところまで行くけど、そういうことみたい。

4行目 <% model.errors.full_messages.each do |message| %>

まず、はじめのmodelには、呼び出し先の

<%= form_with model: @user, local: true do |f| %>

の@userが代入されます。そして、errorsメソッドで@userの持っているエラーを表示してくれ、full_messagesでエラーの文章のみを配列で表示してくれます。そして、each do |message|でエラーの配列を一つ一つ処理してくれる、というようになっているようです。

これでエラーメッセージが個別で出る動きが分かった。難しい。

参考

https://yama2-0506.hatenablog.com/entry/2020/12/11/083007 https://qiita.com/ryuuuuuuuuuu/items/1a1e53d062bff774d88a

Railsでデータベースのリセットをしよう!

データベースを空にするために、

rails db:reset

rails db:migrate:reset

の2種類存在する。この2つについて考えていきます。

rails db:resetとは

rails db:resetは2種類のコマンドを実行するのと同じ働きがあります。

上の2種類のコマンドを実行するのと同等なので、一度データベースを削除して、スキーマからテーブルを再度作成し、シードデータを用いてデータベースの初期化を実行します。

rails db:migrate:resetとは

rails db:migrate:resetでは、DBの削除、DBの作成、rails db:migrateが行われます。なので、seeds.rbの読み込みがないため、ダミーデータのようなものは作成されません。

どちらを使うか

seeds.rbの読み込みまでしたい場合は、rails db:reset 読み込みまではしたくない場合は、rails db:migrate:resetということになる。

参考

https://k-koh.hatenablog.com/entry/2020/09/25/232829 https://railsguides.jp/active_record_migrations.html https://note.com/kentarotawara/n/n976705aa4cb8 https://railsdoc.com/rake#rake_db_migrate