JQ Blog

Active Storage

Rails5.2の新しい機能の中にActive Storageというものが気になったので使ってみた。

Active Storageとは

AWS S3やGoogle Cloud Storageなどのクラウドファイルストレージサービスへのアップロードをシンプルにやってくれる仕組みとのこと。
もちろん物理的なディスクシステムへ保存することもできるけど、主眼はあくまでクラウドサービスに置いているらしい。

Modelの仕組

Active Storageをインストールするとactive_storage_blobs,active_storage_attachmentsが生成される。

active_storage_blobsmetadata (filename, content-type, etc.)を保存するtableになっている。keyカラムはidentifier keyとしてクラウドファイルストレージのアップするファイルのfilenameになる。

active_storage_attachmentsは添付ファイルの親モデルとactive_storage_blobsをアソシエートしてくれる。親モデルはpolymorphicになる。

使い方

  • 環境
    • Rails 5.2.0.beta2
    • ruby 2.4.1p111

インストール

rails newを通してプロジェクトを作成するとき自動的にActive Storageがインストールされる。
rails new --skip-active-storageにするとインストールせずにプロジェクトを作成できる。

既存プロジェクトにActive Storageを入れたい場合は、まずRailsのバージョンをアップグレードしてから、

1
2
rails active_storage:install
bundle exec rake db:migrate

で入れることができる。

サンプルコード

  • gemfile
1
2
gem 'mini_magick', '~> 4.8' # 画像の加工のために
gem 'aws-sdk-s3' # S3へのアップロード
  • model
1
2
3
4
class User < ApplicationRecord
  has_one_attached :avatar # has_oneの場合
  has_many_attached :images # has_manyの場合
end
  • controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class UsersController < ApplicationController
  def create
    @user = User.new(user_params)

    ActiveRecord::Base.transaction do
      render :new and return unless @user.save

      if (avatar = params[:user][:avatar]).present?
        @user.avatar.attach(avatar)
      end

      if (images = params[:user][:images]).present?
        @user.images.attach(images)
      end
    end

    redirect_to users_path
  end
end
  • view
1
2
3
4
5
6
7
8
9
10
11
12
13
14
= form_for @user do |f|
  = f.label :name
  = f.text_field :name
  br
  = f.label :email
  = f.email_field :email
  br
  = f.label :avatar
  = f.file_field :avatar
  br
  = f.label :images
  = f.file_field :images, multiple: true # has_manyの場合
  br
  = f.submit "作成"

クラウド設定

  • config/environments/development.rb
1
2
# Store uploaded files on the local file system (see config/storage.yml for options)
config.active_storage.service = :amazon
  • config/storage.yml
1
2
3
4
5
6
7
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
amazon:
  service: S3
  access_key_id: <%= ENV['AWS_ACCESS_KEY'] %>
  secret_access_key: <%= ENV['AWS_SECRET_KEY'] %>
  region: <%= ENV['AWS_REGION'] %>
  bucket: <%= ENV['AWS_BUCKET'] %>

リサイズ

1
= image_tag @user.avatar.variant(resize: '200x200')

このようにvariantメソッドを使えばリサイズでビューに表示できる。
参照:https://github.com/rails/rails/blob/master/activestorage/app/models/active_storage/variant.rb

Direct upload

JSを使ってDirect uploadすることもできる。

  • include activestorage.js

    • asset pipelineの場合
    //= require activestorage
    
    • npm packageの場合
    import * as ActiveStorage from "activestorage"
    ActiveStorage.start()
    
  • file_fieldに設定

    • ビューの file_field に direct_upload: true を入れる
    = f.file_field :avatar, direct_upload: true
    

サンプル

https://active-storage-jo.herokuapp.com

参考

https://qiita.com/nashirox/items/e63fd28d974ecf12f0e7
https://github.com/rails/rails/tree/master/activestorage