@kyanny's blog

My thoughts, my life. Views/opinions are my own.

Dragonfly を学ぶ

仕事で markevans/dragonfly · GitHub を使っているが、すでに導入・運用済みのものをなんとなく利用しているだけで、どのように使うのか・どのように動作するのかが自分の中で腑に落ちていないことに気づいたので、 http://markevans.github.io/dragonfly/ を読みながら動作する最小のコードを書いて学んだ。

https://github.com/kyanny/playground/tree/gh-pages/ruby-dragonfly

  • Dragonfly はコンテンツの保存と配信を司るライブラリで、 Rails エコシステムにおける carrierwave や paperclip と似た存在だが、独立して利用することもできる
  • Dragonfly.app で Dragonfly のインスタンスを得る。このインスタンスを通じてコンテンツに対し各種操作を行う
  • Dragonfly.app.store でコンテンツをバックエンドのストレージに保存する。 store は uid を返し、これがストレージ内でコンテンツを一意に特定するキーとなる。通常この uid をデータベースに保存しておく。ストレージは設定により複数から選べる(メモリ、ファイルシステム、 Amazon S3 など)
  • Dragonfly.app.fetch に uid を渡すと Job オブジェクトというものが得られる。これは Dragonfly がコンテンツをラップしたオブジェクトで、コンテンツの属性(mime type など)を得たり、コンテンツの種類によっては動的な変換処理を施すこともできる
  • Job オブジェクトに対して #url というメソッドを呼び出すと、そのコンテンツを配信するための長くて一意な URL が得られる。こんなの http://localhost:9292/W1siZiIsIjIwMTUvMDkvMTgvMzhnd2phY3pzMl9sZW5hX3N0ZC5wbmciXV0
  • コンテンツを配信するウェブアプリケーションは、 uid をパラメータで受け取るように実装してもよい(その場合は内部で #fetch したあと適切な HTTP ヘッダを付与してコンテンツを返すような実装も書かなければならない)
  • そういう処理を毎度自分で書かなくて済むように、 Dragonfly.app は Rack アプリケーションとして動作し、 Job オブジェクトが #url で返した URL へアクセスしたとき対応するコンテンツを配信してくれるようになっている
  • Dragonfly.app.fetch_url メソッドを使うと指定した URL からコンテンツを取得して再配信できるので、バックエンドストレージ無しのコンテンツ配信プロキシサーバとしても動作する
  • Dragonfly はプラグイン機構や設定が充実していて、標準で ImageMagick プラグインが利用できるので、画像ファイルを配信時に動的に変換することができる(任意のサイズのサムネイル画像を配信する、など)