4

3つのモデル:ユーザー、映画、いいね

User has_many :likes
User has_many :movies, through: :likes

このコード:

user.movies = [ m1, m2, m3 ]

ユーザーとm1/m2/m3に関連Like#after_createする新しいレコードを要求します。Like次に、このコード:

user.movies = [ m3, m4 ]

ユーザーをm1/m2に関連付けるレコードは必要ありませんがLike#after_destroy、m4との新しい関係は必要です。LikeLike#after_create

moviesコレクションは、手動で設定することも、user[movie_ids]チェックボックスのあるフォームを使用して設定することもできます。

user.update_attributes(params[:user])
  1. コレクションを設定するための正しいRailsアプローチは何ですか?
  2. after_destroyを強制的に呼び出すにはどうすればよいですか?

アップデート:

@jdoeがドキュメントから引用しているように、新しいコレクションを割り当てるとき、またはコレクションから削除するときは達成できません(user.movies.delete(m1))。唯一の方法は、ユーザーモデル(およびポリモーフィック関係の場合は他のモデル)でbefore_remove/コールバックを使用することです。定義は次のとおりです。after_removehas_many

has_many :movies, through: :likes, before_remove: :before_like_destroy, after_remove: after_like_destroy

def before_like_destroy(movie)
  like = self.likes.where(movie_id: movie)
  # trigger the after_destroy on like
  like.trigger_before_destroy # to be implemented on like, should call what the original callbacks contained
end

def after_like_destroy(movie)
  # no way to get Like object here because it was already removed, need to remember it on the before_destroy somehow
end

その背後にある論理を理解することはできません。リレーションシップモデルのコールバックはまったく役に立たなくなります。何かが起こった場合、after_createで元に戻すことはできませんafter_destroy。また、ロジックの前後を別々にではなく一緒に使用することをお勧めします。これにより、すべてのコールバックが役に立たなくなります。

それを自動的に行う宝石を書くつもりだと思います。

4

2 に答える 2

3

ドキュメントによると:

collection =objects

必要に応じてオブジェクトを削除および追加することにより、コレクションのコンテンツを置き換えます。:throughオプションがtrueの場合、削除は直接であるため、破棄コールバックを除いて、結合モデルのコールバックがトリガーされます。

于 2012-07-05T09:05:39.660 に答える
0

likeとmovieの両方の関連付けにdependent::destroyを追加すると、after_destroyコールバックが呼び出されます

于 2014-11-13T18:41:13.210 に答える