Skip to content

Commit

Permalink
Merge pull request #16220 from pcreux/postgresql-jsonb-support
Browse files Browse the repository at this point in the history
Add support for Postgresql JSONB
  • Loading branch information
senny committed Jul 25, 2014
2 parents 75eddfb + 99b82fd commit 1ec601b
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 9 deletions.
10 changes: 10 additions & 0 deletions activerecord/CHANGELOG.md
@@ -1,3 +1,13 @@
* Add support for Postgresql JSONB.

Example:

create_table :posts do |t|
t.jsonb :meta_data
end

*Philippe Creux*, *Chris Teague*

* `db:purge` with MySQL respects `Rails.env`.

*Yves Senn*
Expand Down
Expand Up @@ -14,6 +14,7 @@
require 'active_record/connection_adapters/postgresql/oid/inet'
require 'active_record/connection_adapters/postgresql/oid/integer'
require 'active_record/connection_adapters/postgresql/oid/json'
require 'active_record/connection_adapters/postgresql/oid/jsonb'
require 'active_record/connection_adapters/postgresql/oid/money'
require 'active_record/connection_adapters/postgresql/oid/point'
require 'active_record/connection_adapters/postgresql/oid/range'
Expand Down
@@ -0,0 +1,23 @@
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class Jsonb < Json # :nodoc:
def type
:jsonb
end

def changed_in_place?(raw_old_value, new_value)
# Postgres does not preserve insignificant whitespaces when
# roundtripping jsonb columns. This causes some false positives for
# the comparison here. Therefore, we need to parse and re-dump the
# raw value here to ensure the insignificant whitespaces are
# consitent with our encoder's output.
raw_old_value = type_cast_for_database(type_cast_from_database(raw_old_value))
super(raw_old_value, new_value)
end
end
end
end
end
end
Expand Up @@ -64,6 +64,10 @@ def json(name, options = {})
column(name, :json, options)
end

def jsonb(name, options = {})
column(name, :jsonb, options)
end

def citext(name, options = {})
column(name, :citext, options)
end
Expand Down
Expand Up @@ -451,6 +451,7 @@ def initialize_type_map(m) # :nodoc:
m.register_type 'point', OID::Point.new
m.register_type 'hstore', OID::Hstore.new
m.register_type 'json', OID::Json.new
m.register_type 'jsonb', OID::Jsonb.new
m.register_type 'cidr', OID::Cidr.new
m.register_type 'inet', OID::Inet.new
m.register_type 'uuid', OID::Uuid.new
Expand Down
34 changes: 25 additions & 9 deletions activerecord/test/cases/adapters/postgresql/json_test.rb
Expand Up @@ -4,7 +4,7 @@
require 'active_record/base'
require 'active_record/connection_adapters/postgresql_adapter'

class PostgresqlJSONTest < ActiveRecord::TestCase
module PostgresqlJSONSharedTestCases
class JsonDataType < ActiveRecord::Base
self.table_name = 'json_data_type'

Expand All @@ -16,8 +16,8 @@ def setup
begin
@connection.transaction do
@connection.create_table('json_data_type') do |t|
t.json 'payload', :default => {}
t.json 'settings'
t.public_send column_type, 'payload', default: {} # t.json 'payload', default: {}
t.public_send column_type, 'settings' # t.json 'settings'
end
end
rescue ActiveRecord::StatementInvalid
Expand All @@ -26,21 +26,21 @@ def setup
@column = JsonDataType.columns_hash['payload']
end

teardown do
def teardown
@connection.execute 'drop table if exists json_data_type'
end

def test_column
column = JsonDataType.columns_hash["payload"]
assert_equal :json, column.type
assert_equal "json", column.sql_type
assert_equal column_type, column.type
assert_equal column_type.to_s, column.sql_type
assert_not column.number?
assert_not column.binary?
assert_not column.array
end

def test_default
@connection.add_column 'json_data_type', 'permissions', :json, default: '{"users": "read", "posts": ["read", "write"]}'
@connection.add_column 'json_data_type', 'permissions', column_type, default: '{"users": "read", "posts": ["read", "write"]}'
JsonDataType.reset_column_information

assert_equal({"users"=>"read", "posts"=>["read", "write"]}, JsonDataType.column_defaults['permissions'])
Expand All @@ -52,11 +52,11 @@ def test_default
def test_change_table_supports_json
@connection.transaction do
@connection.change_table('json_data_type') do |t|
t.json 'users', default: '{}'
t.public_send column_type, 'users', default: '{}' # t.json 'users', default: '{}'
end
JsonDataType.reset_column_information
column = JsonDataType.columns_hash['users']
assert_equal :json, column.type
assert_equal column_type, column.type

raise ActiveRecord::Rollback # reset the schema change
end
Expand Down Expand Up @@ -175,3 +175,19 @@ def test_changes_in_place
assert_not json.changed?
end
end

class PostgresqlJSONTest < ActiveRecord::TestCase
include PostgresqlJSONSharedTestCases

def column_type
:json
end
end

class PostgresqlJSONBTest < ActiveRecord::TestCase
include PostgresqlJSONSharedTestCases

def column_type
:jsonb
end
end

0 comments on commit 1ec601b

Please sign in to comment.