当ブログではPRや広告を掲載しています

【Rails】ActiveStorage を初心者向けに解説!

rails activestorage プログラミング
この記事はこんな人向け
  • Rails 初学者
  • ActiveStorage の導入方法が知りたい
  • 既に refile などのgemを使っているが、ActiveStorageに乗り換えたい
スポンサーリンク

ActiveStorage とはざっくり言うと

画像をDB(データベース)でイイ感じに管理してくれる、「便利なヤツ」です。

難しい仕組みは後ほど解説しますが、仕組みまで理解してなくとも簡単に使えるようになっているのが特徴で、これからActiveStorageを導入する方などは最後までお付き合いください。

導入手順

インストール

まずはターミナル等で、railsを使用しているプロジェクト(フォルダ)に移動します。

そして、次のコマンドを実行して ActiveStorage をインストールします。

rails active_storage:install
rails db:migrate

実行後は、「YYYYMMDDHHMMSS_create_active_storage_tables.active_storage.rb」というファイルが作成され、さきほどのマイグレーションの実行で、schemaファイルに以下の内容が追加されます。

db/schema.rb
create_table "active_storage_attachments", force: :cascade do |t|
    t.string "name", null: false
    t.string "record_type", null: false
    t.integer "record_id", null: false
    t.integer "blob_id", null: false
    t.datetime "created_at", null: false
    t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
    t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
  end

  create_table "active_storage_blobs", force: :cascade 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"], name: "index_active_storage_blobs_on_key", unique: true
  end

モデルでの定義を追加

ActiveStorageで画像を扱うモデルに対して、以下のようにコードを追加します。
今回は、「Book」というモデルに対して導入するため、book.rbファイルに追記します。

app/models/book.rb
has_one_attached :image

この行は重要なので、意味を解説しておきます。

  • has_one_attached
    • 対象モデルのレコードと画像を単数で紐づける。(複数の場合はhas_many_attached)
  • :image
    • リレーションを組むカラム名のようなモノ。任意の名称でよい。

Viewファイルを編集

ここからは、実際に画像を登録できるように、画面のフォームを編集していきます。

以下のように、モデルで指定した “image” という名称で file_field を追加します。
(新規登録画面、編集画面など、必要な箇所に追加してください)

app/views/books/edit.html.erb
<%= form_with model:@book, local:true do |f| %>
  <div class="form-group">
    <label for="book_title">Title</label>
    <%= f.text_field :title, id:"book_title", placeholder:"", class: 'form-control'%>
  </div>
  <div class="form-group">
    <label for="image">Image</label>
    <%= image_tag @book.image, style: 'width:100%;' %>
    <%= f.file_field :image %>
  </div>
  <div class="form-group">
    <label for="book_opinion">Opinion</label>
    <%= f.text_area :body, rows:'5', id:"book_opinion", placeholder: "", class: 'form-control' %>
  </div>
  <div class="form-group">
    <%= f.submit "Update Book", class: 'btn btn-success' %>
  </div>
<% end %>

Controllerファイルを編集

最後にコントローラーを編集して、画像をDBに登録できるようにします。

今回は Book モデルに対して画像を登録するため、book_controllerの対象メソッド(createやupdateなど)に以下の記述を追加します。

app/controllers/book_controller.rb
@book = Book.new(params.require(:book).permit(:title, :body, :image))

このコードのミソは、”:image” の部分で、これがフォームやモデルで指定した名称と同じになっていることで、画像が登録されるようになっています。

※上のコードは、Book.new なので新規作成の例ですが、updateの場合は Book.update などの記述で出来ます。その辺りは追加する箇所に対して適切になるようにしてみてください。

ActiveStorageの動きを解説

さて、導入と動作はここまでで完了です!

ここからは ActiveStorage の理解を深めるために、登録した画像が何処にどのように登録されているか解説していきます。

※これ以降は、理解を深めたい人だけお進みください。

導入時に作られたテーブル

AcriveStorage では、画像をDBのカラムに文字列として格納し、呼び出された時に画像として表示しています。

では、そのテーブルはどのようになっているのか、インストール時に自動作成されたテーブルを見てみましょう。

作成されたテーブル
  • active_storage_attachments
    • モデルレコードとの紐付きを保存する、言わば中間テーブル。
  • active_storage_blobs
    • 実際に画像をカラムに保持しているテーブル。

schema.rb を見ることでも確認できますが、active_storage_blobs に “metadata” というカラムがあり、ここに画像が文字列のデータとして格納されています

画像レコードとモデルの紐付けの仕組み

ここまでやってきて、理解されている方は「active_storage_attachments は1つのテーブルなのに、複数モデルで画像を扱ったらどうなるのだろう」と思うかもしれません。

結論から言うと、複数モデルで画像を扱っても active_storage_attachments 1つのテーブルだけで紐付きを管理できるんです。

実際にどんなレコードが入っているか見てみましょう。

active_storage_attachments のレコード

Bookモデルの任意のレコードに対して画像を1つ登録してみました。
この時の active_storage_attachments のレコードは以下のようになっています。

active_storage_attachments
id|name|record_type|record_id|blob_id|created_at
1|image|Book|13|1|2022-03-14 09:16:19.997985

それぞれのカラムを解説すると、以下の通りです。

  • name
    • モデルで指定した名称。
  • record_type
    • モデル名
  • record_id
    • モデルの対象レコードのid
  • blob_id
    • active_storage_blobs のレコードのid

また、”created_at” のカラムしか存在しないことを考えると、このテーブルのレコードはデリート&インサートで内容を更新していると言えます。(=updateではない)

refile(画像系gem)との共存

これまで説明したActiveStorageの仕組みからすると、テーブルは独立しているため、refileなど画像系gem が既に入っていても導入可能です。

ただし、modelやviewファイルでの記載で競合する部分があるので、それらについて解説します。

refile -> ActiveStorage での競合箇所

それぞれの箇所を以下のように修正すれば、ActiveStorageで問題なく動作するようになります。

model

# refile
attachment :image
↓
# ActiveStorage
has_one_attached :image

view

# refile
<%= attachment_image_tag @book, :image, :fill, 60, 60, fallback: "no_image.jpg"%>
↓
# ActiveStorage
<% if @book.image.attached? %>
  <%= image_tag @book.image, size: '60x60' %>
<% else %>
  <%= image_tag 'no_image.jpg' %>
<% end %>

まとめ

  • ActiveStorage はコマンド2つ実行するだけでインストール完了
  • 画像保存ようのテーブルは自動生成され、自分でカラム追加などの必要は無い
  • model, view, controller をそれぞれ記述すればOK

コメント

タイトルとURLをコピーしました