【Ruby on Rails】Active Storageを使った画像アップロード

# はじめに

Rails勉強中のエンジニア初心者が他の記事を参考にしたり、実際に実装してみたりして、アウトプットの一環としてまとめたものです。
間違っていることもあると思われるので、その際は指摘いただけると幸いです。

# Railsガイド

https://railsguides.jp/active_storage_overview.html#active-storage%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

# Railsでの画像アップロード

代表的な方法として下記2つのパターンがあるが、1について記載する。
Rails5.1までは`carrierwave`という`Gem`のインストールが一般的であったが、
Rails5.2以降は`Active storage`という便利機能が追加されたため、新たな`Gem`のインストールは不要となった。

1. `Active Storage`と`image_processing`を使用する
2. `carrierwave`と`mini_magic`を使用する

# Active Storageとは

- `Active Storage`は、Rails5.2で追加されたファイルアップロードを行うための機能で、フォームでの画像の投稿機能などが簡単に実装できる
- `Amazon S3`、`Google Cloud Storage`、`Microsoft Azure Storage`などのクラウドストレージサービスに対しても、ファイルのアップロードを簡単に行うことができる
- クラウドストレージの他に、ローカルディスクにファイルを保存することもでき、開発環境ではローカルストレージにファイルを保存して、本番環境ではクラウドストレージにファイルを保存するなど、環境毎に保存先を切り替えることもできる
- `Paperclip`、`Carrierwave`、`Dragonfly`などの`Gem`の代わりになると言われている

# Active Storageをインストールする

`rails active_storage:install`を実行するとActive Storageを使用するために必要となるテーブルを作成するためのマイグレーションファイルが自動で作成される（`active_storage_bolds`、`active_storage_attachements`、`active_storage_variant_records`）

#### 実行コマンド
    
    
    rails active_storage:install
    rails db:migrate
    
# Active Storageの実装

### モデルの編集

`Active Storage`を使って画像などのデータを既存のテーブルと紐づけるために、

モデルファイルに`has_one_attached :カラム名`を追加する（`has_one_attached`は`Active Storage`で使う指定方法）。

> シンボルで指定するカラム名でそのデータを扱うため分かりやすい名称にする。例えば、画像なら`:image`、動画なら`:movie`、アバターなら`:avatar`など。
> 

### モデルファイルへの記載方法
    
    ```ruby
    # １ファイルの場合
    has_one_attached :image
    
    # 複数ファイルの場合
    has_many_attached :images
    ```
    

### 実際の記述例
    
    # Roomモデルにアイコンとして画像を1つ紐づける場合
    class Room < ApplicationRecord
      has_one_attached :image    
    end

    

### コントローラの編集

モデルファイルで関連付けたActive Storageのデータをパラメータで受け取ることができるように、ストロングパラメータに対象のカラム名を追加する。

- 実際の記述例
    
    ```ruby
    class RoomsController < ApplicationController
      def create
        @room = Room.new(room_params.merge(user_id: current_user.id))
        if @room.save
          flash[:notice] = "ルームを登録しました"
          redirect_to :rooms
        end
      end
    
      private
    
      def room_params
        params.require(:room).permit(:room_name, :room_introduction, :usage_fee, :address, :image)
      end
    end
    ```
    

### ビューの編集

- ビューへの記載方法
    
    ```ruby
    # 画像を登録するフォーム
    <%= form.file_field :image %>
    
    # 登録されている画像を表示する
    <%= image_tag @room.image %>
    ```
    

- 実際の記述例
    
    ```ruby
    # 登録フォーム
    
    <%= form_with model: room do |f| %>
    
      <%= f.label :image, 'ルーム画像' %>
      <%= f.file_field :image, required: true %>
    
    	<%= f.submit '登録', class: 'submit-button' %>
    <% end %>
    ```
    
    ```ruby
    # 画像の表示
    # 画像が登録されていないとエラーになるため、if room.image.attached?で画像が登録されている場合のみ表示する
    <% @rooms.each do |room| %>
      <%= link_to(new_reservation_path(id: room.id)) do%>
        <p><%= image_tag(room.image.variant(resize: 399)) if room.image.attached? %></p>
      <% end %>
    <% end %>
    ```
    

# 画像のサイズ変換

アップロードした画像をビューで表示するときに画像サイズを変換することができる。一覧ページでは画像サイズを100×100で表示し、詳細ページでは300×300で表示する場合などは、`Active Storage`の`variant`（バリアンと）という機能を使用する。

`variant`を使用すると、アップロードした画像を基にして簡単に画像のサイズを変更することが作成できる。

`variant`を使用するためには、`ImageProcessing`という`Gem`をインストールする必要がある。

```ruby
# Use Active Storage variant
gem 'image_processing', '~> 1.2'
```

`ImageProcessing`は内部の画像プロセッサとして`MiniMagick`という`Gem`を使用しており、`MiniMagick`は`ImageMagick`というソフトウェアの`Gem`版であるため、`ImageMagick`がインストールされていないと動かない。

> `ImageMagick`　>>　`MiniMagick`　>>　`ImageProcessing`　>>　`variant`という流れ
> 

そのため、ImageProcessingを使うためには、ImageMagickをインストールする必要がある。

> この手順は本番環境でも行う必要があるため注意が必要。
> 

```bash
# Macの場合
$ brew install imagemagick

# Ubuntuの場合
$ sudo apt-get install imagemagick

# バージョン確認
$ convert --version
```

- variantによる画像のリサイズ
    
    ```ruby
    <%= image_tag room.image.variant(resize: 399) %>
    ```
    

- オプション一覧
    
    
    | オプション | 説明 |
    | --- | --- |
    | gravity | 画像変換の始点。convert -list gravityで指定値一覧を表示（デフォルトはNone）。 |
    | resize | 画像のサイズ。詳しくは Image Geometry - ImageMagick 参照。 |
    | crop | 始点からの切り抜きサイズ。 |
    | precessed | 既に変換済みであれば変換しない（キャッシュを表示）。 |



# 参考

https://autovice.jp/articles/134

https://prograshi.com/framework/rails/active-storage/

https://qiita.com/hmmrjn/items/7cc5e5348755c517458a

https://goruchanchan.hatenablog.com/entry/2022/08/22/234305#%E3%83%93%E3%83%A5%E3%83%BC%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B