Добавление: default => true для логического значения в существующем столбце Rails

160

Я видел несколько вопросов (а именно этот ) здесь, в SO, о добавлении логического значения по умолчанию в существующий столбец. Так что я попробовал change_columnпредложение, но я не должен делать это правильно.

Я попытался:

$ change_column :profiles, :show_attribute, :boolean, :default => true

Который возвращается -bash: change_column: command not found

Я тогда побежал:

$ rails g change_column :profiles, :show_attribute, :boolean, :default => true

...и

$ rails change_column :profiles, :show_attribute, :boolean, :default => true

Затем побежал rake db:migrate, но ценность для :show_attributeосталась nil. В вопросе, на который я ссылался выше, говорится, что в PostgreSQL вам необходимо обновить его вручную. Так как я использую PostgreSQL, я добавил следующее в свою create_profilesмиграцию:

t.boolean :show_attribute, :default => true

Может кто-нибудь сказать мне, что я здесь делаю не так?

tvalent2
источник

Ответы:

314

change_columnэто метод ActiveRecord::Migration, так что вы не можете так его называть в консоли.

Если вы хотите добавить значение по умолчанию для этого столбца, создайте новую миграцию:

rails g migration add_default_value_to_show_attribute

Затем в миграции создано:

# That's the more generic way to change a column
def up
  change_column :profiles, :show_attribute, :boolean, default: true
end

def down
  change_column :profiles, :show_attribute, :boolean, default: nil
end

ИЛИ более конкретный вариант:

def up
    change_column_default :profiles, :show_attribute, true
end

def down
    change_column_default :profiles, :show_attribute, nil
end

Тогда беги rake db:migrate.

Это ничего не изменит на уже созданные записи. Для этого вам нужно создать rake taskили просто зайти rails consoleи обновить все записи (что я бы не рекомендовал в производстве).

Когда вы добавили t.boolean :show_attribute, :default => trueв create_profilesмиграцию, ожидается, что она ничего не сделала. Выполняются только те миграции, которые еще не были выполнены. Если вы начали с новой базы данных, то по умолчанию будет установлено значение true.

Робин
источник
2
Этот вызов change_column должен быть в upметоде миграции, который является новым классом, который будет сгенерирован в db / migrate /. ( downМетод должен быть написан, чтобы отменить то, что upделает.) Затем внесите это изменение rake db:migrate.
rkb
Ааа, это имеет больше смысла RKB. Спасибо!
tvalent2
это не работало для меня, пока я не написал def self.upиdef self.down
Камил Сзот
Вы, вероятно, используете более старую версию рельсов тогда. Я думаю, что этот синтаксис существует с 3.1.
Робин
А в Rails 5 вы пропускаете _attribute, поэтому он должен просто сказать showили как там будет имя столбца.
Лабиринт
95

В качестве варианта принятого ответа вы также можете использовать change_column_defaultметод при миграции:

def up
  change_column_default :profiles, :show_attribute, true
end

def down
  change_column_default :profiles, :show_attribute, nil
end

Rails API-документы

Себастьян Пуйе
источник
1
Это гарантирует, что вы не будете случайно изменять какие-либо другие свойства столбца
Брайан Лоу
1
А в Rails 5 вы пропускаете _attribute, поэтому он должен просто сказать showили как там будет имя столбца.
Лабиринт
1
@labyrinth Что ты имеешь в виду? show_attribute это название колонки, я не думаю, что rails 5 имеет к этому какое-то отношение, верно?
Робин
34

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

change_column_null :products, :name, false

Рельсы 5:

change_column_default :products, :approved, from: true, to: false

http://edgeguides.rubyonrails.org/active_record_migrations.html#changing-columns

Рельсы 4.2:

change_column_default :products, :approved, false

http://guides.rubyonrails.org/v4.2/active_record_migrations.html#changing-columns

Это отличный способ избежать просмотра ваших миграций или схемы спецификаций столбцов.

fbelanger
источник
Осторожно, это из документации Rails 5. В Rails 4.2 эта версия не принимает хеш, но в качестве третьего параметра используется абсолютно новое значение по умолчанию. guides.rubyonrails.org/v4.2/…
Clamoris
Что касается Rails 5, то и то, и другое кажется наиболее правильным, например, null: falseи в default: :somethingосновном
Дориан
1

Кроме того, согласно документу:

по умолчанию нельзя указать через командную строку

https://guides.rubyonrails.org/active_record_migrations.html

Так что нет готового рельса генератора. Как указано в ответах выше, вы должны вручную заполнить файл миграции с помощью change_column_defaultметода.

Вы можете создать свой собственный генератор: https://guides.rubyonrails.org/generators.html

Margotte
источник
1

Если вы только что выполнили миграцию, вы можете выполнить откат, а затем снова выполнить миграцию.

Для отката вы можете сделать столько шагов, сколько захотите:

rake db:rollback STEP=1

Или, если вы используете Rails 5.2 или новее:

rails db:rollback STEP=1

Затем вы можете просто выполнить миграцию снова:

def change
  add_column :profiles, :show_attribute, :boolean, default: true
end

Не забудьте rake db:migrateи если вы используете герокуheroku run rake db:migrate

BM
источник
0
change_column :things, :price_1, :integer, default: 123, null: false

Кажется, это лучший способ добавить значение по умолчанию к существующему столбцу, которого еще нет null: false.

В противном случае:

change_column :things, :price_1, :integer, default: 123

Некоторые исследования, которые я провел по этому вопросу:

https://gist.github.com/Dorian/417b9a0e1a4e09a558c39345d50c8c3b

Дориан
источник
0

Если вы не хотите создавать другой файл миграции для небольшого недавнего изменения - из Rails Console:

ActiveRecord::Migration.change_column :profiles, :show_attribute, :boolean, :default => true

Затем выйдите и снова войдите в консоль rails, чтобы изменения в DB вступили в силу. Тогда, если вы сделаете это ...

Profile.new()

Вы должны увидеть значение по умолчанию "show_attribute" как true.

Для существующих записей, если вы хотите сохранить существующие "ложные" настройки и обновить только значения "nil" до новых значений по умолчанию:

Profile.all.each{|profile| profile.update_attributes(:show_attribute => (profile.show_attribute == nil ? true : false))  }

Обновите миграцию, которая создала эту таблицу, чтобы любые будущие сборки БД получали ее с самого начала. Также запустите тот же процесс на всех развернутых экземплярах БД.

При использовании метода «new dbigration» вы можете обновить существующие nil-значения в этой миграции.

JosephK
источник