2013-10-31 59 views
13

所以我开始使用Postgres JSON数据类型,现在是there's a lot of fun stuff you can do with it。 在我的Rails应用这是一个尚未轨道4(其中support for Postgres JSON has been added)我加了一个JSON列如下:在Rails中为Postgres JSON列设置默认值<4

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

,但我想不出如何设置列的默认值。 我尝试了所有的变化一样{}'{}''{}'::json'[]'::json等,但我要么得到一个错误,当迁移运行,或者它根本不起作用,这意味着迁移运行,但是,当我创建一个新的Foobarnil

+1

您是否尝试过在模型中手动设置默认值? AR通常会屠杀或忽略它不了解的默认值。 –

+0

是的,现在我使用'after_initialize'回调,但我通常不喜欢那些...... –

+0

尝试'“”',我相信这是什么用于hstore表示一个空的散列 –

回答

24

虽然晚了一点,这个工作对我来说(需要的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 
+1

我得到以下错误:'PG :: UndefinedFunction:错误:函数to_json(文本)不存在 提示:没有函数匹配给定的名称和参数类型。您可能需要添加明确的类型转换.' –

+0

@ManuelMeurer我相信您需要最新版本的Postgres;我在9.3.2上。 – janfoeh

+1

是的,它是在9.3中加入的。你能在你的答案中提到吗?然后我可以接受它。 –

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