7

I am currently trying to run this migration:

class AddDroppedProjectsCountToUser < ActiveRecord::Migration
  def self.up
    add_column :users, :dropped_projects, :integer, {:default=>0, :required=>true}
  end

  def self.down
    remove_column :users, :dropped_projects
  end
end

The column is added correctly, but none of the old records are populated with 0. They are nil. I have tried using default=>'0' as well, to no avail. Any idea why this might be happening? (Rails 3.0.3)


Edited to add: When I create a new user it works fine, and everything looks correct. It's just the old users that still have nil for that value in the table.

3 Answers 3

13

What happens if you say:

def self.up
  add_column :users, :dropped_projects, :integer, :null => false, :default => 0
end

instead? Without the :null=>false you're still allowing NULL in dropped_projects so there's no reason for PostgreSQL to make them 0. Also, I don't think :required is a valid option for add_column; since the options are just a simple Hash and add_column only looks for options it knows about, your stray :required option is silently ignored.

Sign up to request clarification or add additional context in comments.

4 Comments

Great Success! Thanks Mu. So weird that it takes all that just to fill some 0's.
@Dave G: Also see my little update about :required. The problem with NULL is that sometimes it means "unknown" and sometimes it means "not there", the database has no way of differentiated these two cases; if you don't explicitly say "no NULLs" then the DB can't know if the NULLs are default values or explicit NULLs.
It worked for me. What if you don't want to force no nulls? Is there another way to do it? What if you don't want to force a default, but just change the values for rows that are already in the database and subject to the migration?
@B Seven: Just leave the :null=>false out but that probably won't do anything to existing rows, you could always execute "UPDATE table ..." and do the update half with raw SQL; there's no good reason to be avoid SQL when it is the most direct and efficient way to get the job done.
3

you could do this:

(taken from http://apidock.com/rails/ActiveRecord/Migration)

Using a model after changing its table

Sometimes you’ll want to add a column in a migration and populate it immediately after. In that case, you’ll need to make a call to Base#reset_column_information in order to ensure that the model has the latest column data from after the new column was added. Example:

class AddPeopleSalary < ActiveRecord::Migration
  def up
    add_column :people, :salary, :integer
    Person.reset_column_information
    Person.all.each do |p|
      p.update_column :salary, SalaryCalculator.compute(p)
    end
  end
end

1 Comment

What happens if you have a huge collection of existing people on production or so?
1

I believe this is due to the fact that you are changing the old migration, instead of creating a new. In this case, the solution is to check the schema file (schema.rb). It does not change automatically, and add

t.integer "dropped_projects", default: 0, null: false

Comments

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.