takumiのエンジニア技術ブログ

takumiのエンジニア技術ブログ

未経験からエンジニアを目指しています!技術定着の為にこのブログにアウトプットしていきます!気軽にコメント等いただけるとありがたいです!

Active Storageを使用したタスク管理アプリへの画像添付(development環境)

f:id:golikyua:20190922105837j:plain

 

 

画像ファイル添付について勉強したのでアウトプットする!

 

目標

「タスク管理アプリのタスク詳細画面に画像を表示する」

 

やること

・Active Storageをタスク管理アプリで使うための準備。(Rails5.2以降はgemのインストールはされている)

・タスクモデルに画像を添付できるようにする。

 

大まかにはこんな感じ!

 

本題

 

Active Storageをタスク管理アプリで使うための準備

 

マイグレーションファイルの出力。

$bin/rails active_storage:install

 

 

db/migrate/xxxxxxxxxxxxxx_create_active_storage_tables.active_storage

# This migration comes from active_storage (originally 20170806125915)
class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
  def change
    create_table :active_storage_blobs do |t|
      t.string   :key,        null: false
      t.string   :filename,   null: false
      t.string   :content_type
      t.text     :metadata
      t.bigint   :byte_size,  null: false
      t.string   :checksum,   null: false
      t.datetime :created_at, null: false

      t.index [ :key ], unique: true
    end

    create_table :active_storage_attachments do |t|
      t.string     :name,     null: false
      t.references :record,   null: false, polymorphic: true, index: false
      t.references :blob,     null: false

      t.datetime :created_at, null: false

      t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
      t.foreign_key :active_storage_blobs, column: :blob_id
    end
  end
end

このマイグレーションファイルはActive Storageが利用する二つのテーブル、active_storage_blobs と active_storage_attachment を作成する。

 

二つのテーブルは、ActiveStorage::Bolb と ActiveStorege::Attachmentというモデルに紐ずいている。

ActiveStorage::Bolbは添付されたファイルに対応するモデルで、ファイルの実態をデータベース外で管理する!

ActiveStorege::AttachmenはActiveStorage::Bolbとアプリ内の様々なモデルを関連づける中間テーブル!

 

今回はTaskとActiveStorege::boldを紐づけます。

紐づけのイメージは以下の感じ!(※この画像はuserモデルとの紐づけだが、今回はTaskモデルとの紐づけ)

 

 

マイグレーションファイルをDBに反映させる

$bin/rails db:migrate

 

 

添付したファイルの実体を管理する場所について設定を行う。

Rails.application.config.active_storage.serviceにファイルを管理する場所の名前を与え、その名前に対応する設定を、config/storage.ymlに定義する。

(デフォルトでは、development環境のファイル管理場所はlocalとなっている)

 

config/environments/development.rb

# Store uploaded files on the local file system (see config/storage.yml for options)
  config.active_storage.service = :local

 

local設定がされているconfig/storage.yml

 test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
# amazon:
...

 

 

タスクモデルに画像を添付できるようにする。

 

1つのタスクに1つの画像を紐づける。

class Task < ApplicationRecord
  has_one_attached :image
 ...
end

has_one_attacthedというメソッドにより1つのタスクに1つの画像を紐づけること、その画像をTaskモデルからimageと呼ぶことを指定。

 

ビューを編集して新規登録画面、更新画面の両方で画像を指定できるようにする。

app/views/tasks/_from.html.slim(formパーシャル)

= form_with model: task, local: true do |f|
  .form-group
    = f.label :name
    = f.text_field :name, class: 'form-control', id: 'task_name'
  .form-group
    = f.label :description
    = f.text_area :description, rows: 5, class: 'form-control', id: 'task_description'
  .form-group
    = f.label :image
    = f.file_field :image, class: 'form-control'
  = f.submit nil, class: 'btn btn-primary'

form_withの中に新しくform-groupクラスを作成し、画像選択フォームを作成する。

 

画像フィールドのラベルが日本語表記になるように、config/locales/ja.ymlを編集

attributes:
      task:
        id: ID
        name: 名称
        description: 詳しい説明
        image: 画像
        created_at: 登録日時
        update_at: 更新日時

 

task_paramsメソッドを変更

app/controller/tasks_controllerdef task_params

def task_params
    params.require(:task).permit(:name, :description, :image)
  end

許可するパラメーターのキーとして:imageを追加する。

ビューを編集して取得した画像を、詳細画面で表示する。

 app/views/tasks/show.html.slimに以下を追加

...
tr th= Task.human_attribute_name(:image) td= image_tag @task.image if @task.image.attached?
...

 image_tagを使う場合は、実際に画像が添付されていないと、エラーが発生してしまうため、@task.image.attached?をいう判定メソッドを使用して、「画像が添付されている場合のみ、画像を表示する」というようにします!

 

まとめ

マイグレーションファイルを取得する

マイグレーションファイルの反映

 

一つのモデルに一つの画像を紐づける

新規登録、更新画面のビュー編集

imageラベルが日本語になるようにja.ymlファイルを編集

task_paremsを変更し、:imageを許可するパラメーターに追加

詳細画面のビュー変更 image_tagは画像がないとエラーになるため @task.image.attashed?で判定

 

 

参考文献

「現場で使える Ruby on Rails 5 速習実践ガイド 」