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::Type
s.