LoginSignup
19
26

More than 3 years have passed since last update.

Active Storageで複数画像の投稿・削除

Last updated at Posted at 2020-07-26

環境

Ruby 2.5.1
Rails 5.2.4.3

やりたい事

Rails標準のファイル管理機能Active Storageを使い、画像を複数を投稿・削除できる機能を実装したい。

まずアプリを作成

$ rails new sample_app
$ cd sample_app 
$ bin/rails db:create

別ターミナルで

$ bin/rails s

http://localhost:3000 にアクセスして馴染みの画像が出ていればOK。

スクリーンショット 2020-07-26 21.55.06.png

modelとcontrollerを作成

今回はpostという名前で。

$ bin/rails g model post name:string 
$ bin/rails db:migrate
$ bin/rails g controller posts

ルーティング

config/routes.rb
Rails.application.routes.draw do
  resources :posts
end

Active Storageをインストール

$ bin/rails active_storage:install
Copied migration 20200726095142_create_active_storage_tables.active_storage.rb from active_storage

以下の2つのテーブルを作成するマイグレーションファイルが作成される。
・active_storage_attachments
・active_storage_blobs
migrateしてテーブルを作成。

$ bin/rails db:migrate
== 20200726095142 CreateActiveStorageTables: migrating ========================
-- create_table(:active_storage_blobs)
   -> 0.0020s
-- create_table(:active_storage_attachments)
   -> 0.0019s
== 20200726095142 CreateActiveStorageTables: migrated (0.0041s) ===============

モデルと関連付けて使えるようにする

models/posts.rb
class Post < ApplicationRecord
  has_many_attached :images
end

controllerを記述

controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    @posts = Post.all
  end

  def new
    @post = Post.new
  end

  def create
    @post = Post.new(post_params)

    if @post.save
      flash[:success] = "作成しました"
      redirect_to posts_path
    else
      render :new
    end
  end

  def destroy
    @post = Post.find(params[:id])
    @post.destroy
    flash[:success] = "作成しました"
    redirect_to posts_path
  end

  private

  def post_params
    params.require(:post).permit(:name, images: [])
  end
end

viewを作成

投稿一覧ページ

posts/index.html.erb
<h1>投稿一覧</h1>
<%= link_to '新規投稿', new_post_path %>
<%= render @posts %>

今回はpostのpartialを作って表示させる。

posts/_post.html.erb
<div class="post-partial">
  <li id="post-<%= post.id %>">
    <%= post.name %>
    <% post.images.each do |image| %>
      <%= image_tag(image, width:100) %>
    <% end %>
    <%= link_to '削除', post, method: :delete, data: { confirm: '削除してよろしいですか?' } %>
  </li>
</div>

新規作成ページ

画像を複数投稿する場合はmultiple: trueが必要

posts/new.html.erb
<%= form_with(model: @post, local: true) do |f| %>
  <div>
    <%= f.label :name, '名前' %>
    <%= f.text_field :title %>
  </div>

  <div>
    <%= f.label :images, '画像' %>
    <%= f.file_field :images, multiple: true %>
  </div>

  <div>
    <%= f.submit  '投稿する' %>
  </div>
<% end %>

ブラウザから http://localhost:3000/posts にアクセス

新規投稿から画像を複数投稿する事ができた。

スクリーンショット 2020-07-26 20.51.02.png

任意の画像を削除する

controllerにメソッド追記

編集に必要なedit、updateメソッドを追記します。

controllers/posts_controllers.rb
  def edit
    @post = Post.find(params[:id])
  end

  def update
    post = Post.find(params[:id])
    if params[:post][:image_ids]
      params[:post][:image_ids].each do |image_id|
        image = post.images.find(image_id)
        image.purge
      end
    end
    if post.update_attributes(post_params)
      flash[:success] = "編集しました"
      redirect_to posts_url
    else
      render :edit
    end
  end

投稿編集ページの作成

新規投稿ページとほぼ一緒だが、登録されている画像を表示しチェックを入れる部分を追記。

posts/edit.html.erb
<%= form_with(model: @post, local: true) do |f| %>
  <div>
    <%= f.label :name, '名前' %>
    <%= f.text_field :name %>
  </div>

  <div>
    <%= f.label :images, '画像' %>
    <%= f.file_field :images, multiple: true %>
  </div>

  <% if @post.images.present? %>
    <p>現在登録されている画像(削除するものはチェックしてください)</p>
    <% @post.images.each do |image| %>
      <%= f.check_box :image_ids, {multiple: true}, image.id, false %>
      <%= image_tag image, size:"100x100" %> <br>
    <% end %>
  <% end %>

  <div>
    <%= f.submit  '編集する' %>
  </div>
<% end %>

indexに編集リンクを追記

posts/index.html.erb
<div class="post-partial">
  <li id="post-<%= post.id %>">
    <%= post.name %>
    <% post.images.each do |image| %>
      <%= image_tag(image, width:100) %>
    <% end %>
    <%= link_to '編集', edit_post_path(post.id) %>  #追加
    <%= link_to '削除', post, method: :delete, data: { confirm: '削除してよろしいですか?' } %>
  </li>
</div>

確認

ブラウザから編集のリンクをクリックし、削除したい画像にだけチェックを入れる。
スクリーンショット 2020-07-26 21.35.14.png

任意の画像だけ削除できました。

スクリーンショット 2020-07-26 21.36.05.png

参考

ActiveStorageを使って複数画像管理をしてみる
ActiveStorage で画像を複数枚削除する方法

19
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
26