概要
ひょんなことから、画像をアップロードする処理を書くことになりました。
これまで、Railsで画像アップロードといえば、CarrierWave
やPaperclip
を使っておけば良いでしょ〜!くらいに思ってたんですが、せっかくRails5.2を使っているのであれば、Active Storage
を使ってみよう!と思ったので、
今回はRails5.2でActive Storageの使った画像のアップロードの方法をまとめます。
なぜActiveStorageなのか
今回のアップロード機能の要件は至極単純でした。
- あらかじめ、特定のフォルダに画像データが配置されている
- 上記の画像データを特定のモデルにバッチで添付する
- アップロードされた画像はオリジナルサイズで閲覧ができる
ただこれだけでした。
サムネイル作成などのファイルの変換、バリデーション、セキュリティなどなど、ガン無視でOKみたいな。
そのため、CarrierWave
、Paperclip
は、やや機能過多感があるため、今回はActive Storage
に決定しました。
また、Active Storage
の特徴を抜粋すると下記の通りです。
- DBにファイルのメタ情報と中間テーブルを用意することによって、既存のテーブルにカラムを追加しなくても良い => スキーマの変更が柔軟にできそう
- レコード:ファイルが1:1にも1:多にもできる
- 既存モデルには
has_one_attached :name
と書くだけ。 - 時間制限付きURLを楽に生成できる
今回の要件に置いてはこの機能があれば十分ですね。
Getting start
railsguides.jp ここ読めばGetting startできるわけですが、コマンドとかをまとめようと思います。
config/storage.ymlの編集
どこに保存すんの?という設定を書きます。
test: service: Disk root: <%= Rails.root.join("tmp/storage") %> local: service: Disk root: <%= Rails.root.join("storage") %> amazon: service: S3 access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> region: us-west-2 bucket: bucketname
amazonのところの書いた<%= Rails.application.credentials.dig(:aws, :access_key_id) %>
については、Rails 5.2からのcredential管理の方法で設定した値を使います。
詳細はこちらの記事を参照してください。
config/environments/development.rb
config/storage.yml
に設定したawsの設定を反映するために、config/environments/development.rbを修正します。
# Store uploaded files on the local file system (see config/storage.yml for options) # config.active_storage.service = :local config.active_storage.service = :amazon
モデルにファイル添付する設定を書く
冒頭で紹介した通り、1レコードにつき1ファイルだけ添付するのであれば、下記設定のみです。
class User < ApplicationRecord has_one_attached :avatar end
ファイルの添付と確認
ファイルの添付と確認はrails consoleで確認します。
$ cd rails_root $ bin/rails c user = User.first user.avatar.attached? #=> false filepath = File.join(Dir.home, 'filename.jpg') user.avatar.attach( io: File.open(filepath), filename: File.basename(filepath), content_type: 'image/jpg' ) user.avatar.attached? #=> true # アプリケーションを指すblobの永続URLを生成 include(Rails.application.routes.url_helpers) default_url_options[:host] = 'localhost:3000' url_for(user.avatar) #=> "http://localhost:3000/rails/active_storage/blobs/09Iiw63f495IkJ09IiwkJ09Iiw6IkJBaH19--7209IiwiZXxsLCJwdXIiOiJibG9iX2lkIn19--726eT09IiwbeaHBEUT09Iiwbe29513f4943f49513f49e4a9c55b4af76f5/filename.jpg"
上記の生成されたURLにアクセスすると画像を閲覧することができます。
まとめ
簡単な設定情報と、モデルにhas_one_attached
という記述を追加するだけでファイルのアップロード機能を作ることができました。さすがRailsですね。
要件によってはリサイズしなければならなかったり、バックグラウンドで処理しなければならなかったりするので、Gemを使うことを検討しなければならないのですが、今回は要件が少なかったため、Active Storageで十分でした。