Skip to content

Commit 09ac177

Browse files
committed
Merge pull request rails#10404 from chadmoone/fix-pg-uuid-default
Allow override of PostgreSQL UUID primary key default
2 parents d1f857e + 55c40c0 commit 09ac177

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,38 @@ def json(name, options = {})
330330
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
331331
include ColumnMethods
332332

333+
# Defines the primary key field.
334+
# Use of the native PostgreSQL UUID type is supported, and can be used
335+
# by defining your tables as such:
336+
#
337+
# create_table :stuffs, id: :uuid do |t|
338+
# t.string :content
339+
# t.timestamps
340+
# end
341+
#
342+
# By default, this will use the +uuid_generate_v4()+ function from the
343+
# +uuid-ossp+ extension, which MUST be enabled on your databse. To enable
344+
# the +uuid-ossp+ extension, you can use the +enable_extension+ method in your
345+
# migrations To use a UUID primary key without +uuid-ossp+ enabled, you can
346+
# set the +:default+ option to nil:
347+
#
348+
# create_table :stuffs, id: false do |t|
349+
# t.primary_key :id, :uuid, default: nil
350+
# t.uuid :foo_id
351+
# t.timestamps
352+
# end
353+
#
354+
# You may also pass a different UUID generation function from +uuid-ossp+
355+
# or another library.
356+
#
357+
# Note that setting the UUID primary key default value to +nil+
358+
# will require you to assure that you always provide a UUID value
359+
# before saving a record (as primary keys cannot be nil). This might be
360+
# done via the SecureRandom.uuid method and a +before_save+ callback,
361+
# for instance.
333362
def primary_key(name, type = :primary_key, options = {})
334363
return super unless type == :uuid
335-
options[:default] ||= 'uuid_generate_v4()'
364+
options[:default] = options.fetch(:default, 'uuid_generate_v4()')
336365
options[:primary_key] = true
337366
column name, type, options
338367
end

activerecord/test/cases/adapters/postgresql/uuid_test.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,34 @@ def test_auto_create_uuid
5151
assert_not_nil u.other_uuid
5252
end
5353
end
54+
55+
class PostgresqlUUIDTestNilDefault < ActiveRecord::TestCase
56+
class UUID < ActiveRecord::Base
57+
self.table_name = 'pg_uuids'
58+
end
59+
60+
def setup
61+
@connection = ActiveRecord::Base.connection
62+
63+
@connection.reconnect!
64+
65+
@connection.transaction do
66+
@connection.create_table('pg_uuids', id: false) do |t|
67+
t.primary_key :id, :uuid, default: nil
68+
t.string 'name'
69+
end
70+
end
71+
end
72+
73+
def teardown
74+
@connection.execute 'drop table if exists pg_uuids'
75+
end
76+
77+
def test_id_allows_default_override_via_nil
78+
col_desc = @connection.execute("SELECT pg_get_expr(d.adbin, d.adrelid) as default
79+
FROM pg_attribute a
80+
LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
81+
WHERE a.attname='id' AND a.attrelid = 'pg_uuids'::regclass").first
82+
assert_nil col_desc["default"]
83+
end
84+
end

0 commit comments

Comments
 (0)