Note that there are some explanatory texts on larger screens.

plurals
  1. POActiveRecord has_many association doesn't call after_destroy when setting a collection
    primarykey
    data
    text
    <p>3 models: User, Movie, Like</p> <pre><code>User has_many :likes User has_many :movies, through: :likes </code></pre> <p>This code:</p> <pre><code>user.movies = [ m1, m2, m3 ] </code></pre> <p>calls <code>Like#after_create</code> for the new <code>Like</code> records that relate user and m1/m2/m3. Then, this code:</p> <pre><code>user.movies = [ m3, m4 ] </code></pre> <p>doesn't call <code>Like#after_destroy</code> for the <code>Like</code> records that relate user to m1/m2, but does call <code>Like#after_create</code> for the new relationship with m4.</p> <p>The <code>movies</code> collection could be set manually or with a form that has <code>user[movie_ids]</code> checkboxes, and then</p> <pre><code>user.update_attributes(params[:user]) </code></pre> <ol> <li>What is the right Rails approach for setting a collection?</li> <li>How do I force it to call after_destroy?</li> </ol> <h1>Update:</h1> <p>As @jdoe cited from the docs, it's not achievable when assigning new collection or when deleting from a collection (<code>user.movies.delete(m1)</code>). The only way is to use <code>before_remove</code>/<code>after_remove</code> callbacks on the user model (and in case of a polymorphic relationship -- any other model), with the <code>has_many</code> definition:</p> <pre><code>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 </code></pre> <p>Can't understand the logic behind it. It makes callbacks on relationship models totally useless. If something happened on <code>after_create</code> it can't be undone in <code>after_destroy</code>, and since it's better practice to have after and before logic together and not separately, it makes all callbacks useless.</p> <p>Think I'm gonna write a gem that does that automagically.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload