ChatGPT解决这个技术问题 Extra ChatGPT

Rails migrations: Undo default setting for a column

I have the problem, that I have an migration in Rails that sets up a default setting for a column, like this example:

def self.up
  add_column :column_name, :bought_at, :datetime, :default => Time.now
end

Suppose, I like to drop that default settings in a later migration, how do I do that with using rails migrations?

My current workaround is the execution of a custom sql command in the rails migration, like this:

def self.up
  execute 'alter table column_name alter bought_at drop default'
end

But I don't like this approach, because I am now dependent on how the underlying database is interpreting this command. In case of a change of the database this query perhaps might not work anymore and the migration would be broken. So, is there a way to express the undo of a default setting for a column in rails?


J
Joshua Pinter

Rails 5+

def change
  change_column_default( :table_name, :column_name, from: nil, to: false )
end

Rails 3 and Rails 4

def up
  change_column_default( :table_name, :column_name, nil )
end

def down
  change_column_default( :table_name, :column_name, false )
end

In postgres, this won't actually drop the default for CHARACTER VARYING columns, just set it to NULL::character varying.
In more recent versions, you can make it reversible. For example: change_column_default(:table_name, :column_name, from: nil, to: false)
@AttilaO. I've had success running ALTER TABLE table_name ALTER COLUMN type DROP DEFAULT, no need to set it to NULL I think.
FYI, it looks like the reversible version that @Mark mentions was added in Rails 5+, so anything below that, you won't be able to use it.
S
Serx

Sounds like you're doing the right thing with your 'execute', as the docs point out:

change_column_default(table_name, column_name, default) Sets a new default value for a column. If you want to set the default value to NULL, you are out of luck. You need to DatabaseStatements#execute the appropriate SQL statement yourself. Examples change_column_default(:suppliers, :qualification, 'new') change_column_default(:accounts, :authorized, 1)


Thanks! I haven't found this hint in the docs by myself! Hopefull they build in the dropping of default values into migrations in future versions of rails.
This is not true anymore as of Rails 3.1.0, cfr. apidock.com/rails/v3.1.0/ActiveRecord/ConnectionAdapters/…
A
Alex Fortuna

The following snippet I use to make NULL columns NOT NULL, but skip DEFAULT at schema level:

def self.up
  change_column :table, :column, :string, :null => false, :default => ""
  change_column_default(:table, :column, nil)
end

I don't see added value in this answer since the accepted one states the same.
P
Pardeep Dhingra

Rails 4

change_column :courses, :name, :string, limit: 100, null: false

This one adds NOT NULL constraint, it has nothing to do with DEFAULT
has nothing to do with DEFAULT +1