読者です 読者をやめる 読者になる 読者になる

何もしないファイルアップローダーTori

Toriというgemを書いた。

ToriはPaperclipCarrierwaveなどと同じくファイルのアップローダ

ファイルアップローダは機能が豊富だったりする反面、ハマることが多かったり結局コードを読むことになるけど、機能豊富がゆえコード量に気が滅入ったりする。

そこで新しいファイルアップローダを考えた。

というか既にあるものからできるだけ機能を削った。

目指した特徴は「なにもしない」こと。

極限までシンプルなものを目指した。

画像処理をしない

昨日書いた通り、画像処理をアプリケーションサーバでやるのはイマイチだ。

だったらファイルアップローダに画像処理機能はいらない。

アップロード時だろうがアクセス時だろうが一切何もしない。

imagemagickにも依存しない。

DBに専用カラムを用意しない

PaperclipやCarrierwaveではファイル名を決めるためにDBに専用のカラムを用意しなければならない。

新規作成するアプリには問題ないが、既存のシステムにファイルアップロード機能を付けたい場合には導入をためらうキッカケになる。

そこで、ToriではDBに専用のカラムを追加する必要をなくしている。

ファイル名の決定はユーザ側が任意にロジックを決定できるようにした。

ファイル名の遅延決定

ファイル名の決定ロジックを設定で変更できる。

デフォルトはこう。

Tori.config.filename_callback = ->(model) do
  Digest::SHA1.hexdigest "#{model.class.name}/#{model.id}"
end

このブロックがファイル名を取得したいときに呼ばれる。 modelはToriを使いたいclass(Railsで言えばActiveRecord::Base)のインスタンスを渡すようになっていて、遅延評価で決定できる。つまりはDBのidからファイル名を決定できる。

ファイル名の決定ロジックを後から設定で変更できるので、コードを公開しなければファイル名を特定するは非常に困難になる。 このへんの考えはというかほとんどのコードはRefileからパクって参考にしている。

Hashingしたくなければ変えられるし、MD5を使いたければ設定すればいい。 MurmurHashSiphashアルゴリズムを使いたい? 僕がすでに書いている。(宣伝)

callbackはcallメソッドを持っていればなんでもいい。

ファイルの保存場所

ファイルの保存にはまだマシンローカルにしか対応していないけど、S3にも標準対応を目指している。 この保存場所も設定で変更可能になっているし、なんならプラグイン的にclassを書ける。

設定は

Tori.config.backend = GodStorage.new

保存時は

Tori.config.backend.copy(from_filename, to_filename)

削除時は

Tori.config.backend.delete(filename)

と呼べばいい。

ちなみにRailsではGemfileで

gem 'tori', require: 'tori/rails'

としておけば自動的にafter_saveafter_destoryにフックして 自動でストレージに保存したり削除する仕掛けになっている。

コード量

小さいのでハマる確率は低いと思われるが、開発者フィルターがふんだんにかかっている。

全部で140行ぐらいなので読める範囲だと思う。

詳しくはksss/toriで。

リスク

僕の気分次第で仕様が変わる。

なにもしないので何も紹介できることがない。

まとめ

"(\( ⁰⊖⁰)/)"