Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save marcamillion/213fd304e6c6518aae55 to your computer and use it in GitHub Desktop.
Save marcamillion/213fd304e6c6518aae55 to your computer and use it in GitHub Desktop.
Easily Find Polymorphically Associated Records whose destroy callbacks were not called
# The main issue here is, if you do a bunch of delete calls on a model that has associations there will be some other records that
# still exist and point to legit looking values that don't work, because even though the foreign_key exists in the table,
# the record it is pointing to does not.
# For e.g. A User and an Event
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# email :string(255) default(""), not null
#
class User < ActiveRecord::Base
has_many :events, dependent: :destroy
end
# == Schema Information
#
# Table name: events
#
# id :integer not null, primary key
# user_id :integer
# action :string(255)
# eventable_id :integer
# eventable_type :string(255)
# created_at :datetime
# updated_at :datetime
#
class Event < ActiveRecord::Base
belongs_to :user
belongs_to :eventable, polymorphic: true
end
# If you do `user.delete`, the associated events with that user won't get removed. They will just be hanging there.
# Since you don't have a list of all the IDs that you deleted, the way to approach this is simply get the inverse (or the 'not')
# of the IDs that do exist.
[11] pry(main)> node_ids = Node.all.map(&:id)
Node Load (1.0ms) SELECT "nodes".* FROM "nodes"
=> [38, 43, 39, 44, 34, 35, 36]
[12] pry(main)> Event.where(eventable: node_ids)
Event Load (0.6ms) SELECT "events".* FROM "events" WHERE "events"."eventable_id" IN (38, 43, 39, 44, 34, 35, 36)
=> [#<Event id: 390, user_id: 1, action: "uploaded", eventable_id: 34, eventable_type: "Node", created_at: "2015-12-19 05:57:46", updated_at: "2015-12-19 05:57:46">,
#<Event id: 391, user_id: 1, action: "uploaded", eventable_id: 35, eventable_type: "Node", created_at: "2015-12-19 06:12:48", updated_at: "2015-12-19 06:12:48">,
#<Event id: 392, user_id: 1, action: "uploaded", eventable_id: 36, eventable_type: "Node", created_at: "2015-12-19 06:18:40", updated_at: "2015-12-19 06:18:40">,
#<Event id: 394, user_id: 3, action: "uploaded", eventable_id: 38, eventable_type: "Node", created_at: "2015-12-22 08:53:33", updated_at: "2015-12-22 08:53:33">,
#<Event id: 395, user_id: 3, action: "uploaded", eventable_id: 39, eventable_type: "Node", created_at: "2015-12-22 09:50:36", updated_at: "2015-12-22 09:50:36">,
#<Event id: 399, user_id: 3, action: "uploaded", eventable_id: 43, eventable_type: "Node", created_at: "2015-12-22 11:32:52", updated_at: "2015-12-22 11:32:52">,
#<Event id: 400, user_id: 3, action: "favorited", eventable_id: 43, eventable_type: "Node", created_at: "2015-12-22 11:35:41", updated_at: "2015-12-22 11:35:41">,
#<Event id: 401, user_id: 3, action: "uploaded", eventable_id: 44, eventable_type: "Node", created_at: "2015-12-22 11:39:01", updated_at: "2015-12-22 11:39:01">]
[13] pry(main)> Event.where.not(eventable: node_ids)
Event Load (1.1ms) SELECT "events".* FROM "events" WHERE ("events"."eventable_id" NOT IN (38, 43, 39, 44, 34, 35, 36))
=> [#<Event id: 387, user_id: 1, action: "uploaded", eventable_id: 31, eventable_type: "Node", created_at: "2015-12-19 05:22:24", updated_at: "2015-12-19 05:22:24">,
#<Event id: 393, user_id: 3, action: "uploaded", eventable_id: 37, eventable_type: "Node", created_at: "2015-12-22 08:43:44", updated_at: "2015-12-22 08:43:44">,
#<Event id: 396, user_id: 3, action: "uploaded", eventable_id: 40, eventable_type: "Node", created_at: "2015-12-22 10:28:52", updated_at: "2015-12-22 10:28:52">,
#<Event id: 397, user_id: 3, action: "uploaded", eventable_id: 41, eventable_type: "Node", created_at: "2015-12-22 10:47:18", updated_at: "2015-12-22 10:47:18">,
#<Event id: 398, user_id: 3, action: "uploaded", eventable_id: 42, eventable_type: "Node", created_at: "2015-12-22 11:07:06", updated_at: "2015-12-22 11:07:06">]
[14] pry(main)> Event.where.not(eventable: node_ids).destroy_all
Event Load (0.7ms) SELECT "events".* FROM "events" WHERE ("events"."eventable_id" NOT IN (38, 43, 39, 44, 34, 35, 36))
(1.7ms) BEGIN
SQL (3.2ms) DELETE FROM "events" WHERE "events"."id" = $1 [["id", 387]]
(3.2ms) COMMIT
(0.1ms) BEGIN
SQL (0.3ms) DELETE FROM "events" WHERE "events"."id" = $1 [["id", 393]]
(0.3ms) COMMIT
(0.1ms) BEGIN
SQL (0.3ms) DELETE FROM "events" WHERE "events"."id" = $1 [["id", 396]]
(0.5ms) COMMIT
(0.1ms) BEGIN
SQL (0.2ms) DELETE FROM "events" WHERE "events"."id" = $1 [["id", 397]]
(0.5ms) COMMIT
(0.1ms) BEGIN
SQL (0.3ms) DELETE FROM "events" WHERE "events"."id" = $1 [["id", 398]]
(0.2ms) COMMIT
=> [#<Event id: 387, user_id: 1, action: "uploaded", eventable_id: 31, eventable_type: "Node", created_at: "2015-12-19 05:22:24", updated_at: "2015-12-19 05:22:24">,
#<Event id: 393, user_id: 3, action: "uploaded", eventable_id: 37, eventable_type: "Node", created_at: "2015-12-22 08:43:44", updated_at: "2015-12-22 08:43:44">,
#<Event id: 396, user_id: 3, action: "uploaded", eventable_id: 40, eventable_type: "Node", created_at: "2015-12-22 10:28:52", updated_at: "2015-12-22 10:28:52">,
#<Event id: 397, user_id: 3, action: "uploaded", eventable_id: 41, eventable_type: "Node", created_at: "2015-12-22 10:47:18", updated_at: "2015-12-22 10:47:18">,
#<Event id: 398, user_id: 3, action: "uploaded", eventable_id: 42, eventable_type: "Node", created_at: "2015-12-22 11:07:06", updated_at: "2015-12-22 11:07:06">]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment