- shrineとは
公式サイトには
Shrine is a toolkit for file attachments in Ruby applications.
と書いてある。つまり、ShrineはRubyアプリケーションにおいてファイルをアタッチするために使えるツールキットである。
- 使い方
- gemのインストール
gem 'shrine'
- 初期設定
# 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 :activerecord Shrine.plugin :cached_attachment_data # for forms
- Model
class Photo < ApplicationRecord include ImageUploader[:image] end
- Uploader
class ImageUploader < Shrine end
- Controller
Controllerのparamはimage_data
ではなく、image
にする。
def photo_params params.require(:photo).permit(:name, :image) end
ビューを作ってブラウザーで確認してみると、
大きすぎる。。!!
リサイズ
リサイズのためには他のgemをインストールする必要がある。- gemのインストール
gem 'image_processing' gem 'mini_magick', '>= 4.3.5'
- Uploader編集
require 'image_processing/mini_magick' class ImageUploader < Shrine include ImageProcessing::MiniMagick plugin :processing plugin :versions # enable Shrine to handle a hash of files plugin :delete_raw # delete processed files after uploading process(:store) do |io, context| original = io.download size_800 = resize_to_limit!(original, 800, 800) { |cmd| cmd.auto_orient } # orient rotated images size_500 = resize_to_limit(size_800, 500, 500) size_300 = resize_to_limit(size_500, 300, 300) {original: io, large: size_800, medium: size_500, small: size_300} end end
- ビューで表示する ビューでサイズ別の画像を取得できる。
= image_tag, @photo.image[:original].url = image_tag, @photo.image[:large].url} = image_tag, @photo.image[:medium].url}" = image_tag, @photo.image[:small].url}"
ビューで確認すると、
バリデーションの追加
Uploadにバリデーションをかけるのももちろんできる。
validation_helpers
のプラグインを追加し、バリデーションを追加する。
バリデーションの処理はAttacher.validate
の中に記述する。- Uploaderの編集
require 'image_processing/mini_magick' class ImageUploader < Shrine include ImageProcessing::MiniMagick plugin :processing plugin :versions # enable Shrine to handle a hash of files plugin :delete_raw # delete processed files after uploading plugin :validation_helpers process(:store) do |io, context| original = io.download size_800 = resize_to_limit!(original, 800, 800) { |cmd| cmd.auto_orient } # orient rotated images size_500 = resize_to_limit(size_800, 500, 500) size_300 = resize_to_limit(size_500, 300, 300) {original: io, large: size_800, medium: size_500, small: size_300} end Attacher.validate do validate_max_size 5 * 1024 * 1024, message: 'Image is too large (max is 5 MB)' validate_mime_type_inclusion %w(image/jpeg image/jpg image/png) end end
バリデーションにかかったら
photo = Photo.new photo.image = File.open("img.png") photo.valid? #=> false photo.errors.to_hash #=> {image: ["Image is too large (max is 5 MB)"]}
- Direct uploads
- gemのインストール
gem 'aws-sdk', '~> 2.1' gem 'roda'
- config/initializers/shrine.rbファイルの編集
require "shrine/storage/s3" s3_options = { access_key_id: "abc", secret_access_key: "123", region: "my-region", bucket: "my-bucket", } Shrine.storages = { cache: Shrine::Storage::S3.new(prefix: "cache", **s3_options), store: Shrine::Storage::S3.new(prefix: "store", **s3_options), }
- Uploaderにpluginの追加
plugin :direct_upload
- routes.rbに
mount
追加
Rails.application.routes.draw do mount ImageUploader::UploadEndpoint => "/images" end
- jsonの取得
GET /images/cache/presign
のrouteでjsonを取得できる。# GET /images/cache/presign { "url" => "https://my-bucket.s3-eu-west-1.amazonaws.com", "fields" => { "key" => "cache/b7d575850ba61b44c8a9ff889dfdb14d88cdc25f8dd121004c8", "policy" => "eyJleHBpcmF0aW9uIjoiMjAxNS0QwMToxMToyOVoiLCJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJzaHJpbmUtdGVzdGluZyJ9LHsia2V5IjoiYjdkNTc1ODUwYmE2MWI0NGU3Y2M4YTliZmY4OGU5ZGZkYjE2NTQ0ZDk4OGNkYzI1ZjhkZDEyMTAwNGM4In0seyJ4LWFtei1jcmVkZW50aWFsIjoiQUtJQUlKRjU1VE1aWlk0NVVUNlEvMjAxNTEwMjQvZXUtd2VzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LHsieC1hbXotYWxnb3JpdGhtIjoiQVdTNC1ITUFDLVNIQTI1NiJ9LHsieC1hbXotZGF0ZSI6IjIwMTUxMDI0VDAwMTEyOVoifV19", "x-amz-credential" => "AKIAIJF55TMZYT6Q/20151024/eu-west-1/s3/aws4_request", "x-amz-algorithm" => "AWS4-HMAC-SHA256", "x-amz-date" => "20151024T001129Z", "x-amz-signature" => "c1eb634f83f96b69bd675f535b3ff15ae184b102fcba51e4db5f4959b4ae26f4" } }
こう設定すると、ひとまずs3にdirect_uploadはできる。
公式documentにはjQuery-File-Upload
, Dropzone
, FineUploader
などのJavaScriptファイルアップロードライブラリとも連携もできると書いてあるので、次は今のプロジェクトで使用しているDropzone
との連携を調べてみる。
参照
Shrine githubページ
RailsでShrineを使ってファイルをS3にダイレクトアップロードするときの注意点
Shrineを使って画像をアップロードする