大阪でRailsを中心に学習しているヨマ(@yoma_2003)です!
「ActiveStorageで、保存する前に画像を縮小する方法」をまとめます。
※おことわり※
断定口調でまとめますが、初学者であるため間違い等あればご指摘頂けると嬉しいです。
はじめに
やりたいこと
ActieStorageでAmazon S3等に画像を保存する場合に、指定のサイズ以下に画像を縮小してから保存したい。
必要環境
画像処理のためのツール、Gemの導入。
- ImageMagick:画像加工ツール(本番環境ではサーバーにもインストールする)
- Minimagick:ImageMagickをRubyから使えるようにするGem
- ImageProcessing:画像サイズを調整するGem
結論
コントローラーに渡されたパラメーター内の画像ファイル(ActionDispatch::Http::UploadedFile
のtempfile
)を、Imageprocessing::MiniMagick
を利用して縮小処理して置き換えてからインスタンスを作成する。
モデル
class Post < ApplicationRecord
has_one_attached :image
end
ビュー
<%= form_with model: @post, local: true do |f| %>
<%= f.text_field :name %>
<%= f.file_field :image %>
<%= f.submit "投稿する" %>
<% end %>
コントローラー
class PostsController < ApplicationController
# indexアクション、newアクション、editアクションは省略
def create
@post = Post.new(image_resize(post_params))
if @post_comment.save
redirect_to root_path
else
render :new
end
end
def update
@post = Post.find(params[:id])
if @post.update(image_resize(post_params))
redirect_to root_path
else
render :edit
end
end
private
def post_params
params.require(:post).permit(:name, :image)
end
def image_resize(params)
if params[:image]
params[:image].tempfile = ImageProcessing::MiniMagick.source(params[:image].tempfile).resize_to_limit(500, 500).call
end
params
end
end
解説
パラメーター内の画像ファイルを縮小して置換するメソッドを定義
「パラメーターの内容自体を置換する」という処理がRailsのセオリー的にどうなのか不明ですが、アクション内の記述をほとんど変えずにそのまま代入できるので、以下の様にしました。
def image_resize(params)
if params[:image]
params[:image].tempfile = ImageProcessing::MiniMagick.source(params[:image].tempfile).resize_to_limit(500, 500).call
end
params
end
画像ファイルの場所
アップロードされた画像ファイルは、パラメーター内のimageカラムで、ActionDispatch::Http::UploadedFile
のtempfile
にバイナリファイルとして格納されている。
pry(#<PostsController>)> post_params
=> <ActionController::Parameters {
"name"=>"a",
"image"=>
#<ActionDispatch::Http::UploadedFile:0x00007faf175307c8
@tempfile=#<Tempfile:/var/folders/mf/abcde1234500000/T/RackMultipart20220831-21205-pnm0r4.jpg>,
@original_filename="test.jpg",
@content_type="image/jpeg",
@headers="Content-Disposition: form-data; name=\"post[image]\"; filename=\"test.jpg\"\r\nContent-Type: image/jpeg\r\n">
} permitted: true>
縮小する処理
ImageProcessing::MiniMagick
モジュールの機能を使用して画像ファイルを縮小する。
ImageProcessing::MiniMagick.source(params[:image].tempfile).resize_to_limit(500, 500).call
おわりに
ImageProcessing::MiniMagickモジュールでは他にも簡単に画像処理ができるメソッドがいくつか用意されているのでこの形の用途はいろいろとありそうです。
参考