Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Sadly people keep on using <code>has_and_belongs_to_many</code> even though it leads to all kinds of orphans like this. A <code>has_many ..., :through</code> relationship can be flagged <code>:dependent =&gt; :destroy</code> to clean up unused children automatically. It's common that you'll have unused join records and they are obnoxious to remove.</p> <p>What you might do is approach this from a SQL angle since <code>has_and_belongs_to_many</code> records are inaccessible if their parent records are no longer defined. They simply do not exist as far as ActiveRecord is concerned. Using a join model means you can always access this data since they are issued their own ids.</p> <p><code>has_and_belongs_to_many</code> relationships are based on a compound key which makes removing them a serious nuisance. Normally you'd do a <code>DELETE FROM table WHERE id IN (...) AND ...</code> and be confident that only the target records are removed. With a compound key you can't do this.</p> <p>You may find this works for an example Tag to Item relationship:</p> <pre><code>DELETE FROM item_tags, tags, items WHERE item_tags.tag_id=tags.id AND item_tags.item_id=items.id AND tags.id IS NULL AND items.id IS NULL </code></pre> <p>The <code>DELETE</code> statement can be really particular about how it operates and does not give the same latitude as a <code>SELECT</code> with joins that can be defined as left or right, inner or outer as required.</p> <p>If you had a primary ID key in your join table you could do it easily:</p> <pre><code>DELETE FROM item_tags WHERE id IN (SELECT id FROM item_tags LEFT JOIN tags ON item_tags.tag_id=tags.id LEFT JOIN items ON item_tags.item_id=items.id WHERE tags.id IS NULL AND items.id IS NULL) </code></pre> <p>In fact, it might be advantageous to add a primary key to your relationship table even if ActiveRecord ignores it.</p> <p><em>Edit:</em></p> <p>As for your module issue, if you're stuck with that approach:</p> <pre><code>module CleanupMethods def cleanup # ... end end class Tag # Import the module methods as class methods extend CleanupMethods end </code></pre> <p>If you use a counter cache column you can do this a lot more easily, but you will also have to ensure your counter caches are accurate.</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.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      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