【Rails】Railsで動画をアップロード（ActiveStorage）

現在プログラミングスクールに通い、ポートフォリオ制作フェーズに移行した所です。
インスタのストーリーズみたいに、短い動画を投稿できるようなのを作ろうと思ったのですが動画をアップする記事が思ったより少なくて悩んだので、今回忘れないように書いておこうと思います。

## 参考サイト

- [【Rails 5.2】 Active Storageの使い方](https://qiita.com/hmmrjn/items/7cc5e5348755c517458a)
- [Active Storageを使って動画投稿サイトを作った](http://yuzukiarai.me/?p=378)
- https://stackoverflow.com/questions/50993367/active-storage-displaying-video-in-video-tag
　

## Active Storage を使用

当初は Carrierwave などを使って実装しようと考えていましたが、調べると Rails の標準機能でファイルアップロードができるようなので、こちらで実装します。
ActiveStorageを今日知った程度の初学者なので詳しいことは他の方の記事を調べてみて下さい。
動画投稿までのフローを残しておきます。
参考サイトからの引用です。

>Rails5.2で追加された、ファイルアップロードを行うための機能です。これを使えば、フォームで画像の投稿機能などが簡単に作れます。また、Amazon S3, Google Cloud Storage, Microsoft Azure Storageなどのクラウドストレージサービスに対するファイルのアップロードを簡単に行うことができます。クラウドストレージの他に、ローカルディスクにファイルを保存することもできます。

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

```
$ rails active_storage:install
$ rails db:migrate
```

`active_storage_blobs`と`active_storage_attachments`という２つのテーブルが作成されます。
この２つはこのままで次に進みます。

### モデルの作成

今回はシンプルに`Video`というモデルを作ります。
カラムに`title`と`introduction`を作成しました。
ここで動画自体のカラムは作っていません。

```
$ rails g resource video title:string introduction:text
$ rails db:migrate
```

今回は「投稿する動画は1回で１つ」という前提にします。
`Video`モデルに`has_one_attached`を記述します。

```/app/models/video.rb
class Video < ApplicationRecord
  has_one_attached :video
end
```
`:video`はファイルの呼び名で、用途に合わせて好きな名前をつけていいようです。（画像をアップロードするなら`:image`など）

### コントローラーの作成

videosコントローラーに記述していきます。

```/app/controllers/videos_controller.rb
class VideosController < ApplicationController

  def new
    @video = Video.new
  end

  def create
    @video = Video.new(video_params)
    @video.create
    redirect_to @video
  end

  def show
    @video = Video.find(params[:id])
  end

  private

  def video_params
    params.require(:video).permit(:title, :introduction, :video)
  end
end
```

`Video`モデルに`:video`カラムはありませんが、ここは`has_one_attaches :video`に対応します。
今回は動画の投稿ができるかテストなので、new create showだけ書いてあります。

### ビューの作成 

newで投稿フォームを記述します。

```/app/views/videos/new.html.erb
<%= form_with model: @video, local: true do |form| %>
  <p>title</p><%= form.text_field :title %> <br>
  <p>introduction</p><%= form.text_area :introduction %> <br>
  <p>video</p><%= form.file_field :video %> <br>
  <%= form.submit %>
<% end %>
```
![スクリーンショット 2020-09-02 14.26.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629679/fe5e8cea-d6a6-c87b-b0d1-140af70246fb.png)
こんな感じで投稿フォームができたかと思います。
showページも作ります。

```/app/views/videos/show.html.erb
<% if @video.video.attached? %>
  <p><%= @video.title %></p> <br>
  <p><%= @video.introduction %></p>
  <%= video_tag rails_blob_path(@video.video) %>
<% end %>
```
`.attached?`で@videoがvideoを持っているかどうかを調べられます。

シンプルに　`<%= video_tag @video.video %>`　と書いてしまうと、データを `/app/assets/` の方に探しにいくみたいで、アセットパイプラインのエラーが出ます。
`rails_blob_path`を記述しましょう。

![スクリーンショット 2020-09-02 14.34.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629679/f5f484e4-5cec-6ba5-d0fc-04ed16979bf5.png)

これで表示はされました。ただ今のままだと動画が再生されません。 `<%= video_tag %>`を `<video>` の中に記述します。

```/app/views/videos/show.html.erb
<% if @video.video.attached? %>
  <p><%= @video.title %></p> <br>
  <p><%= @video.introduction %></p>
  <video src="<%= rails_blob_path(@video.video) %>" type="video/mp4" controls></video>
<% end %>
```

`controls`は動画を利用しやすくするインタフェースを自動で作成します。
これで、動画のアップロードと表示、再生までを作ることができました。

![スクリーンショット 2020-09-02 14.46.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629679/72d41d49-3e7d-175e-b2d4-e7ce317a4a3e.png)

実際カラムを作っているわけではないので、一覧表示してみたりするのはこれからですが果たしてうまくいくのか・・・
また何かあったら投稿しようと思います。


## 注意点
今回はポートフォリオ作成なので、デプロイまで考えて動画はフリー素材のもの、かつ、数秒程度の短いものを利用する前提です。
動画が長いものはサイズが大きいのでローカルはともかくネットワーク上でやろうとするとえらいことになりそうです。
（スクールの人には必要最低限にしてねと注意されました）
利用料はかかりますが AWS S3 を使用するなどの方法があるようです（この辺りはまだ詳しくないですが）
自分と同じような初学者の方で、こういう方法があるんだなぁ、と思ってもらえれば幸いです。