Last active
December 23, 2015 11:30
-
-
Save marcamillion/213fd304e6c6518aae55 to your computer and use it in GitHub Desktop.
Easily Find Polymorphically Associated Records whose destroy callbacks were not called
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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