Rails5.2で導入されるActive Storageをのぞいてみる（本家ファイルアップローダー）


## はじめに
某所で、Rails5.2よりクラウドファイルストレージサービスへのアップロード機能が導入されると聞きました。
この機能は[CarrierWave + fogの組み合わせ](http://qiita.com/ryo-ichikawa/items/a30dc626cba1ec909d57)でよく実装するので、楽になったらいいなぁと思い、（多分）来年リリースの新機能ではありますが[リポジトリ](https://github.com/rails/activestorage)を眺めてみた結果のチラ裏です。

DHHもアナウンスしていますね。
見落としていました


<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">Active Storage is coming to Rails 5.2: A brand-new framework for managing cloud and local files in Rails. Overdue! <a href="https://t.co/BFF4kWesT6">https://t.co/BFF4kWesT6</a></p>&mdash; DHH (@dhh) <a href="https://twitter.com/dhh/status/882965074767474688">2017年7月6日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>


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

※ お断り
以下は、もりもり開発している途中のコードを眺めて書き散らしたチラ裏です。
Active Storageに関する日本語記事がほぼなかったので、これくらいでもお役に立てるかなと思い公開しています。
記事執筆時点から仕様が変わる可能性はありますので、あらかじめご了承ください。

## 使用準備
### インストール
`application.rb`に`require 'active_storage'`を追加する

```diff:config/application.rb
require 'rails/all'
+ require 'active_storage'
```

その後、インストールコマンドを実行する。

```sh
$ rails activestorage:install
```

実行後、[記事執筆時点](https://github.com/rails/activestorage/blob/6dcdc5c9abb8e4e93a2c582b11ff4bb77d62ed3b/lib/tasks/activestorage.rake)では次のようになるみたいです。

- storageディレクトリが生える
	- `/storage`
	- `/tmp/storage`
- 設定ファイル出現
	- `/config/storage_services.yml`
- マイグレーションファイル出現
	- `db/yyymmddhhmmss_active_storage_create_tables.rb`


### 設定ファイル
クラウドファイルストレージサービスの鍵やバケットなどの情報を記述しておくとこです。
秘匿情報は、Rails 5.1から導入されたEncrypted Secrets機能を使っていますね。

```yml:config/storage_services.yml
test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

# Use rails secrets:edit to set the AWS secrets (as shared:aws:access_key_id|secret_access_key)
amazon:
  service: S3
  access_key_id: <%= Rails.application.secrets.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.secrets.dig(:aws, :secret_access_key) %>
  region: us-east-1
  bucket: your_own_bucket

# Remember not to checkin your GCS keyfile to a repository
google:
  service: GCS
  project: your_project
  keyfile: <%= Rails.root.join("path/to/gcs.keyfile") %>
  bucket: your_own_bucket

mirror:
  service: Mirror
  primary: local
  mirrors: [ amazon, google ]
```

### スキーマ
ここは意識しなくても良いところですが、内部的に使われるテーブルが二つ生えます。
それぞれ、`Blob`モデルと`Attachment`モデルで使われます。


```ruby:db/yyymmddhhmmss_active_storage_create_tables.rb
class ActiveStorageCreateTables < ActiveRecord::Migration[5.1] # :nodoc:
  def change
    create_table :active_storage_blobs do |t|
      t.string   :key
      t.string   :filename
      t.string   :content_type
      t.text     :metadata
      t.integer  :byte_size
      t.string   :checksum
      t.datetime :created_at

      t.index [ :key ], unique: true
    end

    create_table :active_storage_attachments do |t|
      t.string  :name
      t.string  :record_gid
      t.integer :blob_id

      t.datetime :created_at

      t.index :record_gid
      t.index :blob_id
      t.index [ :record_gid, :name ]
      t.index [ :record_gid, :blob_id ], unique: true
    end
  end
end
```


## 使い方
`has_one_attached`メソッドで使用したいプロパティ[^1]を引数にとって定義する。


```ruby:app/models/user.rb
class User < ApplicationRecord
  has_one_attached :avatar
end
```

これでActive Storageが用意したメソッドを使うことができる。

```ruby
# attachメソッドでアップロード
user.avatar.attach io: File.open("~/face.jpg"), filename: "avatar.jpg", content_type: "image/jpg"
user.avatar.exist? # => true

# purgeメソッドで削除
user.avatar.purge
user.avatar.exist? # => false

# user.avatar.purge_laterで非同期削除もできるっぽい
```

有効期限が設定されたURLを発行することもできるようです

```ruby
# 5分だけ有効なURL
user.avatar.url(expires_in: 5.minutes) # => /rails/blobs/<encoded-key>
```

その他、複数ファイルのアップロードも対応していますが、機能としては現時点でこれくらいのものでした。

## まとめ
まだまだ開発中のようですが、アップロードだけであれば簡単にできそうな感じでした。

他の同種ライブラリのように、画像リサイズやサムネイル生成、拡張子のホワイトリスト／ブラックリスト機能はないようですので、まずはシンプルなアップロード要件から使っていこうかなという印象です。

Active Storageが同梱されるRails5.2リリースは通常であれば来年の春〜夏前です。
時間もまだまだありますので、この記事の内容はだいぶ変わると思います。
「そんな機能も入るんか」くらいのざっくりとした気持ちで頭の片隅に置いててください。

現場からは以上です。

[^1]: 仮想的に使うもので、マイグレーションで生やす必要はない（サンプルでは`avatar`）