refileで画像を複数投稿したい!


今回はrefileで画像を複数投稿できる機能を作ります。
調べたところ、画像複数投稿には gem 'carrierwave'を使用する記事がたくさん出てきましたが、うまくいかなかったので今回はrefileで実装してみました。

画像投稿用のテーブルを作成

画像1枚だけの投稿だと、対象のモデルにimageカラムを追加するだけでいいのですが、複数枚となると別でテーブルを作成する必要があります。

私はpet_imageモデルを新規作成しました。

 create_table "pet_images", force: :cascade do |t|
    t.integer "pet_id"
    t.string "image_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["pet_id"], name: "index_pet_images_on_pet_id"
  end

リレーションを組む

1:Nの関係性を持たせます。

pet.rb
 has_many :pet_images, dependent: :destroy
 accepts_attachments_for :pet_images, attachment: :image
pet_image.rb
 belongs_to :pet
 attachment :image

コントローラーを編集

pet.controller.rb

 private
 def pet_params
    params.require(:pet).permit(:name, :birthday, :gender, :introduction, :genre_id, :prefecture_id, :age, :is_active, :image,  pet_images_images:[] )
  end

新規投稿フォーム編集

pet.new.html
<%= form_with model: @pet, url: pets_path, method: :post, local: true do |f| %>
  <%= f.attachment_field :pet_images_images, multiple: true %>
<% end %>

ペット一覧には画像を一枚だけ表示させたいので以下のように記述

pet.index.html
  <% pet.pet_images.first(1).each do |image| %>
   <%= attachment_image_tag image, :image, size: '200x200' %>
  <% end %>

画像を複数枚表示させたいところには↓

pet.show.html
<script type="text/javascript" src="//cdn.jsdelivr.net/npm/[email protected]/slick/slick.min.js"></script>
 <div id="slider">
   <% @pet.pet_images.each do |image| %>
      <%= attachment_image_tag image, :image, size: '350x350', class: "rounded mt-4" %>
   <% end %>
 </div>

プラスでスライドショーにする

application.html
<head>
  <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/[email protected]/slick/slick.css"/>
  <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/[email protected]/slick/slick-theme.css"/>
</head>
application.js
$(function() {
  $('#slider').slick({
      dots: true, 
      autoplay: true, 
      autoplaySpeed: 4000, 
  });
});
application.css
.slick-next {
    right: 10px 
    z-index: 100;
 }

.slick-prev {
    left: 10px 
  z-index: 100;
 }

以上です!!