Part one of this blog post mini-series showed how to override default table names and primary key names in ActiveRecord model classes, and how to define alias attributes for legacy column names.
This part will discuss some options for primary key definitions in the schema file, which are relevant for legacy schemas, as well as primary key value generation on Oracle databases.
Primary key schema definition
The database schema definition of a Rails application is usually provided in a file called schema.rb
via a simple domain specific language.
The create_table
method implicitly adds a primary key column with name id
(of numeric type) by default.
create_table 'users' do |t| t.string 'name', limit: 20 # ... end
If the primary key has a different name you can easily specify it via the primary_key
option:
create_table 'users', primary_key: 'user_key' do |t| t.string 'name', limit: 20 # ... end
But what if a table has a primary key of non-numeric type? The Rails schema DSL does not directly support this. But there’s a workaround: you can set the id
option of create_table
to false, declare the primary key column like an ordinary non-nullable column, and add the primary key constraint afterwards via execute
.
create_table 'users', id: false do |t| t.string 'user_key', null: false t.string 'name', limit: 20 # ... end execute 'ALTER TABLE user ADD PRIMARY KEY (user_key)'
Primary key value generation
On Oracle databases new primary key values are usually created via sequences. The Oracle adapter for ActiveRecord assumes sequence names in the form of table name + “_seq”. You can override this default sequence name in a model class via the sequence_name
property:
class User < ActiveRecord::Base self.sequence_name = 'user_sequence' # ... end
Sometimes primary key values are auto-generated via triggers. In this case you need the Oracle Enhanced adapter, which is a superset of the original ActiveRecord Oracle adapter, but with additional support for working with legacy databases. Now you can set the sequence_name
property to the value :autogenerated
:
class User < ActiveRecord::Base self.sequence_name = :autogenerated # ... end
This circumvents the default convention and tells the adapter to not include primary key values in generated INSERT statements.