Добавить значение по умолчанию в столбец с помощью миграции


276

Как добавить значение по умолчанию для столбца, который уже существует в процессе миграции?

Вся документация, которую я могу найти, показывает, как это сделать, если столбец еще не существует, но в этом случае он существует.

Ответы:


352

Вот как вы должны это сделать:

change_column :users, :admin, :boolean, :default => false

Но некоторые базы данных, такие как PostgreSQL, не будут обновлять поле для ранее созданных строк, поэтому убедитесь, что вы обновляете поле также вручную при переносе.


14
Если вам нужны обратимые миграции, поместите это в upблок, а не в changeблок. Вы можете оставить downблок пустым. Таблица не вернется к исходному состоянию, но миграцию можно откатить.
ИАМНАН

1
Сохранит ли это данные нетронутыми?
Марко Принс

2
На PostgreSQL, да, я не знаю, что произойдет с другими базами данных.
Маурисио Линьярес

1
Что вы имеете в виду, когда говорите «убедитесь, что вы обновляете поле вручную при переносе»? Как это сделать?
Дэвид Аргайл Такер

7
Я попробовал это на PostgreSQL, и он обновил ранее созданные поля.
Абузар Раджаби

190
change_column_default :employees, :foreign, false

1
@DenisLins Я согласился с вами, поэтому я провел некоторое исследование, чтобы выяснить, почему это не так, и оказалось, что есть вероятность, что определенный адаптер базы данных не поддерживает его, поскольку он реализован на этом уровне. Принятый ответ остается самой безопасной ставкой, пока он не будет реализован в абстрактной модели. apidock.com/rails/ActiveRecord/ConnectionAdapters/…
natchiketa

5
Кроме того, вам нужно указать a, from:и to:если вы хотите, чтобы он был обратимым :)
radubogdan

5
Использование fromиto было добавлено в Rails 5+ в этом коммите: github.com/rails/rails/pull/20018/files
Джошуа Пинтер

116

Для Rails 4+ используйтеchange_column_default

def change
  change_column_default :table, :column, value
end

1
Это прекрасно, особенно если у вас есть миграция, которая добавляет столбец и устанавливает значения по умолчанию для существующих записей. Например: def change `add_column: foos,: name, default:" что-то для существующих значений "` `change_column_default: foos,: name, default:" "`end
user1491929

2
Эта миграция имеет странное поведение. В твоем примере это необратимо. edgeguides.rubyonrails.org/active_record_migrations.html рекомендую использовать его следующим образом: change_column_default :products, :approved, from: true, to: false- но он тоже не работает.
Илья Кригузов

не может откат с помощью этого?
aldrien.h

Обычно так, да, почти для любого предложения «Изменить», поскольку все предыдущие состояния обычно явные, такие как наличие столбца, его тип и т. Д. Изменение можно откатить, как показано там, если и только если было действительное явное значение по умолчанию ранее. Поскольку обычно значения по умолчанию не определены, у вас может возникнуть проблема.
Элиндор

48

Использование def changeозначает, что вы должны написать миграции, которые являются обратимыми. И change_columnне является обратимым. Вы можете идти вверх, но не можете идти вниз, так какchange_column это необратимо.

Вместо этого, хотя это может быть пара дополнительных строк, вы должны использовать def up иdef down

Так что если у вас есть столбец без значения по умолчанию, то вы должны сделать это, чтобы добавить значение по умолчанию.

def up
  change_column :users, :admin, :boolean, default: false
end

def down
  change_column :users, :admin, :boolean, default: nil
end

Или, если вы хотите изменить значение по умолчанию для существующего столбца.

def up
  change_column :users, :admin, :boolean, default: false
end

def down
  change_column :users, :admin, :boolean, default: true
end

37

** Рельсы 4.X + **

Начиная с Rails 4, вы не можете сгенерировать миграцию для добавления столбца в таблицу со значением по умолчанию . Следующие шаги добавляют новый столбец в существующую таблицу со значением по умолчанию true или false.

1. Запустите миграцию из командной строки, чтобы добавить новый столбец.

$ rails generate migration add_columnname_to_tablename columnname:boolean

Приведенная выше команда добавит новый столбец в вашу таблицу.

2. Установите для нового значения столбца значение TRUE / FALSE, отредактировав новый созданный файл миграции.

class AddColumnnameToTablename < ActiveRecord::Migration
  def change
    add_column :table_name, :column_name, :boolean, default: false
  end
end

** 3. Чтобы внести изменения в таблицу базы данных приложения, выполните следующую команду в терминале **

$ rake db:migrate

Чем это отличается от рельсов 3+ или 2+?
Рубин Racer

2
Кто-нибудь знает, было ли это включено в Rails 5?
Самбекер

9

Выполнение:

rails generate migration add_column_to_table column:boolean

Это сгенерирует эту миграцию:

class AddColumnToTable < ActiveRecord::Migration
  def change
    add_column :table, :column, :boolean
  end
end

Установите значение по умолчанию, добавив: default => 1

add_column: table,: column,: boolean,: default => 1

Бегать:

грабли дБ: мигрировать


2
Теперь значение по умолчанию 1 не совсем булево;) Кроме того, этот экзамен добавляет новый столбец вместо изменения существующего столбца, чего и хотел достичь OP
radiospiel

@radiospiel На самом деле, 1 тоже логическое значение :)
kinduff

Вам также нужно будет создать запись в таблице внешнего ключа с идентификатором 1, чтобы это работало, чтобы избежать Key is not present in table error.
Обещание Престон

-50

Вот что вы можете сделать:

class Profile < ActiveRecord::Base
  before_save :set_default_val

  def set_default_val
    self.send_updates = 'val' unless self.send_updates
  end
end

РЕДАКТИРОВАТЬ: ... но, очевидно, это ошибка новичка!


Лучше, если вы установите значение по умолчанию в схеме какbefore_save
rigelstpierre

6
Какое ужасное предложение
svelandiag

согласился, это действительно ужасно
Houcheng

3
ой, у вас много тепла для того, чтобы делать что-то на уровне модели вместо уровня базы данных. -38 это легендарная оценка.
Нуреттин

1
какая ошибка новичка ... ;-)
webaholik
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.