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.
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
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
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
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
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.