views:

19

answers:

3

I have a Note model, with a note_type field. How do write a migration that will remove Note records from the database if the type is "short_note"?

A: 
def self.up
  execute "DELETE FROM notes WHERE note_type = 'short_note'"
end

:-P

Just kidding. I'm sure you could do this:

Note.delete_all :note_type => 'short_note'
Chris Jester-Young
A: 

In the self.up:

Note.delete_all("type = 'short_note'");

or use destroy_all which will call the record's destroy method and callbacks (before_destroy and after_destroy):

Note.destroy_all("type = 'short_note'");
Trevor
I vastly prefer to use the hash and/or array forms where possible, and only use the string form when I must write straight SQL. That way nobody is tempted to refactor it into a form that is open to SQL injection in case they want to delete a parameterised type.
Chris Jester-Young
+2  A: 

The code itself is simple.

Note.delete_all :type => 'short_note'

(If notes have destroy callbacks, you'll need to run destroy_all instead. It's slower because they're deleted one-by-one, but can sometimes produce better data integrity.)

However, I imagine you're a bit more worried about the down migration than the up migration. It is an irreversible transformation by nature. The answer to that particular bit of the question is that your migration should raise an ActiveRecord::IrreversibleMigration exception.

However, whenever you write an irreversible migration, it's important to consider why you're doing it. Depending on your situation, maybe it's more appropriate to just run that particular command in the console upon deploy to production than to make that migration part of your application's very definition.

Matchu
No, don't specify the `:conditions` key! The `delete_all` method just takes conditions, not a general `find` spec.
Chris Jester-Young
@Chris Jester-Young: good catch :) Fixed.
Matchu