1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

after_commitでDBの保存前後を比較判定する

Posted at

何を書いているか?

DBの保存前と保存後の判定の仕方に1日詰まってしまい、せっかくなので備忘録として書いてます。

どういう状況で詰まったか

after_commitスコープ内で、DBの保存前と保存後で比較し、保存・更新・削除されていれば、trueを返す処理をしたかったのですが、この「after_commit後の判定」というところでひっかかりました。しかも子モデルのテーブルだったのでなおさら…💧

親モデルと子モデルの関係


# User.rb(親モデル)
class User < ApplicationRecord
  has_many :posts
end

# Post.rb(子モデル)
class Post < ApplicationRecord
  belongs_to :user
end

DBにガッツリ保存された後に判定する

もうどうしようもないと挫けそうでしたが(笑)なんとか方法があったので書きます。
保存する前であれば、さまざまメソッドはあります。

attr_was(現在は非推奨のようですが…)したり、changesやprevious_changes、attr_previously_changedなどなど。

しかし、after_commitスコープ内ではこれらは通用しません。
何せ、もうDBに入ってしまっているのですから…

しかし、このafter_commit内で,「DB保存前とDB保存後のレコードの数を比較して条件分岐」
という状況が訪れました。
データの変更(update)・追加(create)については

# User.rb(親モデル)
def posts_changes?
    posts.any? {|c| c.content_previously_changed? }
end
# postsテーブルにはcontentというカラムがある前提です

のようなメソッドをUser.rb(親モデル)に定義することでクリアすることができました。

それがこちらです。

# User.rb(親モデル)
around_save :around_save_posts_comparison

def around_save_posts_comparison
    @posts_before_save_count = posts.count
    yield
    @posts_after_save_count = posts.count
  end

around_save

これは、「saveの途中の処理」ということらしく、yield前にsave前、後にsave後のものが入ります。
これを使い、インスタンスメソッドを定義しました。
それを使い、


# User.rb(親モデル)
after_commit do
  if @posts_before_save_count != @posts_after_save_count
   puts "レコードの数が変わったよ!新しく追加されたか削除されているよ!"
  end
end

このようして、なんとか処理を書くことができました。。

さっきのprevious_changed?とまとめると…

def posts_changes?
    posts.any? {|c| c.content_previously_changed? } ||
    (@posts_before_save_count != @posts_after_save_count)
end

after_commit do
  if posts_changes?
   puts "レコードの数が変わったか、新しく追加されたか削除されているか、変更されているよ!"
  end
end

ただ、先輩からは「ちょっと見た目やばい。…ただ、他に処理が思いつかないから一旦これでいいか」

という感じなので、他に答え知っている方は教えていただけるとありがたいです。。

参考記事

1
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?