allow override of uuid_generate_v4() default by passing default: nil

without this, it's not possible to use UUID primary keys without uuid-ossp installed and activated
This commit is contained in:
Chad Moone 2013-04-25 00:46:40 -04:00
parent f7f8b7ccfc
commit 55c40c0ece
2 changed files with 61 additions and 1 deletions

@ -330,9 +330,38 @@ def json(name, options = {})
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
include ColumnMethods
# Defines the primary key field.
# Use of the native PostgreSQL UUID type is supported, and can be used
# by defining your tables as such:
#
# create_table :stuffs, id: :uuid do |t|
# t.string :content
# t.timestamps
# end
#
# By default, this will use the +uuid_generate_v4()+ function from the
# +uuid-ossp+ extension, which MUST be enabled on your databse. To enable
# the +uuid-ossp+ extension, you can use the +enable_extension+ method in your
# migrations To use a UUID primary key without +uuid-ossp+ enabled, you can
# set the +:default+ option to nil:
#
# create_table :stuffs, id: false do |t|
# t.primary_key :id, :uuid, default: nil
# t.uuid :foo_id
# t.timestamps
# end
#
# You may also pass a different UUID generation function from +uuid-ossp+
# or another library.
#
# Note that setting the UUID primary key default value to +nil+
# will require you to assure that you always provide a UUID value
# before saving a record (as primary keys cannot be nil). This might be
# done via the SecureRandom.uuid method and a +before_save+ callback,
# for instance.
def primary_key(name, type = :primary_key, options = {})
return super unless type == :uuid
options[:default] ||= 'uuid_generate_v4()'
options[:default] = options.fetch(:default, 'uuid_generate_v4()')
options[:primary_key] = true
column name, type, options
end

@ -51,3 +51,34 @@ def test_auto_create_uuid
assert_not_nil u.other_uuid
end
end
class PostgresqlUUIDTestNilDefault < ActiveRecord::TestCase
class UUID < ActiveRecord::Base
self.table_name = 'pg_uuids'
end
def setup
@connection = ActiveRecord::Base.connection
@connection.reconnect!
@connection.transaction do
@connection.create_table('pg_uuids', id: false) do |t|
t.primary_key :id, :uuid, default: nil
t.string 'name'
end
end
end
def teardown
@connection.execute 'drop table if exists pg_uuids'
end
def test_id_allows_default_override_via_nil
col_desc = @connection.execute("SELECT pg_get_expr(d.adbin, d.adrelid) as default
FROM pg_attribute a
LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
WHERE a.attname='id' AND a.attrelid = 'pg_uuids'::regclass").first
assert_nil col_desc["default"]
end
end