在Rails<中设置Postgres JSON列的默认值4

时间:2013-10-31 19:44:08

标签: ruby-on-rails json ruby-on-rails-3.2 rails-postgresql pg

所以我开始使用Postgres JSON数据类型,现在是there's a lot of fun stuff you can do with it。 在我的一个Rails应用程序中还没有Rails 4(其中support for Postgres JSON has been added)我添加了一个JSON列,如下所示:

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

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

3 个答案:

答案 0 :(得分:25)

虽然有点晚,但这对我有用(需要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"')

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

    =# SELECT * FROM foo WHERE bar->>1 = 'baz';
    ERROR:  cannot extract element from a scalar
    

答案 1 :(得分: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 = '{}';"

application.rb中

config.active_record.schema_format = :sql

答案 2 :(得分:0)

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

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

使用default: []default: {}或您认为合适的其他任何方式说明默认值。

更新:请注意,这适用于Rails 4 +