Techioz Blog

Ruby on Rails のアクティブ ストレージ検証が機能しない

概要

使っています:

レール 6.0.4.4

ルビー 3.0.0

gem’active_storage_validations’ をプロジェクトに追加し、それを使用して添付されたアバターが画像であることを検証しようとしています

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable, :trackable, :lockable, :masqueradable
         
  validates :first_name, :last_name, presence: true
  validates :email, uniqueness: true
  validates :terms_and_conditions, acceptance: true
  validates :avatar, attached: true,  content_type: ['image/png', 'image/jpg', 'image/jpeg']
  has_one_attached :avatar
end

私のサインアップフォームで

<%= render "devise/shared/error_messages", resource: resource %>
<div class="container pt-3 pb-3">
  <div class="card">
    <div class="card-header">
      <h2>Sign up</h2>
    </div>
    <div class="card-body">
      <%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
        <div class="field mb-3">
          <%= f.label :profile_picture %><br />
          <%= f.file_field :avatar, class: "form-control"  %>
        </div>
        <div class="field mb-3">
          <%= f.label :email %><br />
            <%= f.email_field :email, autofocus: true, autocomplete: "email", class: "form-control", placeholder: "[email protected]" %>
        </div>
        <div class="field mb-3">
          <%= f.label :first_name %><br />
            <%= f.text_field :first_name, required: true, autofocus: true, autocomplete: "first_name", class: "form-control" %>
        </div>
        <div class="field mb-3">
          <%= f.label :last_name %><br />
            <%= f.text_field :last_name, autofocus: true, autocomplete: "last_name", class: "form-control" %>
        </div>
        <div class="field mb-3">
          <%= f.label :password %>
          <% if @minimum_password_length %>
          <em>(<%= @minimum_password_length %> characters minimum)</em>
          <% end %><br />
          <%= f.password_field :password, autocomplete: "new-password", class: "form-control" %>
        </div>
        <div class="field mb-3">
          <%= f.label :password_confirmation %><br />
          <%= f.password_field :password_confirmation, autocomplete: "new-password", class: "form-control" %>
        </div>
        <div class="form-check form-switch text-muted">
          <%= f.check_box :terms_and_conditions, class: 'form-check-input', id: 'flexSwitchCheckDefault' %>
          I hereby confirm I have read and undertood the terms and conditions
        </div>
        <div class="actions">
          <%= f.submit "Continue", class: "btn btn-primary"  %>
        </div>
      <% end %>
      <br>
    <%= render "devise/shared/links" %>
    </div>
  </div>
</div>

他の検証はすべて正常に機能します。

添付された画像にファイルの種類またはサイズの検証を追加しても、ユーザーは任意のファイルの種類とサイズをアップロードできます

解決策

私は active_storage_validation gem の管理者ですが、あなたがここに期待しているかどうかはわかりません。

まず、UI 部分でのユーザー入力を制限する必要があります。これは、input 要素の accept HTML 属性、つまり accept=“image/png, image/jpg, image/jpeg” で表されます。これにより、ユーザーはこれらのコンテンツ タイプのファイルのみをアップロードできるようになり、UX が向上します。

次に、モデル上で検証を実行し、そこで active_storage_validation が機能します。 content_type バリデータには次のガード句 (record.send(attribute).attached? (ここ) がない限り true を返す) があるため、何もアタッチしなくてもエラーは発生しません。これにより、送信されるエラーの数が減少します。

accept HTML 属性を追加すると、ほとんどのケースが解決すると思います。

そうでない場合は、gem リポジトリで問題を取り上げてこれについて議論できます。