Rails Dependent Associations
I often find that the dependent parameter gets forgotten on projects. This is easy to do if you're new to Rails. When dependent is not set, nothing terrible happens at first… but once you get further into a project you will start seeing this:
The cause of the error is that the parent record no longer exists, but the foreign key still references the parent object.
To stop this from happening you can use the dependent option with
Dependent simply tells destroy what to do with child records. The available dependent options are as follows:
The destroy option is the most common in a Rails app, as it is the most likely scenario. For example, when you delete a post, you probably want to remove the comments as well.
Now when you delete the post the comments are also deleted. Any callback's that are defined will also be fired.
The destroy option should be a default in Rails because of the ethos of convention over configuration. Currently what happens is the child record doesn't have its foreign key nullified, which is the next option we will look at.
I don't think we could change this default now as it would cause unexpected behaviors when updating to a new Rails version.
Nullify is the opposite to destroy, it means the child record is not destroyed after Active Record removes the parent. Curiously, not that many developers seem to know that this option exist.
Now when you delete the post the comment is not deleted. Instead the foreign key is set to Null.
This is better than leaving the foreign key set but will still cause an error if you try to access the post.
The delete all option is the same as destroy but no callbacks will be executed.
Restrict with Exception
This is an option that I have to admit I’ve never seen or used before writing this article. Restrict with exception raises an exception when destroy is called on a parent record with children. The parent will only be deleted if the parent doesn't have associated children.
I can imagine it to be useful if you wanted to protect against posts with comments being deleted.
As you can see this raises an ActiveRecord::DeleteRestrictionError exception if a comment exists.
Restrict with Error
The last option is restrict with error which sets an error on the parent record if the parent has child records associated.
Active Record has added an error to the errors attribute in the same way as a validation error would be added. I think this would work well with validations as you can display this error to the admin trying to delete the post. Restrict with error could be a replacement to doing a custom validation rule in less code. The downside you would lose the if/unless functionality available in validation.
I know that the dependent parameter is not the most exciting thing to read about but knowing the less known features in a framework can save you time when working on your next amazing feature.