Override database attribute types

Sometimes you don't have control over how your database handles information, so you need Rails to set it

In an ideal world, your database setup will reflect your business logic, as in if a field is required in your application, it is required in your database, if it is a number in your database, it is a number on your system. I’ve written about this in checking in with your database.

We don’t live in an ideal world, far from it. Sometimes your database will say one thing but your application needs it to act like something else. The “correct” fix would be to update the database to suit. That isn’t always possible or desirable. Luckily, Rails can help!

I was working on a codebase recently where the database used TEXT for a lot of fields. Ideally these would be VARCHAR(30) or similar. In this project, Rails didn’t control the database, so writing a quick migration was out of the question, but I wanted the convenience of Rails “magically” knowing what type of input field to use.

Lets say our attribute was called name, we can tell it to act like a string instead of some text by doing this following;

class User < ApplicationRecord
  attribute :name, :string
end

Now if we were to create an input field, input would be used instead of textarea.

We can even set a default here;

class User < ApplicationRecord
  attribute :name, :string
  attribute :favourite_colour, :string, default: 'Purple'
end

Combining these with some validates will help you make sure you aren’t putting something into the database you shouldn’t, regardless of if the database will allow it or not.

What I’ve shared above is a fairly straight forward example, but you can define an entire object as a type and override things like the cast method, so that you could e.g. uppercase everything before it is saved without needing to write a before_save callback. You can read more about ActiveRecord::Types.

Recent posts View all

JavaScript

Setting a more specific database type in Prisma

Prisma sets a default of TEXT for all String fields, here is how you can override that.

Ruby

Override database attribute types

Sometimes you don't have control over how your database handles information, so you need Rails to set it