【Rails】carrierwaveでupdateしたときにimageが空でも更新されてしまうのをなんとかする

なんか消える

railsを使っていて、画像のアップロードにはcarrierwaveを使っているのだけど、updateのときに、画像の内容が空でもデータベース内の画像のパスを上書きしてしまうって感じになってる。

つまりパスは最新の日付に従って更新されるのにそれに応じた画像をアップロードしないので実質画像が削除された感じになってしまう。

ということでこれを解消してみた。(もっといい方法はありそうというか使い方が間違ってるからこうなってるのかも)

controller

controllerはこんな感じ。

# app/controller/notes_controller.rb

# 
# omission
#

  before_action :set_note, only: [:show, :edit, :update, :destroy]
# 
# omission
# 
  def update
    if note_params[:coffee_image1]
      respond_to do |format|
        if @note.update(note_params)
          format.html { redirect_to @note, notice: "note was successfully updated with image file" }
          # format.json { render action: 'edit', status: :created, location: @note }
          format.json { head :no_content }
        else
          format.html { render action: 'edit' }
          format.json { render json: @note.errors, status: :unprocessable_entity }
        end
      end
    else
      respond_to do |format|
        if Note.update_except_for_image_path(note_params)
          format.html { redirect_to @note, notice: "#{params[:blendName]}note was successfully updated except for image file." }
          # format.json { render action: 'edit', status: :created, location: @note }
          format.json { head :no_content }
        else
          format.html { render action: 'edit' }
          format.json { render json: @note.errors, status: :unprocessable_entity }
        end
      end
    end
  end
  
  # omission
  
    private

  def note_params
    params.require(:note).permit(
      :blendName, :origin, :place, :date, :roast, :dark, :body, :flavor, :acidity, :sweetness, :cleancup, :aftertaste, :overall, :comment, :coffee_image1
    )
  end

  def set_note
    @note = Note.find(params[:id])
  end

冗長だー。完全にDRYに反してるけどどうしたらいいかわからん。htmlとjsonの部分とか、新しいメソッド作ったりすればいいのかな。

とりあえず

if note_params[:coffee_image1]

でnote_paramsにセットした、受け取った値の中にcoffee_image1が含まれているかどうかを確認する。

ユーザが画像データを送っていなかった場合は普通にそのままupdateする。

送っていなかった場合はモデルで自分で定義したクラスメソッドupdate_except_for_image_pathを実行する。

model

上記のクラスメソッドの内容は以下の通り。

  def self.update_except_for_image_path(note_params)
    Note.where(@note).update_all(blendName: note_params[:blendName], origin: note_params[:origin], place: note_params[:place], roast: note_params[:roast], dark: note_params[:dark], body: note_params[:body], flavor: note_params[:flavor], acidity: note_params[:acidity], sweetness: note_params[:sweetness], cleancup: note_params[:cleancup], aftertaste: note_params[:aftertaste], overall: note_params[:overall])
  end

update_allメソッドを使って画像のパス以外のカラムを変更してる。

おわり

入門の入門の参考書だとテーブル内の内容を全部取り出したり、みたいな処理しかしないので全部コントローラで完結してる。

でも実際それは controllerがデータベースの内容を引っ張ってくるロジックを持ってることになるからMVCモデルとしてはあまりよくないみたい。。

ということでどんなデータをselectするか、どんな風にデータをinsertしたりupdateしたいするか、ってロジック部分はできるだけmodelに書くようにこれからも気をつけよう。

できるだけcontrollerをシンプルに保つ。