1

I'm trying to write a migration and it looks something like this:

class AddStatusToWorks < ActiveRecord::Migration
  def self.up
    change_table :works do |t|
        t.string :status
    end
  end

  def self.down
    change_table :works do |t|
        t.remove :status
    end
  end
end

Thing is, I want to set different default values for "status" based on a boolean value that's already in the table, "complete." If complete = true, status = "complete." If not, status = "work in progress." (The reason I want a string instead of keeping complete as the boolean is because I want there to be able to be more than two possibilites for status.) Any idea how to do that? Do I just stick an if statement in there like this

change_table :works do |t|
        t.string :status
           if (:complete == true)
               :value => "complete"
           else
               :value => "wip"
end

Er, so that doesn't look quite right. I googled a bit and found that you can set :default values, but that's not quite what I'm going for. Any ideas/help would be lovely. Thanks!

6
  • So you want to initialize status based on the current value of complete? What about new rows? Commented Sep 27, 2012 at 2:05
  • Er...new rows? I am mildly clueless on this front, sorry. Commented Sep 27, 2012 at 2:09
  • Wait! Do you mean new rows as in future entries to the database? In those cases, the user would set a value whenever they create a new work. It's just that there are a lot of entries already in the database and I'd like to know if there's an automatic way to set their values. Commented Sep 27, 2012 at 2:19
  • Yes, that's what I mean by new rows. Commented Sep 27, 2012 at 2:36
  • Heh, I knew I was missing something. But I caught on eventually, that counts for something, right? Looking over your other response now! Commented Sep 27, 2012 at 2:46

2 Answers 2

2

You don't need a default at all, you just need to add the new column and give it values. Something like this should work:

def self.up
  change_table :works do |t|
      t.string :status
  end
  Works.reset_column_information
  Works.where(:complete => true).update_all(:status => 'complete')
  Works.where(:complete => [false, nil]).update_all(:status => 'wip')
end

See the Migrations Guide for information on reset_column_information.

You could also do it straight in the database but you have to be careful about different boolean representations (PostgreSQL wants 't' and 'f', MySQL wants 1 and 0, SQLite wants 1 and 0 but Rails mistakenly uses 't' and 'f', ...):

t = connection.quote(true)
connection.execute(%Q{
  update works
  set status = case complete
    when #{t} then 'complete'
    else 'wip'
  end
})
Sign up to request clarification or add additional context in comments.

2 Comments

So you can use "where" to pick out info, not if/else. Oh, that looks brilliant, exactly what I'm looking for. Thank you so much!
Right, you use where to tell ActiveRecord what you're looking for and then update_all to turn that into an UPDATE ... inside the database.
0

Remember that default values are created immediately when the record is created, and thus don't yet have values for fields w/o defaults. You'll likely want to move this sort of logic to your model. Perhaps in an ActiveRecord callback, i.e. before_validation or before_save.

2 Comments

Ahh...hmm. Okay. So basically, create the table without the if statement and then in the model, do something like this: def edit_status if self.complete = true self.status = "complete" else self.status = "wip" then before_save :edit_status Like that?
welp, that lost a lot of the formatting. Eh. At any rate, there is not way to do it directly in the migration? Because the thing is I want the default values to be set once and then the user can directly edit them after that. If I use before_save, won't that trigger every time the user edits anything about :works?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.