【Rails】ActiveStorageの image_tag エラー について

Ruby Ruby
Ruby

はじめに

ActiveStrageの使い方を知ろうと思い簡単なアプリケーションを作っていたところimage_tagで発生したエラーについて調べてみました。

エラー発生時のコード

画像挿入実装の前提

  • Mac OS(imagemagicインストール済み)
  • image_processing 1.12.2利用
  • ActiveStorageで保存した画像を表示させる
  • 画像の表示は存在する時のみ表示 ⇦ 結局ここで引っかかった

実装内容

理想の画面イメージはこんな感じ。

ところが、ActiveStrageで保存した画像を表示させるテンプレートで下記のようなimage_tagを利用した表記を試したところいくつかエラーが発生しました。

Can’t resolve image into URL: undefined method `persisted?’ for nil:NilClass

下記のようにテンプレートを実装したところ<%= image_tag user.avatar %> で発生したエラーです。

<tbody>
  <% @users.each do |user| %>
    <tr>
      <td><%= user.name %></td>
      <td><%= user.email %></td>
      <td><%= user.code %></td>
      <td><%= user.address %></td>
      <td><%= image_tag user.avatar %></td> <%# ⇦ココで発生している %>
      <td><%= link_to t('views.common.show'), user %></td>
      <td><%= link_to t('views.common.destroy'), user, method: :delete, data: { confirm: t('views.common.delete_confirm') } %></td>
    </tr>
  <% end %>
</tbody>

user.avatorはActiveStorageのクラスであるActiveStorage::Attached::Oneを持っています。

画像が存在しない場合、そのActiveStorage::Attached::OneクラスがNull値としてuser.avatarに代入されることが根本原因です。

image_tagのエラーというより「Nilクラスはpersisited?メソッドを持たないよ」というエラーです。

この文言をimage_tagでURIとして解釈しようとしてしまい今回のようなエラーが発生してしまいました。

Nil location provided. Can’t build URI.

同様に<%= image_tag user.avatar %> で発生したエラーです。

一つ目のエラーとは違い、user.avator.variant() メソッドを利用しています。

<tbody>
  <% @users.each do |user| %>
    <tr>
      <td><%= user.name %></td>
      <td><%= user.email %></td>
      <td><%= user.code %></td>
      <td><%= user.address %></td>
      <td><%= image_tag user.avatar.variant( resize: "64x64^", gravity: "center", crop: "100x100+0+0" ) if user.avatar.attached?%></td> <%# ⇦ココで発生している %>
      <td><%= link_to t('views.common.show'), user %></td>
      <td><%= link_to t('views.common.destroy'), user, method: :delete, data: { confirm: t('views.common.delete_confirm') } %></td>
    </tr>
  <% end %>
</tbody>

variantメソッドでは画像をサーバサイドでレンダリングする際に加工をしています。

その中で加工された画像のURLが返却値をしてimage_tagに渡されるのですが、画像が存在しない場合にはNull値になります。

そのためこのエラーが発生することになります。

証拠として、image_tagにあえてnilを渡すと同様のエラーが得られます。

<td><%= image_tag nil %></td>

 

エラーの回避

通常、DBにデータが保存されていなければNullとして返され、それがString型やInt型であればテンプレート上は特に何も指定しなくても良いです。

しかし、今回のようにメソッドに値を渡すなどの処理が走る場合はNull値に気をつけなければいけません。

対処法としては単純にuser.avatarに画像がアタッチされているかどうかを確認すれば良いのです。

<% image_tag <値> if user.avatar.attached?%>

上記を付け加えると先ほどまでのエラーを起こしていたコードが下記のようになります。

  <% @users.each do |user| %>
    <tr>
      <td><%= user.name %></td>
      <td><%= user.email %></td>
      <td><%= user.code %></td>
      <td><%= user.address %></td>
      <td><%= image_tag user.avatar.variant( resize: "64x64^", gravity: "center", crop: "100x100+0+0" ) if user.avatar.attached? %></td>
      <td><%= link_to t('views.common.show'), user %></td>
      <td><%= link_to t('views.common.destroy'), user, method: :delete, data: { confirm: t('views.common.delete_confirm') } %></td>
    </tr>
  <% end %>
</tbody>

まとめ

StringやIntではNull値はあまり気にしなくても良いですが、image_tagなどのヘルパーメソッドなどを使うときは少し気をつけてあげないといけません。

不明点などはこちらに。

タイトルとURLをコピーしました