Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails ActiveRecord: pretty errors when deleting dependent entities with foreign keys constraints

I have in Rails application several tables with foreign keys constraints. For example, every order belongs to a customer. There's a costumer_id column on the orders table.

When I delete a costumer with a placed order, because of database constraints, MySQL returns the error:

Mysql::Error: Cannot delete or update a parent row: a foreign key constraint fails (orders, CONSTRAINT orders_ibfk_2 FOREIGN KEY (customer_id) REFERENCES customers (id))

And the ugly error pops up on the screen, with all stacktrace and those stuff ActiveRecord::StatementInvalid in DevicesController#destroy ...

I'd like to know if there's an elegant way to treat these constraint errors, giving a beautiful like "you can delete this object because it is associated to X"

How could I do it?

like image 492
Daniel Cukier Avatar asked Feb 18 '10 17:02

Daniel Cukier


People also ask

How to set the name of a foreign key in rails?

By convention, Rails assumes that the column in the join table used to hold the foreign key pointing to this model is the name of this model with the suffix _id added. The :foreign_key option lets you set the name of the foreign key directly:

How to define primary keys in rails migrations?

You need to explicitly define them as part of your migrations. By convention, Rails assumes that the id column is used to hold the primary key of its tables. The :primary_key option allows you to specify a different column. For example, given we have a users table with guid as the primary key.

How to make efficient use of active record associations in rails?

Here are a few things you should know to make efficient use of Active Record associations in your Rails applications: All of the association methods are built around caching, which keeps the result of the most recent query available for further operations. The cache is even shared across methods. For example:

Should you delete the children of a foreign key?

-- Always delete the children first. Again, this is a pretty simple example, but try thinking about it when you have a whole series of foreign keys. Say half a dozen, or even more, of them. All of a sudden, if you aren’t familiar with the structure of your database it could take some time to get that order right.


1 Answers

React in the before destroy callback:

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

  private

  def no_referenced_orders
    return if orders.empty?

    errors.add_to_base("This customer is referenced by order(s): #{orders.map(&:number).to_sentence}")
    false # If you return anything else, the callback will not stop the destroy from happening
  end
end

In the controller:

class CustomersController < ApplicationController
  def destroy
    @customer = Customer.find(params[:id])
    if @customer.destroy then
      redirect_to customers_url
    else
      render :action => :edit
    end
  end
end
like image 71
François Beausoleil Avatar answered Oct 17 '22 19:10

François Beausoleil