Michael Anhari

Adding custom data types to your Postgres database in Rails

Hands molding a clay pot

This week I learned from a colleague that PostgreSQL allows you to create custom domains, which it describes as the following:

a data type with optional constraints (restrictions on the allowed set of values)

Creating the custom domain in Rails

For our current client, a 15-digit numeric string is the protocol for identifying resources in their industry. In our Rails migration for creating this domain, we used something like this:

def change
  execute <<~SQL
    CREATE DOMAIN pid_type AS VARCHAR(15) CHECK(VALUE ~ '^\\d{15}$');
  SQL
end

Here we're defining a custom domain pid_type that can be used to store 15-digit numeric strings in our database that will we reject any nonconforming values.

Adding columns that use our custom domain

After running this, we can now add columns with a type of "pid_type". For example, let's say we needed to add this column to our notes table.

def change
  add_column :notes, :pid, "pid_type"
end

Why not just use an ActiveRecord validation?

Before we added this custom domain, we used a concern to share an ActiveRecord validation that was similiar to our database check constraint (checking that the value was a 15-digit numeric string).

module Pidable
   extend ActiveSupport::Concern

   included do
     validates :pid, length: {is: 15}
     validates :pid, numericality: {only_integer: true}
   end
 end

However, since these records are stricly created via ETL processes (data is being imported from other systems), we realized we did not need to present error information to a user at any point. Also, the database constraint gives us safety at the database layer in case we ever need to bypass ActiveRecord when inserting records.

Conclusion

That just about wraps it up. I don't think this is a feature I will reach for often, but Postgres continues to astound me. What a wonderful foundation on which to build your application. 🐘 == 💯

Newsletter

I'm working on sending out a weekly newsletter. I'll make it as easy as possible to unsubscribe at any time.