とあるModelに複数のファイルをAttachさせるときに、
ActiveStorage
の has_many_attached
を使うことはよくあると思いますが、
このとき、
- ファイルに属性を付与したい
- 同じ属性のファイルが既にあるなら削除したい
的な感じの気持ちが溢れ出ると思います。
ので、やります。
class Foo < ApplicationRecord
has_many_attached :bars
end
このクラスで何かをattachします
class Foo < ApplicationRecord
has_many_attached :bars
def attach_bars
bar = 'something' #何らか適当なファイル的なやつ
bars.attach(
io: StringIO.new(bar),
filename: 'なんらかてきとうなふぁいるめい.txt',
content_type: 'text/plain',
metadata: { bar_type: 'something' }
)
end
end
metadata: { bar_type: 'something' }
の部分が何かいい感じのやつで、これで active_storage_blobs.metadata
に "bar_type": "something"
な感じでデータが保持されるようになります。やったね。
これで属性付与できたので、 bars
の中で bar_type == 'something'
なattachmentを削除したい場合は、
foo = Foo.find(xxx)
foo.bars.select {|bar| bar.metadata[:bar_type] == 'something' }
.each {|bar| bar.purge }
みたいな感じでpurgeすることはできるんですが、仮に bars
が100件とか200件とかなってきたらウザウザなので、事前にクエリで絞り込む的なことがしたくなりました。
というわけで、しました。
foo.bars.joins(:blob).where(
"`active_storage_blobs`.`metadata`->>'$.bar_type' = ?", 'something'
).each { |bar| bar.purge }
やったね!