Ответ 1
Хотя немного поздно, это сработало для меня (требуется Postgres >= 9.3):
create_table :foo do |t|
t.column :bar, :json
end
execute "ALTER TABLE foo ALTER COLUMN bar SET DEFAULT '[]'::JSON"
EDIT: этот ответ использовался для to_json('[]'::text)
вместо '[]'::JSON
- @Offirmo для подсказки.
Проблема со старым методом заключалась в том, что он фактически не определял массив или объект как значение по умолчанию, как можно было бы ожидать, а скаляр (строка), который был похож на один. Почему это имеет значение?
Postgres позволяет вставлять три типа значений в столбцы JSON:
-
Объекты
INSERT INTO foo (bar) VALUE('{}')
-
Массивы
INSERT INTO foo (bar) VALUE('[]')
-
Скаляры
INSERT INTO foo (bar) VALUE('"string"')
Проблема заключается в том, что если вы смешиваете эти три вида в одном столбце, вы теряете возможность использовать JSON-операторы. Если вы установите значение по умолчанию "[]" с использованием ранее защищенного метода и запросили для элемента массива, столкновение с одной строкой со скалярным значением по умолчанию приведет к прерванию всего запроса с ошибкой:
=# SELECT * FROM foo WHERE bar->>1 = 'baz';
ERROR: cannot extract element from a scalar