はじめに
こんにちは、onoです。
以前、CarrierWaveを使って画像をアップロードするフォームを作成しました。
CarrierWaveは多機能で使いやすいGemだと思いますが、コードが大きく複雑なため、一般的な使い方から外れた場合や問題が発生した場合に処理を追っていくのが大変です。
そこで、今回は実装がシンプルで必要な機能を選んで追加できるShrineを使ってみます。
Shrineとは
簡単な説明
Shrineはファイルをアタッチするためのツールです。
主に画像をアップロードする際に利用されるのではないかと思います。
作者
ShrineはJanko Marohnić氏(リポジトリはこちら)が2015年9月から開発しています。
特徴
主な特徴としては下記の2つが挙げられます。
- Shrine本体は必要最小限の機能のみを実装しているため、シンプルでコードが小さい。
- リサイズやダイレクトアップロードなど、必要な機能のみをプラグインで追加できる。
下準備
Gemを追加
プロジェクトを作成後、Gemfileに下記のGemを追加します。
1 | gem 'shrine' |
初期設定
画像をアップロードするディレクトリの指定と使用するプラグインを宣言します。
アプリケーション全体で共通の設定は、config/initializers/で行います。
1 2 3 4 5 6 7 8 9 10 11 12 | 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 :activerecord Shrine.plugin :cached_attachment_data # for forms |
テーブルを作成する
アップロードした画像を管理するテーブルを作成します。
アップロードした画像の情報を保存するカラムはtext型の「xxx_data」という名前にします(xxxはモデルの中でアップローダをアタッチする際に指定するシンボル名)
1 2 3 4 5 6 7 8 9 10 | class CreatePhotos < ActiveRecord::Migration[5.0] def change create_table :photos do |t| t.string :name, limit: 16, null: false t.text :image_data, comment: '「アップローダに渡すシンボル名_data」とい名前にする' t.timestamps end end end |
実装
Uploaderの実装
モデルにアタッチするアップローダを実装します。
特にディレクトリに指定はありませんが、app/uploaders/に追加していきます。
1 2 | class ImageUploader < Shrine end |
Modelの実装
実装したアップローダをアタッチします。
1 2 3 4 5 | class Photo < ApplicationRecord include ImageUploader[:image] validates :name, presence: true, length: { maximum: 16 } end |
Controllerの実装
下記の通り、scaffoldで生成したコードの一部を修正します。
1 2 3 4 5 6 7 | def photo_params # before params.require(:photo).permit(:name, :image_data) # after params.require(:photo).permit(:name, :image) end |
Viewの実装
画像をアップロードするフォームを実装します。
アップロードした画像のアドレスはxxx_urlで取得できます(xxxはモデルの中でアップローダをアタッチする際に指定するシンボル名)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <%= form_for(photo) do |f| %> <!--省略--> <div class="field"> <%= f.label :name %> <%= f.text_field :name %> </div> <div class="field"> <%= f.label :image_data %> <% if photo.cached_image_data.present? %> <!--バリデーションに失敗した場合、ここで画像を表示する--> <%= image_tag photo.image_url %> <% end %> <%= f.hidden_field :image, value: photo.cached_image_data %> <%= f.file_field :image %> </div> <div class="actions"> <%= f.submit %> </div> <% end %> |
インサートされるレコード
フォームから画像をアップロードして保存すると、下記のようなレコードがインサートされます。
1 2 3 4 5 6 7 | mysql> select * from photos; +----+------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+---------------------+ | id | image_data | created_at | updated_at | +----+------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+---------------------+ | 4 | {"id":"01ebba4bae62c5fb1ecd136224f9d1dd.jpg","storage":"store","metadata":{"filename":"1182774.rsz.jpg","size":2989,"mime_type":"image/jpeg"}} | 2017-04-16 11:41:19 | 2017-04-16 11:41:19 | +----+------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+---------------------+ 1 row in set (0.00 sec) |
さいごに
今後はプラグインを追加して、ファイル名の変更、リサイズ、サムネイルの作成などを行なっていきます。