How do I prevent deletion of parent if it has child records?

Ruby on-RailsModelAssociations

Ruby on-Rails Problem Overview


I have looked through the Ruby on Rails guides and I can't seem to figure out how to prevent someone from deleting a Parent record if it has Children. For example. If my database has CUSTOMERS and each customer can have multiple ORDERS, I want to prevent someone from deleting a customer if it has any orders in the database. They should only be able to delete a customer if it has no orders.

Is there a way when defining the association between models to enforce this behavior?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

class Customer < ActiveRecord::Base
  has_many :orders, :dependent => :restrict # raises ActiveRecord::DeleteRestrictionError

Edit: as of Rails 4.1, :restrict is not a valid option, and instead you should use either :restrict_with_error or :restrict_with_exception

Eg.:

class Customer < ActiveRecord::Base
  has_many :orders, :dependent => :restrict_with_error

Solution 2 - Ruby on-Rails

You could do this in a callback:

class Customer < ActiveRecord::Base
  has_many :orders
  before_destroy :check_for_orders

  private

  def check_for_orders
    if orders.count > 0
      errors.add_to_base("cannot delete customer while orders exist")
      return false
    end
  end
end

EDIT

see this answer for a better way to do this.

Solution 3 - Ruby on-Rails

Try using filters to hook in custom code during request processing.

Solution 4 - Ruby on-Rails

One possibility would be to avoid providing your users a link to deletion in this scenario.

link_to_unless !@customer.orders.empty?

Another way would be to handle this in your controller:

if !@customer.orders.empty?
  flash[:notice] = "Cannot delete a customer with orders"
  render :action => :some_action
end

Or, as Joe suggests, before_filters could work well here and would probably be a much more DRY way of doing this, especially if you want this type of behavior for more models than just Customer.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRobView Question on Stackoverflow
Solution 1 - Ruby on-RailsMauroView Answer on Stackoverflow
Solution 2 - Ruby on-RailszeteticView Answer on Stackoverflow
Solution 3 - Ruby on-RailsJoseph WeissmanView Answer on Stackoverflow
Solution 4 - Ruby on-RailsSamoView Answer on Stackoverflow