Image magicを使用してphotogalleryを作成する。


はじめに

プログラマー初学者です。何か至らない点などあれば是非ご指摘ください。

私は現在Railsを学習中なのですが、まずは何か成果物を作成したいと思い、
個人的にあれば便利だなーと感じるものを作ることにしました。

そこで考えついたのは旅行前後に使えるアプリです。
(既にそのようなアプリは山程あるとは思いますが。。。)
色々機能を実装していきたいと考えてるのですが、
photogalleryは必ず組み込みたいと思い実装しました。
備忘録として記事に残したいと思います。

やりたいこと

Bootstrapとimage magicを使いレスポンシブなアルバムページを作成する。

環境

macOS:10.15.2
Ruby:2.6.5
Rails:5.2.4.1
Bootstrap: 4.3.1

手順

1. Image Magicをインストールする。

まず、Image Magicが既に導入済みかのチェックをこちらのコマンドを使って調べます。

$ convert -v

下記のようにバージョン情報が出てきたらインストール済みとなります。

Version: ImageMagick 7.0.10-0 Q16 x86_64 2020-03-08 https://imagemagick.org

インストールには、brewコマンドを使用します。

$ brew install imagemagick

これで、imagemagickのインストールは完了です。
$ convert -vでインストール完了済みかチェックしてみて下さい。

2. mini_magick、carrierwaveのインストールを行う

次にGemfileを編集していきます。
以下、記述後bundle installを行って下さい。

Gemfile
gem 'carrierwave'
gem 'mini_magick'

これで、準備はOKです!

3. 投稿画像用のデータベースの作成

今回は例として、scaffoldを使用してUploadモデルを作成していきたいと思います。

$ rails g scaffold upload image:string title:string body:text
<!--投稿した画像にタイトルとコメントを入れるためのカラムを作成します。-->

次にapp配下にアップローダーを生成します。

$ rails g uploader images
$ rails db:migrate

ここまでで大体の機能は実装されています。

4. アップローダーの設定

先程作成したアップローダーに画像を投稿する際の設定内容が記載されている為、
こちらを編集していきます。(app/uploaders/images_uploader.rb)

まずは、modelsの編集から行います。
下記のように記述して下さい。
(validatesを記述することで空の投稿を防ぎます。)

upload.rb
class Upload < ApplicationRecord
  mount_uploader :image, ImagesUploader
  validates :title, presence: true
  validates :image, presence: true
  validates :body, presence: true
end

次にアップローダーの編集をしていきます。

images_uploader.rb
# Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  include CarrierWave::MiniMagick <!--コメントアウト外す-->

  # Choose what kind of storage to use for this uploader:
  storage :file
  # storage :fog

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:

 def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end
<!--アップロードの中に保存するという記述(画像保存先はpublic配下)-->

# Provide a default URL as a default if there hasn't been a file uploaded:
  # def default_url(*args)
  #   # For Rails 3.1+ asset pipeline compatibility:
  #   # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
  #
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  # end

 def extension_whitelist
    %w(jpg jpeg gif png)
  end
<!--追記。ホワイトリストの記述でアップロード出来る画像を制限出来ます。-->

  process :resize_to_limit => [700, 700]
<!--追記。画像保存時のサイズを指定することが出来ます。サーバの容量オーバーを防ぎます。-->

  version :thumb do
    process resize_to_fill: [100, 100]
  end
<!--追記。サムネイルサイズを指定することが出来ます。-->

<!--以下省略-->

5. Viewsの編集

現段階では、画像の選択ボタンが表示されていないので、views/uploadsの編集を行っていきます。

_form.html.erb
  <div class="field mb-4">
    <%= form.label :画像 %>
    <%= form.file_field :image %>
  </div>
<!--デフォルトでは、form.text_fieldとなっているので、form.file_fieldに編集。
この記述により、ブラウザから画像のアップロードが可能となります。-->

  <div class="form-group">
    <label>タイトル</label>
    <%= form.text_field :title, class: "form-control" %>
  </div>

  <div class="form-group">
    <label>内容</label>
    <%= form.text_area :body, class: "form-control" %>
  </div>

ここまでの記述で画像のアップロード機能は完成したので、
アップロードした画像の表示をさせていきたいと思います。
下記の記述でアップロード後のShow画面を作成していきます。

show.html.erb
<div class="container">
<p>
  <%= image_tag @upload.image_url() if @upload.image.present? %>
</p>
<!--上記記述で先程指定したサイズの画像が表示されます。サムネイル画像を表示させたい
場合は()内に:thumbと記載すればサムネイル画像の表示に切り替わります。-->

<p>
  <strong>Title:</strong>
  <%= @upload.title %>
</p>

<p>
  <strong>Body:</strong>
  <%= @upload.body %>
</p>

<%= link_to '編集', edit_upload_path(@upload) %> |
<%= link_to '戻る', uploads_path %>
</div>

最後に投稿した画像一覧をアルバムのように表示させる為に、
indexを編集して完成にしたいと思います。

_index.html.erb
<h1>PhotoGallery</h1>

<div class="container">
 <div class="row">
  <% @uploads.each do |upload| %>
   <div class="col-lg-4 col-md-6 col-sm-12 mb-4">
     <div class="container border">
       <div class="row bg-dark ">
         <%= upload.title %>
        </div>
        <div class="row">
         <%= image_tag upload.image_url(), class: "img-fluid" if upload.image.present?%>
        </div>
        <div class="row text-body">
          <p class="card-text"><%= upload.body %></p>
        </div>
        <div class="row">
          <button type="button" class="btn btn-sm btn-outline-primary"><%= link_to '詳細', upload %></button>
          <button type="button" class="btn btn-sm btn-outline-primary"><%= link_to '編集', edit_upload_path(upload) %></button>
          <button type="button" class="btn btn-sm btn-outline-primary"><%= link_to '削除', upload, method: :delete, data: { confirm: '削除してもよろしいでしょうか' } %></button>
        </div>
      </div>
    </div>
  <% end %>
 </div>
</div>

<br>
<%= link_to '新規投稿', new_upload_path %>

Bootstrapのグリッドシステムを使い、レスポンシブデザインに対応させました。
表示させるとこのような画面になります。

画面幅を狭くすると。。。


1列に表示させる画像が3つから2つに切り替わりました。

非常にシンプルなアルバム一覧ページとなりましたが、
まだまだ改良の余地が盛り沢山かと思いますので、
学習進めながら更新していきたいと思います。