views:

2054

answers:

4

Hi folks,

I know this is probably on the Internet somewhere but I can't find the answer here on Stackoverflow so I thought I may boost up the knowledge base here a little.

I'm a newbie to Ruby and Rails but my company is getting pretty invested in it so I'm trying to get to know it in a little more detail.

It's been difficult for me to change my mindset to designing an application from the "model" rather the from the database, so I'm trying to figure out how would do all of the design work that I have classically done in the Database in the Rails model instead.

So the most recent task that I have given myself is to figure out how to configure a Rails database model to do cascading deletes? Is there an easy way of doing this? Or would I have to go into the MySql and set this up?

Thanks.

-Matt

+14  A: 

Yeah you can, if you are using a relationship like has_many you just do this

has_many :memberships, :dependent => :destroy

danmayer
Dan,So I guess my next question is if I run a db migrate command will that actually set that up in the db? Or is the cascading completely handled by rails?
matt_dev
Yes, it's handled by rails. (Do make sure you really always need to delete every related rows, though.)
Stein G. Strindhaug
@Matt - the has_many line should be in your model class, the migration won't add that for you.
Gareth
This a good example of the awesomeness of RoR.
allesklar
+2  A: 

It looks like this plugin might give you what you're looking for if you want the cascading deletes reflected in the actual database structure:

http://www.redhillonrails.org/foreign_key_migrations.html

Format for using this in a migration would be something like this:

create_table :orders do |t|
  t.column :customer_id, :integer, :on_delete => :set_null, :on_update => :cascade
  ...
end
Sean McMains
That link is dead but this is a newer alternative:http://github.com/matthuhiggins/foreigner
gdelfino
+3  A: 

you can also set the :dependent option to :delete_all. :delete_all will issue a single SQL statement to delete all child records. because of this using :delete_all may give you better performance.

has_many :memberships, :dependent => :delete_all
Mike Breen
Your explanation is confusing. A single SQL statement will be used, but the destroy method will not be called for each child row. You have to use destroy_all for that.
John Topley
@John - hope the edits clear up the confusion. thanks for pointing that out.
Mike Breen
@Mike - much better, thanks.
John Topley
+2  A: 

Just keep in mind that delete_all will not execute any callbacks (like before_destroy and after_destroy) on the child records.

Jarin Udom