Edited at

Rails6 のちょい足しな新機能を試す15(Active Storage編)


はじめに

Rails 6 に追加されそうな新機能を試す第15段。 今回のちょい足し機能は、 Active Storage 編です。

というか今回は Active Storage のバグフィックスじゃないかと思ってます。

Rails 5.2 では、model で validation のエラーが起ってもファイルがアップロードされていました。

Rails 6.0 では、model がDBに保存されるとファイルがアップロードされるようになっています。

実際に試した方がわかりやすいです。

記載時点では、Rails は 6.0.0.rc1 と 5.2.3 で確認しました。Rails 6.0.0.rc1 は gem install rails --prerelease でインストールできます。

基本的な試し方は、5.2.3 でも 6.0.0rc1 でも同じです。

$  rails --version

Rails 6.0.0.rc1


Rails プロジェクトを作る

$ rails new sandbox6_0_0rc1

$ cd sandbox6_0_0rc1


scaffold で User を作る

$ bin/rails g scaffold User name


Active Storage を使う準備をする

$ bin/rails active_storage:install


User モデルを編集する

User モデルとアップロードファイル(今回は画像ファイル)を紐づけるため has_one_attached を使います。

また、name に validation を追加します。


app/models/user.rb

class User < ApplicationRecord

has_one_attached :avatar
validates :name, presence: true
end


view を編集する

ファイルをアップロードできるように _form.html.erb を編集します。

avatar 用の form.file_field を追加します。


app/views/users/_form.html.erb

<%= form_with(model: user, local: true) do |form| %>

...
<%= form.text_field :name %>
</div>

<div class="field">
<%= form.label :avatar %>
<%= form.file_field :avatar %>
</div>

<div class="actions">
...
<% end %>


アップロードされた画像ファイルを表示できるように show.html.erbimage_tag を追加します。


app/views/users/show.html.erb

...

<%= @user.name %>
</p>

<p>
<strong>Avatar:</strong>
<% if @user.avatar.attached? %>
<%= image_tag @user.avatar %>
<% end %>
</p>
...



controller を編集する

ブラウザからパラメータとして渡されてくる avatar をUserモデルに渡せるように :avatar を追加します。


app/controllers/users_controller.rb

  private:

...
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:name, :avatar)
end


DBのmigration を実行する

$ bin/rails db:create db:migrate


rails s を実行する

$ bin/rails s


動作確認する

ブラウザで http://localhost:3000/users/new にアクセスします。

アップロードする画像ファイルを選択します。

validation error となるように name は何も入力しません。

Create User ボタンを押してみます。


Name can't be blank'


のエラーになります。

ここまでは、Rails 5.2.3 でも Rails 6.0.0rc1 でも同じです。

ここで、別のコンソールで、 storage ディレクトリを確認してみましょう。

Rails 5.2.3 では、サブディレクトリができてファイルもできています。

$ ls -lR storage

storage:
total 4
drwxr-xr-x 3 suke suke 4096 5月 11 15:36 49

storage/49:
total 4
drwxr-xr-x 2 suke suke 4096 5月 11 15:36 gT

storage/49/gT:
total 12
-rw-r--r-- 1 suke suke 9502 5月 11 15:36 49gTM2NXg8UsKPVqTSuMNXCz

Rails 6.0.0rc1 では、サブディレクトリはありません。

$ ls -lR storage

storage:
total 0

Rails 5.2.3 では、登録画面で、ファイルを指定して、validation エラーを起こす度に、 storage ディレクトリの中にファイルが増えていきます。

Rails 6.0.0rc1 では、DBに保存できた時に初めて、 storage ディレクトリの中にファイルができます。


ソース

今回のソースは以下から参照できます。

https://github.com/suketa/rails6_0_0rc1/tree/try015_active_storage


参考情報