numberというカラムを作成。numberはとある条件を元に数字を計算し、それが値として入る。(今回の記事に関係ないので具体的なコードや条件は割愛)
新規登録時にはbefore_saveを経由して上記条件に基づきカラムの値を生成するが、更新時にもその値が変わらないようにしたい場合。
before_saveに書いたメソッドは登録更新どちらのsave時にも経由してしまうため、updateのときだけ通らないようにしたらいいのでは?と考えて以下の実装。
attr_accessorを使用。
参考にさせていただいた記事
https://kei178.me/programming/1416/
attr_accessor :number_required
before_save :apply_number, if: :number_required?
def number_required?
number_required
end
def apply_number
self.number = number_for_new_post
true
end
def number_for_new_post
# 適切な数字を生成するための処理
end
def create
@hoge = Hoge.new(create_hoge_params)
@hoge.number_required = true # この一行追加
if @hoge.save
redirect_to root_path
else
render :new
end
end
...
def update
begin
@hoge = Hoge.find(params[:id])
@hoge.number_required = false # ここの一行追加
@hoge.update!(update_hoge_params)
redirect_to hoge_path
rescue ActiveRecord::RecordNotFound => e
flash[:alert] = "更新失敗しました"
redirect_to hoge_path
rescue ActiveRecord::RecordInvalid => e
render :edit
end
end
...
private
def create_hoge_params
# 新規作成時に必要なカラム
end
def update_hoge_params
# 更新時に必要なカラム
end
これだと確かにupdateのときはbefore_saveを通らない。
しかし今回のように新規登録時にはnumberが必ず必要となる場合、number_required?だとわかりづらい。。
そこで使うのがnilガード
そもそもbefore_saveを経由しても値が変わらないようにすれば問題がなかったため、以下のように修正するだけでよかった。
参考にさせていただいた記事
https://note.com/vixer93/n/n20c409919665
attr_accessor :number_required
before_save :apply_number
def apply_number
self.number ||= number_for_new_post
true
end
numberに値がなければnumber_for_new_postメソッドの返り値がnumberに。
もしnumberがもう入ってればそのまま。