web-dev-qa-db-ja.com

Rails <4でPostgresJSON列のデフォルト値を設定します

だから私はPostgresJSONデータ型を使い始めました それを使ってできる楽しいことがたくさんあります 。私のRailsまだRails 4(ここで Postgres JSONのサポートが追加されました )のアプリの1つでこのようなJSON列:

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

しかし、列のデフォルト値を設定する方法がわかりません。 {}'{}''{}'::json'[]'::jsonなどのすべてのバリエーションを試しましたが、移行の実行時にエラーが発生するか、単に機能しないため、移行は実行されますが、新しいFooを作成すると、barnilになります。

15
Manuel Meurer

少し遅れましたが、これは私にとってはうまくいきました(Postgres> = 9.3が必要です):

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

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

EDIT:この回答は、_'[]'::JSON_ではなくto_json('[]'::text)を提唱するために使用されていました-ありがとう @ Offirmo ヒント。

古いメソッドの問題は、実際には配列またはオブジェクトをデフォルト値として定義していなかったのですが、scalar(string)は1つのように見えました。なぜそれが重要なのですか?

Postgresでは、次の3種類の値をJSON列に挿入できます。

  1. オブジェクト

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

  2. 配列

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

  3. スカラー

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

問題は、これら3種類を同じ列に混在させると、JSON演算子を使用できなくなることです。以前に推奨されたメソッドを使用してデフォルトの「[]」を設定し、配列要素を照会した場合、スカラーのデフォルト値を持つ単一の行に遭遇すると、クエリ全体がエラーで中止されます。

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

以下のコードはPostgreSQL9.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
5
Anton Orel