Nullalign – improve your columns presence validation

Ruby on Rails / Rubygems

Usually, when we want to ensure that value for a given column will be always present we would use presence validator. Here is a simple example of validation for the title column from the Post model:

class Post < ActiveRecord::Base
  validates :title, presence: true
end

Unfortunately, it’s not enough. There are some cases when a new post can be created with a blank title. How to avoid it? Ensure the database level that given column can’t have a null value. You can do it by passing null attribute in a migration file:

class CreatePosts < ActiveRecord::Migration
  def change
    create_table :posts do |t|
      t.string :title, null: false

      t.timestamps null: false
    end
  end
end

Existing applications

Things get more complicated when you are working on an existing app and you want to update all the places where there is presence validation set but the same rule is not set on a database level. If your codebase is large then it would be a time-consuming action - but it doesn’t have to be.

You can use the nullalign gem, a tool created by Tom Copeland. It’s easy to use and it does the dirty work for you. Let’s give it a try!

Add the gem to your Gemfile:

gem 'nullalign'

run bundle install and we are ready to use it. Rules are simple: there is only one task. You can execute it by running bundle exec nullalign and it will generate similar output:

There are presence validators that aren't backed by non-null constraints.
--------------------------------------------------------------------------------
Model              Table Columns
--------------------------------------------------------------------------------
Post               posts: title

Now you can go through the list and pick up the columns you want to update. The last step is to create a migration to update columns:

class UpdatePosts < ActiveRecord::Migration
  def change
    change_column :posts, :title, :string, null: false
  end
end

and that’s it! Check gem on github and Tom's twitter.