Skip to content

Instantly share code, notes, and snippets.

@badosu
Last active August 29, 2015 14:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save badosu/cd7a018f7f7d45836903 to your computer and use it in GitHub Desktop.
Save badosu/cd7a018f7f7d45836903 to your computer and use it in GitHub Desktop.
After destroy hook usage example for Sequel
require 'sequel'
require 'sqlite3'
DB = Sequel.connect 'sqlite:/'
DB.create_table?(:people) do
primary_key :id
String :name
foreign_key :address_id, :addresses
end
DB.create_table?(:addresses) do
primary_key :id
String :street
end
class Person < Sequel::Model
many_to_one :address
def after_destroy
address.destroy if Person.where(address_id: address_id).empty?
end
end
class Address < Sequel::Model
one_to_many :people
end
address = Address.create(street: "Elm Street")
adam = Person.create(name: "Adam", address: address)
john = Person.create(name: "John", address: address)
puts "Before destroying people: #{Address.count}"
adam.destroy
puts "After destroying adam: #{Address.count}"
john.destroy
puts "After destroying john: #{Address.count}"
# Should output:
#
# Before destroying people: 1
# After destroying adam: 1
# After destroying john: 0
@cristianrasch
Copy link

It's a real simple change, take this line out:

foreign_key :address_id, :addresses

and replace it with this one instead:

foreign_key :address_id, :addresses, null: false, on_delete: :cascade

Now every time you delete a parent object (Person), their addresses are mass-deleted automatically for you :) - it also has the added benefits of referential integrity

@badosu
Copy link
Author

badosu commented Aug 15, 2014

Thanks for the comment! :)

So, I applied your change but it did not work as intended:

Before destroying people: 1
After destroying adam: 1
After destroying john: 1

I guess it's because I do not want specifically to remove an address every time a person is deleted, I want to remove an address always when the last person that belonged to that address is deleted.

@cristianrasch
Copy link

Oh I see. Addresses is not something I'd share between users, but I guess you were just illustrating the point, right? Even though, I'd rather use what I call a use case to encapsulate the person[+address] deletion process, at least that's how I see it now. Models are just for hitting the database, I strive to use regular ruby classes for implementing application-specific logic.

I have some good examples I'd like to bounce off you (and anyone else you'd like to listen). Please remind me to do so the next time we see each other :)

@pangur
Copy link

pangur commented Aug 17, 2014

badosu was kindly helping me out, cristianrasch. As it happens, what he proposed works the way I had hoped.

As a parish minister, it works well for me to have addresses in a different table from people. The reason for that is that the addresses are generally geographically grouped into pastoral+administrative districts. It is often useful to know how many addresses are in a district as well as how many people are in a household. It is more helpful for my purpose to have a list of unique addresses for a district than to list multi-occupant addresses for each occupant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment