最近、ファイルアップロード用のgemであるShrine
を使用する機会があったんですが、Uploader別にアップロード先を設定する方法が全然見つからず、だいぶハマってしまったので、やり方をφ(..)メモメモ
とりあえず公式のQuick startを見てみる
Shrine.storage
に各Uploaderが共通で使用するストレージを情報を設定できる。
config/initializers/shrine.rb
require "shrine" require "shrine/storage/file_system" Shrine.storages = { cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # temporary store: Shrine::Storage::FileSystem.new("public", prefix: "uploads/store"), # permanent } Shrine.plugin :sequel # or :activerecord Shrine.plugin :cached_attachment_data # for retaining the cached file across form redisplays Shrine.plugin :restore_cached_data # re-extract metadata when attaching a cached file Shrine.plugin :rack_file # for non-Rails apps
共通のアップロード先にアップロードするだけだったら、簡単で使いやすい😃
アップロード先を個別に設定する
Quick startを見てみるとShrine.strages
にアップロード先の情報を設定されているため、この値を変更する必要があるっぽい。
でも単純にShrine.strageを変更すると、画像アップロード処理全体に影響してしまう...😭
各クラスにShrine.strages
がなぜ反映されているか?
Shrine.starages
はグローバル変数みたいな感じで定義されていて、それを参照しているのかと思ったけど、
どうやらサブクラスのクラスインスタンス変数としてdup
でコピーされた値が反映されているっぽい😳
https://github.com/shrinerb/shrine/blob/master/lib/shrine.rb#L101
class Shrine @storages = {} module Base # 省略 subclass.instance_variable_set(:@storages, storages.dup)
各Uploaderクラスに個別でアップロードパスを設定するには?
サブクラスのクラスインスタンス変数として設定されているということは、こんな感じでUploader別に設定出来るのでは?? 👀
class HogeImageUploader < Shrine @storages = { cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/hoge/cache"), # temporary store: Shrine::Storage::FileSystem.new("public", prefix: "uploads/hoge/store"), # permanent }
image_url
も変わってる、できたっぽい🙌
# 個別の設定が使用されている [1] pry(main)> HogeImage.first.image_url => "/uploads/store/hoge/hogehoge.png" # 共通設定が使用されている [2] pry(main)> FugaImage.first.image_url => "/uploads/store/fugafuga.png"
S3のバケットを使う場合でも同じように個別に設定してあげればOKみたいです😃
class HogeImageUploader < Shrine s3_options = { bucket: "my-bucket", # required access_key_id: "abc", secret_access_key: "xyz", region: "my-region", } @storages = { cache: Shrine::Storage::S3.new(prefix: "cache", **s3_options), store: Shrine::Storage::S3.new(**s3_options), }
2018/06/03追記
default_strage
pluginをつかっても下記のような感じで出来るみたいですφ(..)
require "shrine" require "shrine/storage/file_system" Shrine.storages = { cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # temporary store: Shrine::Storage::FileSystem.new("public", prefix: "uploads/store"), # permanent special_cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # temporary special_store: Shrine::Storage::FileSystem.new("public", prefix: "uploads/store"), # permanent } Shrine.plugin :sequel # or :activerecord Shrine.plugin :cached_attachment_data # for retaining the cached file across form redisplays Shrine.plugin :restore_cached_data # re-extract metadata when attaching a cached file Shrine.plugin :rack_file # for non-Rails apps
class HogeImageUploader < Shrine plugin :default_storage, cache: :special_cache, store: :special_store end