Rails5.2から登場したActive Storageですが、Rails6.0になっていくつかの変更があったのでまとめました。
1. 画像形式のBMP
とtiff
とpjepg
をサポート
Active Storageがサポートする画像形式に、以下の3つが追加されました。
1-1. BMP
Windows端末で標準的な画像の保存形式です。画像を点の集まりとして記録しています。
拡張子は.bmp
です。
1-2. tiff
Tagged Image File Format
の略で、ビットマップ画像の符号化形式の一つです。 タグと呼ばれる識別子を使うことによって、様々な形式のビットマップ画像を柔軟に表現できます。
拡張子は.tif
または.tiff
です。
1-3. progressive JPEG
まずイメージ全体を荒い低解像度で表示し、徐々に細かい高解像度で表示していく方式のJPEGです。
拡張子は.jpg
または.jpeg
です。
2. Active Storageが生成するroutesのprefixが指定可能に
Rails5.2までは、Active Storageが生成するroutesのprefixは/rails/active_storage
で固定でしたが、Rails6.0では任意のprefixが設定できるようになりました。
2-1. デフォルトの場合
$ bundle exec rails routes -c active_storage
Prefix Verb URI Pattern Controller#Action
rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update
rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
2-2. prefixに/files
を指定した場合
module RailsApp
class Application < Rails::Application
...
config.active_storage.routes_prefix = '/files'
end
end
$ bundle exec rails routes -c active_storage
Prefix Verb URI Pattern Controller#Action
rails_service_blob GET /files/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
rails_blob_representation GET /files/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
rails_disk_service GET /files/disk/:encoded_key/*filename(.:format) active_storage/disk#show
update_rails_disk_service PUT /files/disk/:encoded_token(.:format) active_storage/disk#update
rails_direct_uploads POST /files/direct_uploads(.:format) active_storage/direct_uploads#create
3. アップロードしたファイルがストレージに保存されるタイミングがsave時に変更
Rails5.2までは、インスタンスのattributeに代入した時点で、アップロードしたファイルがストレージに保存されていました。
Rails6.0では、saveしたタイミングでストレージに保存されるよう変更になっています。saveトランザクションがコミットされた後に、ストレージに保存されます。
3-1. Rails5.2まではインスタンスのattributeに代入したタイミング
@user.avatar = params[:avatar]
3-2. Rails6.0ではsaveしたタイミング
@user.save!
4. ActiveStorage::Reflection
モジュールが追加
新たに追加されたActiveStorage::Reflection
モジュールのreflect_on_all_attachments
やreflect_on_attachment
といったメソッドを使うことで、定義されたattachmentsの情報を取得することができます。
class User < ApplicationRecord
has_one_attached :avatar
has_many_attached :highlights
end
このようなUserモデルがあった場合、ActiveStorage::Reflection#reflect_on_attachment
メソッドとActiveStorage::Reflection#reflect_on_all_attachments
メソッドを使うと、それぞれ以下のような挙動になります。
4-1. ActiveStorage::Reflection#reflect_on_attachment
reflection = User.reflect_on_attachment(:avatar)
# => #<ActiveStorage::Reflection::HasOneAttachedReflection:0x00007f9e26c37460 @name=:avatar, @scope=nil, @options={:dependent=>:purge_later}, @active_record=User (call 'User.connection' to establish a connection), @klass=nil, @plural_name="avatars">
reflection.name
# => :avatar
reflection.macro
# => :has_one_attached
4-2. ActiveStorage::Reflection#reflect_on_all_attachments
reflections = User.reflect_on_all_attachments
=> [#<ActiveStorage::Reflection::HasOneAttachedReflection:0x00007fbedcaf9608 @name=:avatar, @scope=nil, @options={:dependent=>:purge_later}, @active_record=User (call 'User.connection' to establish a connection), @klass=nil, @plural_name="avatars">, #<ActiveStorage::Reflection::HasManyAttachedReflection:0x00007fbedcab50c0 @name=:highlights, @scope=nil, @options={:dependent=>:purge_later}, @active_record=User (call 'User.connection' to establish a connection), @klass=nil, @plural_name="highlights">]
reflections[0]
=> #<ActiveStorage::Reflection::HasOneAttachedReflection:0x00007f9e26c37460 @name=:avatar, @scope=nil, @options={:dependent=>:purge_later}, @active_record=User (call 'User.connection' to establish a connection), @klass=nil, @plural_name="avatars">
reflections[0].name
=> :avatar
reflections[0].macro
=> :has_one_attached
reflections[1]
=> #<ActiveStorage::Reflection::HasManyAttachedReflection:0x00007fbedcab50c0 @name=:highlights, @scope=nil, @options={:dependent=>:purge_later}, @active_record=User (call 'User.connection' to establish a connection), @klass=nil, @plural_name="highlights">
reflections[1].name
=> :highlights
reflections[1].macro
=> :has_many_attached
5. ActiveStorage::Blob#open
メソッドが追加、ActiveStorage::Downloading
モジュールが非推奨
ActiveStorage::Blob#open
というメソッドが追加されました。
blobをアップロード後に、何かしら処理を加えたい場合に使います。
blobをtmpファイルとして保持しており、ウイルススキャンやメディアトランスコーダによる変換など、外部プログラムを使った処理を実行することもできます。
message.video.open do |file|
system '/path/to/virus/scanner', file.path
# ...
end
また、元々このような形で使う想定で用意されていたActiveStorage::Downloading
モジュールが非推奨になっています。
6. Google Cloud Storageのストリーミングダウンロードをサポート
google-cloud-storage
gemのバージョンが、1.8以上から1.11以上に引き上げられました。
これにより、ストリーミングダウンロードに対応するようになりました。
7. image_processing
gemの導入
ファイルを変換するためのgemが、mini_magick
からimage_processing
に変更されました。
image_processing
はmini_magick
とruby-vips
のwrapperで、画像のリサイズや加工を行います。
Rails 6.0.0.rc1では、Gemfileにおいてデフォルトでコメントアウトされています。
# Use Active Storage variant
# gem 'image_processing', '~> 1.2'
コメントアウトを外して、bundle install
しましょう。
8. 既存の画像を置き換え
アタッチされたモデルをupdate
またはupdate!
で更新すると、新たに画像を追加するのではなく既存の画像を置き換えます。
@user.update!(images: [ … ])