U-Yuri’s 健忘録

U-Yuri’s 備忘録

プログラミングを勉強しています。アウトプットに活用しているブログです。

【Rails】Active Storageを使用し、画像投稿のフォームを作成する

セットアップ

% rails active_storage:install
Copied migration 20240327082510_create_active_storage_tables.active_storage.rb from active_storage
% rails db:migrate
== 20240327082510 CreateActiveStorageTables: migrating ========================
-- create_table(:active_storage_blobs, {:id=>:primary_key})
   -> 0.0065s
-- create_table(:active_storage_attachments, {:id=>:primary_key})
   -> 0.0037s
-- create_table(:active_storage_variant_records, {:id=>:primary_key})
   -> 0.0020s
== 20240327082510 CreateActiveStorageTables: migrated (0.0126s) ===============

Active Storageが利用する3つのテーブルが作成される。

Active Storageのサービスはconfig/storage.ymlで宣言する。

ローカルDiskサービスをdevelopment環境(開発環境)で使うには、config/environments/development.rbに以下を記述。 (デフォルトはこの設定なので変更する必要なし)

config.active_storage.service = :local
#ファイルをローカルに保存する。

上記の:localconfig/storage.yml内のlocal:の箇所。

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

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

amazon:
  service: S3
  access_key_id: ""
  secret_access_key: ""
  bucket: ""
  region: "" # 例: 'ap-northeast-1'

amazon s3を使用するのであれば、:amazonとする。

ファイルをレコードに添付する

has_one_attached

レコードとファイルの間に1対1のマッピングを設定します。レコード1件ごとに1個のファイルを添付できる。
今回wantモデルに一件の画像を追加したいので、app/models/want.rbhas_one_attached :imageを追記。

class Want < ApplicationRecord
  belongs_to :category
  belongs_to :user
  has_one_attached :image
end

*もしまだモデルを作成していない場合は、$ rails generate model Want image:attachmentを実行。
(今回は既にモデルが作成されているので直接app/models/want.rbhas_one_attached :imageを追記)

<%= form.file_field :image %>で書くことで画像付きのwantを作成できます。

<%= form_with url: wants_path, model: @wants do |form| %>
   <select name="category" >
      <% @categories.each do |category| %> 
          <option value= <%= category.id %> ><%= category.name %></option>
      <% end %>
    </select>

    <%= form.file_field :image %>
    
    <div><%= form.label :商品名 %> <%= form.text_field :name %></div>
    <div><%= form.label :金額 %> <%= form.text_field :money %></div>
    <div><%= form.submit "新規登録" %></div>
  <% end %>

app/controllers/wants.controller.rbprivatewant_params:imageを追加。

private

  def want_params
    params.require(:want).permit(:name, :money, :category_id, :image)
  end

app/controllers/wants_controller.rbWant.create!を変数に入れ、want.image.attach(params[:image])を追記。

def create
    want = Want.create!(
      name: params[:name],
      money: params[:money],
      user_id: current_user.id,
      category_id: params[:category]
    )

    want.image.attach(params[:image])

    redirect_to "/wants"
  end

scheema.rbを削除しrails db:resetrails db:migrate
その後画像をアップロードし% tree storageで画像が保存されているか確認。

% tree storage 
storage
├── m7
│   └── hy
│       └── m7hyoyzztbvzqu5ndqitbbzqqh66
├── py
│   └── 15
│       └── py15yatuw28y0o7yrrkliedqyi62
└── zf
    └── 4l
        └── zf4ll26t6asw1t6bz5lq91argxdn

7 directories, 3 files

rails dbselect * from active_storage_attachments;select * from active_storage_blobs;を確認。
$ tree storageでフォルダに格納されているか確認。

ファイルを表示する

ファイルを表示する方法は2種類ある。
1. リダイレクトモード(※今回はこちらで実行する)
2. プロキシモード

リダイレクトモード

表示したいerbファイルに以下のいずれかを記述することで表示可能。

# どちらでも良い
<img src="<%= url_for(want.image) %>" >

<%= image_tag url_for(want.image) %>

画像のリサイズ

image_processingのgemをインストールする

Gemfileのgem "image_processing", "~> 1.2"コメントアウトを外し、$ bundle installでインストール。
表示したいviewファイルを編集(今回はmy-page.html.erb)

<%= image_tag want.image.variant(resize_to_limit: [100, 100])%>

& brew vipsvipsをインストール