これは神社に関する一連の投稿の第2部です。 このシリーズの記事の目的は、既存のファイルダウンローダーに対するShrineの利点を示すことです。
以前の投稿で、私が神社を創る動機になったことについて話しました。 この記事では、Shrineの基盤であるストレージ、ブートローダー、アップロードされたファイルを紹介します。
保管
Shrineの「リポジトリ」は、特定のストレージサービス(ファイルシステム、S3など)でファイル管理をカプセル化するプレーンなRubyオブジェクトです。 リポジトリには、次の5つのメソッドが含まれている必要があります。
class MyStorage def upload(io, id, **options)
Shrineストレージは直接構成され、オプションをコンストラクター(Refileから借用)に
Shrine.storages
、
Shrine.storages
に登録する必要があります:
Shrine.storages[:s3] = Shrine::Storage::S3.new( access_key_id: "abc", secret_access_key: "xyz", region: "eu-west-1", bucket: "my-bucket", )
Shrineは現在、
ファイルシステム 、
S3 、
Fog 、
Flickr 、
Cloudary 、
Transloadit 、
Uploadcare 、
Imgix 、
GridFSおよび
SQLを サポートしてい
ますので、選択してください。
独自のリポジトリを簡単に作成することもできます。これには、すべてが正しく機能するかどうかを自動的にチェックする
マニュアルと
リンターがあります。
ブートローダー
ローダーはShrineのサブクラスであり、特定の添付ファイル(CarrierWaveなど)をアンロードするロジックをカプセル化します。
class ImageUploader < Shrine
アップローダーオブジェクトは、リポジトリのラッパーとして機能し、すべてのリポジトリに共通するロードのすべてのロジックを実行します。
- 処理中
- メタデータを抽出する
- ファイルの場所を生成する
- ダウンロード(この段階で、リポジトリへのアクセスが発生します)
- ダウンロードしたファイルを閉じる
ストレージオプションセットを使用してブートローダーのインスタンスを作成します。
Shrine.storages[:disk] = Shrine::Storage::FileSystem.new(...) uploader = ImageUploader.new(:disk) uploader.upload(image)
ローダーはモデルについて知りません。 入力にアップロードされるファイルでのみ機能し、ダウンロードされたファイルの表現を出力に返します。 これは、ブートローダーがステートレスであることを示唆しているため、その動作が非常に予測可能になります。
アップロードされたファイル
ブートローダーを介してファイルがダウンロードされると、
#upload
メソッドは
Shrine::UploadedFile
オブジェクトを返します。 このオブジェクトは、リポジトリにアップロードされたファイルの完全な表現です。
uploaded_file = uploader.upload(image)
このオブジェクトはロードされた場所を知っているため、多くの便利なメソッドを提供できます。
uploaded_file.url
このオブジェクトはハッシュによってのみ定義されます。 リポジトリはインストールされたパラメーターで参照できるため、このハッシュはJSONでシリアル化され、データベース列に保存できるようになりました。
uploaded_file.data
Shrine::UploadedFile
オブジェクトはローダーに依存しません。 これは、
CarrierWave::Uploader::Base
および
Paperclip::Attachment
クラスとそのような依存関係を持つCarrierWaveとPaperclipとの大きな違いです。
IOの抽象化
Shrineは、
#size
、
#rewind
、
#eof?
#size
、
#rewind
#read
に応答するタイプ
IO
オブジェクトをロードできます
#eof?
そして
#close
(Refileなど)。 この厳密なインターフェイスを定義することにより、各Shrine関数はこれらのメソッドにのみ依存できることを認識します。つまり、
File
、
StringIO
、
ActionDispatch::Http::UploadedFile
、
Rack
タイプをロードするかどうかに関係なく正しく機能することを意味します。または
ストリームによってダウンロードされる削除されたファイル。
さらに、
Shrine::UploadedFile
自体は
IO
タイプのオブジェクトであり、ダウンロードされたファイルを同じ統一されたインターフェースでラップします。 これにより、ある場所から別の場所にファイルを移動することが非常に便利になります。 さらに、ダウンロードとリロードのプロセスをスキップすることにより、いくつかのダウンロードを最適化することができます。たとえば、両方のファイルがS3からのものである場合はS3のコピーを使用します。
cache = ImageUploader.new(:s3_temporary) cached_file = cache.upload(image) store = ImageUploader.new(:s3_permanent) store.upload(cached_file)
プラグインシステム
Shrineには、必要な機能を提供する小さな
カーネル (500行未満のコード)が付属しています。
プラグインを介して追加機能をダウンロードでき
ます 。 これにより、Shrineが何をどのように行うかを正確に選択し、使用する機能のコードのみをダウンロードする柔軟性が得られます。
Shrineには35を超えるプラグインが付属しており、独自のプラグインを簡単に作成できます。 Shrineプラグインシステムは、以前に
書いた Rodaを改造したものです。
さらに、Shrineローダーを継承できます(
CarrierWaveとは異なります )。
Shrine.plugin :logging
依存関係
ファイルをダウンロードするためのほとんどのライブラリには、かなり巨大な依存関係があります。
搬送波
- ActiveSupport-これらのすべてのデコイパッチがほしくない
- ActiveModel- ライブラリなしで検証を実行してみませんか?
- MIME ::タイプ-ファイルの内容からMIMEタイプを決定することをお勧めします
クリップ
- ActiveSupport-繰り返しますが、おとりパッチを一切持たないようにしたいです
- ActiveModel-わかりました、とにかく、ActiveRecordにはActiveModelとActiveSupportの両方が必要です
- コカイン-Open3 Monstrous Command Shell Library
- MIME ::タイプ-MIMEタイプのスプーフィングの検出に問題があります
- MimeMagic-十分なファイルユーティリティ
整頓
- RestClient-簡単なファイルアップロードのための巨大なソリューション
- Sinatra-これは問題ありませんが、 Rodaはより軽い代替手段です。
- MIME ::タイプ-ファイルの内容からMIMEタイプを決定することをお勧めします
一方、Shrineには必須であるが簡単な依存関係が1つだけあります
-Downです。 Downは、
open-uriを
改善し、ストリーミングをサポートするnet / httpファイルダウンロードラッパーであり、ほとんどすべてのShrineリポジトリで使用されます。
さらに、使用する機能のコードのみをダウンロードするため、Shrineは通常非常に高速でロードされます。 他のローダーの場合、不要な可能性があるすべての機能のコードをダウンロードする必要があります。 たとえば、ShrineはロードされたプラグインなしでCarrierWaveより35倍速くロードされ、すべてのロードされた(
source )プラグインで7倍速くロードされます。
まとめ
各高レベルインターフェイスには、適切な基盤が必要です。 したがって、どのレベルの抽象化を使用しても、何が起こっているのかを常に理解できます。 Shrineの基本は、
Storage
、
Shrine
Shrine::UploadedFile
クラスで構成され、各クラスには明確に定義されたインターフェースと責任があります。
オリジナル: https : //twin.imtqy.com/better-file-uploads-with-shrine-uploader/
著者のブログのオリジナルシリーズの記事: