2
0

More than 1 year has passed since last update.

【Rails/carrierwave】画像データをsubmitしたらバリデーションエラーになった話

Last updated at Posted at 2021-11-18

やりたかったこと

ユーザが画像を投稿する際に、投稿確認画面で内容確認後、画像投稿を完了させる。

実行環境

ruby 3.0.1
Rails 6.0.4.1

使用gem:
carrierwave
pry-rails (デバッグで使用のため)

問題

①確認画面(confirm view)から投稿ボタン(form_submit)を押すと、バリデーションエラーが発生する
②モデルに設定したバリデーションを解除し、再投稿したらNil location provided. Can’t build URI.が発生する
4.PNG

問題の発生理由

new viewからconfirm viewにページが移る際に画像のデータが渡されずに消えてしまう。
①は確認画面に移る際にユーザーから渡された画像データがロストしてるため、画像データを挿入したフォームデータはNilとなり、モデルに設定したバリデーションに基づいてバリデーションエラーとなった。
②は画像データの入る(※)カラムはNilの状態でsaveされたため、実際の画像データがあるURLを取得出来なかった。
※ 実際にDBに登録されてるのは画像データそのものではなく、画像データの場所を記したURLが格納されている。

解決手段

Carrierwaveのキャッシュ機能(※)を使用する
※キャッシュ機能とは、"public/uploads/"フォルダ内にアップロードされたファイルを"public/uploads/tmp/"へコピーして再利用出来るようにする仕組みです。

Carrierwaveのキャッシュ機能を使うためには以下の2点を行う必要があります。
1.Viewに「form.hidden_field :<カラム名>_cache」を追記する。
※form.hidden_fieldとは、View上に入力フォームを生成せずに受け取った値を保持するためのフィールド

# 例)confirm.html.erb
# 省略
 <%= form.hidden_field :image_cache %>
# 省略

2.上記1のhidden_fieldで値を保持したデータを受け取るために、ControllerのStrong Parametersに "<カラム名>_cache" を追記する。
実際のモデルやテーブルはキャッシュを格納する属性やカラムを持っていないため、イメージしづらいので注意。

# 例) controller
  private
  def picture_params
    params.require(:picture).permit(:image, :text, :image_cache)
  end

補足という名のメモ

問題②が発生してしまった場合は対象レコードを削除しないと、対象レコードの情報をViewで表示する際に毎度エラーが発生してしまうため、レコードを削除する必要があります。

# 例)
Picture.all
#=> 結果省略

@picture = Picture.find(x) #.all等で確認した際にimage等のカラムがnilになっていたIDを指定する
@picture.destroy

検証のためにモデルのバリデーションを解除している場合は元に戻す

久しぶりにガッツリ沼ってしまったので、解決出来てよかった~

参考文献

carrierwave github
[Rails6]CarrierWaveを基本に忠実に使ってみる~キャッシュ・S3編~
【Rails】CarrierwaveのCache機能を使用し、バリデーション後の画像データを保持する方法
Railsガイド 4.5 Strong Parameters

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0