Saturday, March 3, 2012

Delete Vs. Destroy In Rails

I’ve been writing this web app that has the following models: Order, Recipient, Message. An order has many recipients and a recipient has many messages. The recipients are also dependent upon the order and the messages are dependent upon the recipient.

In Ruby code this looks like:
Order.rb

class Order < ActiveRecord::Base
has_many :recipients, :dependent => :destroy
has_many :messages, :through => :recipients
end

Recipient.rb

class Recipient < ActiveRecord::Base
belongs_to :order
has_many :messages, :dependent => :destroy
end

The idea here is that when I delete an order, I also delete any associated recipients and any associated messages. My controller looked like this:

def delete
Order.delete(params[:id])
end

There are a couple things wrong with this. The first and most important thing is that when I delete a row in the order table, it leaves orphaned rows in the order and messages table. I want to delete these rows as well! The next thing is that this isn’t RESTful design. Instead of calling my method “delete,” let’s call it “destroy.” To fix the issue though, we need to use another method that has subtle difference than delete. Instead of delete, I should be using the destroy method. Why is that?

The delete method essentially deletes a row (or an array of rows) from the database. Destroy on the other hand allows for a few more options. First, it will check any callbacks such as before_delete, or any dependencies that we specify in our model. Next, it will keep the object that just got deleted in memory; this allows us to leave a message saying something like “Order #{order.id} has been deleted.” Lastly, and most importantly, it will also delete any child objects associated with that object!

Now my code in my controller looks like this.

def destroy
Order.destroy(params[:id])
end

Whenever I delete an order object, it will delete all child recipient and message rows in the database . This prevents any orphaned rows and allows for consistency in the database!