15
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails7】ActiveStorageの使い方

Last updated at Posted at 2023-12-12

はじめに

ECサイトを制作する課題に取り組んでいる際にActiveStorageについて調べたのでまとめました。


ActiveStorageとは

Active Storageは、ストレージサービスへのファイルのアップロードや、ファイルをActive Recordオブジェクトにアタッチする機能を提供します。
Active Storage の概要 - Railsガイド


ActiveStorageでできること

アップロードされたファイルをアタッチする

アップロードされたファイルをActiveRecordオブジェクトにアタッチさせることで、実際のテーブルにファイルのカラムがあるかのように扱うことができます。

itemsテーブル

name price description

上記のようなテーブルにアップロードされた画像をimage属性としてアタッチし

name price description image

のような扱い方ができるようになり、
item.nameなどと同じようにitem.imageでattachさせた画像を表示させられるようになります。

ストレージに保存する

アップロードされたファイルの保存先として
Railsアプリ内(ローカル)の他にもクラウドストレージサービスなどを指定することができ、
画像投稿機能があるサイトなど、利用されていくごとにファイルが増えていくような場合はそのようなサービスと連携させて保存していくのが良さそうです。

その他

アップロードされたファイルの「ActiveRecordオブジェクトへのアタッチ」「ストレージへの保存」以外にvariantなどを利用して画像の変形などを行いたい場合には、別途gemのインストールが必要になります。


ActiveStorageの使い方


保存先の設定

config/storage.yml内に

storage.yaml

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

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

amazon:
  service: S3
  access_key_id:     <%= ENV['AWS_ACCESS_KEY'] %>
  secret_access_key: <%= ENV['AWS_SECRET_KEY'] %>
  region:            <%= ENV['AWS_REGION'] %>
  bucket:            <%= ENV['AWS_BUCKET'] %>
  

のような記述があり、ここがアップロードされたファイルの保存先を指定しています。

ここに記述されている:test,:local,:amazonの設定を別途production.rb等の環境ごとの設定ファイルに指定することで利用できます。

(開発環境では:localに、本番環境では:amazonなどのクラウドストレージを利用するやり方が良いかと思われます)
開発環境の設定development.rbでは:localが保存先としてデフォルトで指定されています。
config/environments/

development.rb
Rails.application.configure do
  config.active_storage.service = :local
end

本番環境でクラウドストレージを利用する場合はproduction.rb

production.rb
Rails.application.configure do
  config.active_storage.service = :amazon
end

のように自身が用意したものに変更します。
(AWSなどのクラウドストレージに保存する場合は、認証情報を安全に管理するためにdotenv-railsなどのgemの利用が良さそうです。)




ここまで終わりましたら

$ rails active_storage:install

$ rails db:migrate
を実行します。


これでactive_storageを利用するための以下の3つのテーブルが作成されます。

active_storage_blobs

アップロードされたファイルのメタデータが保存されるテーブル

active_storage_attachments

blobとアタッチ対象のテーブルを結びつける中間テーブル

active_storage_variant_records 

variantを利用して生成されたデータが保存されるテーブル



モデルとファイルの結びつけ


次に``app/models/○○.rb``にファイルとモデルを関連づけるように記述をします

一つのレコードが一つの画像を持つ場合

item.rb
class Item < ApplicationRecord
  has_one_attached :image
end

のように記述します。


一つのレコードが複数の画像を持つ場合は
has_many_attached :images
のように記述します。


:imageは実際に取り出すときに
user.imageのように記述する部分になるので自由に命名して大丈夫です。

登録フォームを作成する

viewに画像をアップロードできるフォームを作成します。

new.html.erb
<%= form_with model: @item, url: items_path, method: :post do |f| %>

<p>

<%= f.label(:name, "商品名") %>

<%= f.text_field :name %>

</p>

<p>

<%= f.label(:price, "値段  ") %>

<%= f.text_field :price %>

</p>

<p>

<%= f.label(:sku, "型番  ") %>

<%= f.text_field :sku %>

</p>

<p>

<%= f.label(:description, "説明 ") %>

<%= f.text_area :description %>

</p>
### 他の属性と同じように書けばよい。
<%= f.file_field :image %>

<p>

<%= f.submit "作成" %>

</p>

<p>

<%= link_to "戻る", items_path %>

</p>

<% end %>

コントローラーに記述

items_controller.rb
class ItemsController < ApplicationController
  def create
    @item = Item.new(item_params)

    if @item.save
      flash[:success] = '商品を登録しました。'
      redirect_to admin_items_path
    else
      flash[:danger] = '商品の登録に失敗しました。もう一度試してください。'
      render 'new', status: :unprocessable_entity
    end
  end

  private

  ### :imageを追加
  def item_params
    params.require(:item).permit(:name, :price, :sku, :description, :image)
  end
end

表示させる

show.html.erb
<!-- items/show -->
<%= @item.name %>
<%= @item.price %>
<%= image_tag(@item.image) %>

variantの使い方


variantを使って、画像のリサイズを行う方法は2種類用意されています。
  • 画像処理ライブラリとしてImageMagickを利用する
  • 画像処理ライブラリとしてvipsを利用する

ImageMagickは、libvipsに比べて知名度が高く普及も進んでいます。しかしlibvipsは10倍高速かつメモリ消費も1/10です。JPEGファイルの場合、libjpeg-devlibjpeg-turbo-devに置き換えると[2〜7倍高速]になります。
Active Storage の概要 - Railsガイド



vipsを使ってみます。

使うための準備


vipsをインストールする

macなら

brew install vipsまたはlibvips

(vipsの中にlibvipsも含まれています。)

Dockerを利用している場合、Dockerfileにlibvipsが含まれているか確認してください。含まれていれば、別途インストールは不要です

image_processingを入れる

次にGemfileに
gem "image_processing", ">= 1.2"
を記述してbundle installをします。

image_processingを入れることで
Rubyでimage_magickを使うために必要な"Mini_magick"、Rubyでvipsを使うために必要な"ruby-vips"もインストールされます。

補足

もしrails7以降にvariantでimage_magickを使う場合は
デフォルトの設定がvipsになっているため
config/application.rb

application.rb
config.active_storage.variant_processor = :mini_magick

の記述が必要なようです。(rails7以前の場合は反対にvipsを利用する場合に記述が必要)


実際に使う


show.html.erb
<%= image_tag @item.image.variant(resize_to_fit: [150, 150]) %>

のように記述をする方法と

例えば、商品のモデルapp/models/item.rb

item.rb
class Item < ApplicationRecord

has_one_attached :image

def thumnail

image.variant(resize_to_limit: [450, 300])

end

def large

image.variant(resize_to_limit: [600, 700])

end

end

のように定義しておいて、viewで

show.html.erb
<%= image_tag @item.thumnail %>

のように記述して使う方法があります。

variantの仕組み

最初にvariantが使用されているページにアクセスしたときに、
rails active_storage:installを実行した時に作成されたactive_storage_variant_recordsテーブルにvariantで生成された加工後のデータが保存されます。
次回以降にアクセスした際は新たに生成せず、そのデータを読み込んで利用するため、処理が早くなる。

画像のリサイズにvariantを使うメリット

サーバー側でサイズの変更や加工などの画像処理をするためクライアント(ブラウザ)へ送信する画像のサイズを小さくすることができ、ページの読み込み速度を向上させられる。

ただし、画面の大きさに合わせて動的に画像サイズを変更できるわけではないのでCSSと合わせて使うのが良さそう。



さいごに

自分なりに学んだことをまとめてみました。間違っている箇所などありましたら指摘いただけると幸いです。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?