[Rails]Active Storageを理解してない人は覗いてご覧なさい

# はじめに
Rails5.2から、公式でファイルアップロード機能が提供されました。それが`Active Storage`です。アプリケーションでActive Storageを用いることで、ImageMagickで画像のアップロードを変換したり、 PDFやビデオなどの非画像アップロードの画像表現を生成したり、任意のファイルからメタデータを抽出したりできます。

# 使用方法
1.Active Storageに必要なファイルを生成する。

```bash
$ rails active_storage:install
```

2.ファイルアップロードを利用したいモデルを生成する。
※今回はscaffoldを利用してUser関連のファイルを生成しています。

```bash
# portraitというActive Storage用属性を追加する
$ rails g scaffold user name portrait:attachment
```

`rails db:migrate`で、マイグレーションファイルを実行する。

3.主となるモデルにActiveStorage用の宣言をする。

```app/models/user.rb
class User < ApplicationRecord
  # 1対１(単数枚画像投稿)で関連付けるという宣言
  has_one_attached :portrailt

  # 1対多(複数枚画像投稿)で関連付けるという宣言
  has_many_attached :portrailts
end
```

## 仕組みとDB構成
Active Storageは、アプリケーションのデータベースで`active_storage_blobs`と`active_storage_attachments`という名前の2つのテーブルを使用します。
テーブル間のリレーション(関係性)は以下の図の通りです。

![スクリーンショット 2021-07-11 22.28.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622448/5c385017-7fc8-bec1-06f7-5b357a801a26.png)

参考:[【Rails6.0】Active Storageを用いた単数枚、複数枚画像投稿の実装手順をそれぞれ解説](https://techtechmedia.com/active-storage-rails6/)

- active_storage_blobsテーブル
    - アップロードファイルのメタ情報を管理するモデル。
- active_storage_attachments
    - 主となるモデルとactive_storage_blobsテーブルの中間テーブル。

## ファイル保存場所の設定
デフォルトでは、ローカルのファイルシステムに保存しています。しかし、本番環境ではS3などクラウドストレージを利用することが多いため。設定ファイルを用意する。

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

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

# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
# 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-east-1
#   bucket: your_own_bucket
...
```

## Tips
### サムネイルの作成
1.Gemfileに以下を記載し、`bundle install`を実行する。

```ruby
gem 'image_processing'
```

2.以下のコマンドを実行し、ImageMagickをインストールする。

```bash
$ brew install imagemagick
```

3.ビューでサムネイルを表示させる。

```app/views/users/show.html.erb
...
  # portrailt.variantメソッドに渡したメソッドは、ImageProcessingメソッドとして実行される
  <%= image_tag @user.portrailt.variant(resize_to_limit: [100, 100]) %>
...
```

### ダイレクトアップロード機能
1.下記のJavaScriptライブラリを読み込む。(Rails6系はデフォルトで読み込み済)

```app/javascript/packs/application.js
require('@rails/activestorage').start()

// こちらの場合もあります
ActiveStorage.start()
```

2.file_fielsにオプションを追加する。
※`direct_upload: true`で、ダイレクトアップロード機能を有効にし、複数のファイルを同時アップロードしたい場合は`multiple: true`とする。

```ruby
...
  <%= form.file_field :portrait, direct_upload: true, multiple: true %>
...
```

## 注意点
少し改善点はあるものの、今後の利用者が増えることに従い、これらの課題は解決されていくと思います。
### 既存のgemなどを利用している場合は移行した方が良い？
無理にActiveStorageに移行する必要は、利用しているライブラリのメンテナンスが終了していて、ActiveStorageへの移行を推奨している場合を除き、コストの観点から必須ではないです。

### Validationヘルパーの不足
ActiveStorageには、バリデーション用のヘルパーメソッドが無いので`自力で実装`もしくは`ActiveStorageValidations等のgem`利用しなければいけないです。

### cacheの不足
バリデーションエラー時には、現在はキャッシュ機能がないので画像をもう一度アップロードしないといけないです。

# 終わりに
今まではCarrierWaveなどを使って画像アップローダーを作成していたので、標準装備で実装できるのはいいですよね！今後は、こっちがスタンダードになってくると思うので、今のうちに扱いを覚えておこう。。


## 参考
[Active Storage の概要]
(https://railsguides.jp/active_storage_overview.html)

[rails/activestorage]
(https://github.com/rails/rails/tree/main/activestorage)

[image_processing/doc/minimagick.md]
(https://github.com/janko/image_processing/blob/master/doc/minimagick.md)

[ImageMagick]
(https://imagemagick.org/script/)