17

所以我开始使用 Postgres JSON 数据类型,现在你可以用它做很多有趣的事情。在我的一个 Rails 应用程序中,它还不是 Rails 4(已添加对 Postgres JSON 的支持),我添加了一个 JSON 列,如下所示:

create_table :foo do |t|
  t.column :bar, :json
end

但我不知道如何为列设置默认值。我尝试了所有变体,例如{}, '{}',等'{}'::json'[]'::json但是当迁移运行时我得到一个错误,或者它根本不起作用,这意味着迁移运行但是,当我创建一个新的Foo,barnil

4

3 回答 3

31

虽然有点晚了,但这对我有用(需要 Postgres >= 9.3):

create_table :foo do |t|
  t.column :bar, :json
end

execute "ALTER TABLE foo ALTER COLUMN bar SET DEFAULT '[]'::JSON"

编辑:这个答案曾经提倡to_json('[]'::text)而不是'[]'::JSON- 感谢@Offirmo的提示。

旧方法的问题在于它实际上并没有像人们期望的那样将数组或对象定义为默认值,而是一个看起来像一个的标量(字符串)。为什么这很重要?

Postgres 允许将三种值插入 JSON 列:

  1. 对象

    INSERT INTO foo (bar) VALUE('{}')

  2. 数组

    INSERT INTO foo (bar) VALUE('[]')

  3. 标量

    INSERT INTO foo (bar) VALUE('"string"')

问题是如果你在同一列中混合这三种,你就失去了使用 JSON 运算符的能力。如果您使用先前提倡的方法设置默认值 '[]' 并查询数组元素,遇到具有标量默认值的单行将中止整个查询并出现错误:

=# SELECT * FROM foo WHERE bar->>1 = 'baz';
ERROR:  cannot extract element from a scalar
于 2013-12-23T15:13:06.887 回答
5

下面的代码适用于 PostgreSQL 9.3.4 和 Rails 3.2.17

class YourModel < ActiveRecord::Base
...
  serialize :your_column, JSON
  before_create do
    self.your_column ||= {}
  end
...
end

迁移代码

add_column :your_table, :your_column, :json
execute "ALTER TABLE your_table ALTER COLUMN your_column SET DEFAULT '{}'"
execute "UPDATE your_table SET your_column = '{}';"

应用程序.rb

config.active_record.schema_format = :sql
于 2014-04-13T21:11:40.200 回答
0

你基本上可以做这样的事情

create_table :foo do |t|
  t.column :bar, :json, default: []
end

default: []用或default: {}或任何其他你觉得舒服的东西陈述默认值 。

更新:请注意,这是针对 Rails 4+

于 2020-05-06T20:54:41.457 回答