LoginSignup
6
11

More than 5 years have passed since last update.

RailsとVue.jsを使ってプレビュー付きの画像登録機能を作ってみる

Last updated at Posted at 2019-03-27

複数の画像登録機能(プレビュー機能付き)の作成手順を記載してみる。

環境

Mac High Sierra
ruby 2.5.1
Rails 5.2.1

実装したこと

複数画像をアップして表示する際の手順を記載してみる。
・index画面に画像一覧を表示させる
・new画面を用意する
・new画面でファイル選択した際の画像をプレビュー表示する
バリデーションやエラーチェックなどはあまり気にせず作成
最低限の機能ってことで、一覧、新規追加、削除しか搭載しない

前の記事をそれぞれ参考にして作成
RailsとVue.jsを使った簡単な項目追加機能
ActiveStorageを使った複数画像管理

1.rails new

rails newに--webpack=vueオプションを付けて、プロジェクトの作成時にVue.jsもインストールさせる

console
rails new image_sample --webpack=vue

記事作成時はsqlite3でエラーが出た

Error loading the 'sqlite3' Active Record adapter. Missing a gem it depends on? can't activate sqlite3 (~> 1.3.6), already activated sqlite3-1.4.0. Make sure all dependencies are added to Gemfile.

ので、Gemfileの編集をする

Gemfile
# Use sqlite3 as the database for Active Record
gem 'sqlite3', '~> 1.3.6'

2.active_storageインストール、マイグレーション

console
cd image_sample
rails active_storage:install
rails db:migrate

[マイグレーション結果]
active_storage_blobs,active_storage_attachmentsテーブルが作られる

== 2019030XXXXXXX CreateActiveStorageTables: migrating ========================
-- create_table(:active_storage_blobs)
   -> 0.0027s
-- create_table(:active_storage_attachments)
   -> 0.0124s
== 2019030XXXXXXX CreateActiveStorageTables: migrated (0.0153s) ===============

3.モデル作成、画像関連づけ

console
rails g model item name:string
rake db:migrate
app/models/item.rb
class Item < ApplicationRecord
  has_many_attached :images
end

4.コントローラー作成

console
rails g controller items

5.ルーティング設定

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

6.コントローラー設定

app/controller/items_controller.rb
class ItemsController < ApplicationController
  # item一覧
  def index
    @items = Item.all
  end

  # item新規作成
  def new
    @item = Item.new
  end

  # item作成
  def create
    @item = Item.new(item_params)

    if @item.save
      redirect_to items_path
    else
      render :new
    end
  end

  # item削除
  def destroy
    @item = Item.find(params[:id])
    @item.destroy
    redirect_to items_path
  end

  private

  def item_params
    params.require(:item).permit(:name, images: [])
  end
end

7.ビューの設定

一覧と新規作成画面を用意する。

一覧画面

app/views/items/index.html.erb
<h1>Items Index</h1>
<%= link_to 'Add item', new_item_path %>

<ul>
  <% @items.each do |item| %>
    <li>
      <p><%= item.name %></p>
      <p>
        <% item.images.each do |image| %>
          <%= image_tag(image, width:100) %>
        <% end %>
      </p>
      <p>
        <%= button_to '削除', item, method: :delete, data: { confirm: 'Are you sure?' } %>
      </p>
    </li>
  <% end %>
</ul>

画像のサイズは一旦width:100で設定

新規作成画面

app/views/items/new.html.erb
<h1>Add Item</h1>

<%= form_with model: @item do |form| %>
  <div>
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>
  <div>
    <div id="image-app">
      <%= form.file_field :images , class: "hidden" , "v-on:change": "onFileChange($event)", multiple: true %>
      <ul v-if="images.length > 0">
        <li v-for="(image, index) in images">
          <button type="button" @click="removeThumbnail(image)">削除</button>
          <img :src="image.thumbnail.url" width="150" height="150"/>
        </li>
      </ul>
    </div>
    <%= javascript_pack_tag 'image' %>
  </div>
  <div>
    <%= form.submit %>
  </div>
<% end %>

8.Vueの処理設定

構成

app/javascript配下に以下を設定

javascript
 |_packs
   |_image.js
packs/image.js
import Vue from 'vue'

new Vue({
  el: '#image-app',
  data: function() {
    return {
      images: [],
    }
  },
  methods: {
    //ファイル選択後イベント
    onFileChange: function(ev) {
      let files = ev.target.files || ev.dataTransfer.files;
      let length = files.length;

      if ( ! length) return;

      for (var i=0; i<length; i++) {
        this.viewThumbnail(files[i]);
      }
    },
    // サムネイルを表示
    viewThumbnail: function(file) {
      var vm = this;
      var reader = new FileReader();

      reader.onload = function(ev){
        var image = {
          paths: [],
          thumbnail: {
            url: ev.target.result
          },
        };
        vm.images.push(image);
      };
      reader.readAsDataURL(file);
    },
    // サムネイルを削除
    removeThumbnail: function(image){
      this.images.splice(this.images.indexOf(image), 1);
    },
  },
})

9.webpackのBuildをする

console
bin/webpack-dev-server 

9.ローカルサーバー起動

console
rails s

9-1. http://localhost:3000/images にアクセス

スクリーンショット 2019-03-28 7.52.04.png

9-2.item新規作成で画像を選択

スクリーンショット 2019-03-28 8.16.44.png

9-3.Create_itemして一覧に遷移した後

スクリーンショット 2019-03-28 8.17.07.png

前の記事のコピーに近くなったけど、プレビュー表示できたのでよかった。

その他

item削除でdatabase lockエラー

スクリーンショット 2019-03-28 8.31.46.png

SQLite3のタイムアウトを変更する

config/database.yml


development:
  <<: *default
  database: db/development.sqlite3
  # 追加
  timeout: 1000


6
11
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
6
11