<!-- canonical: https://majesticlabs.dev/blog/202008/publishable-enum-in-ruby-on-rails-with-postgresql -->
# Publishable Enum in Ruby on Rails with PostgreSQL

By David Paluy

Add publishable status to Rails models with PostgreSQL enums—migrations, scopes, and safe state transitions for reliable draft-to-published workflows.

## Why use a PostgreSQL enum for publishable status?

There are many options to add publishing ability to your Rails model. Let's assume we have an `Article` model, and we want to make it `publishable`.

## Add activerecord-postgres_enum to your Gemfile

```ruby
gem 'activerecord-postgres_enum'
```

You need this [solution](https://github.com/bibendi/activerecord-postgres_enum) if you want to use `schema.rb`.

## Let's create a Publishable module

`app/models/concerns/publishable.rb`

```ruby
module Publishable
  extend ActiveSupport::Concern
  STATUSES = %w[draft reviewing published unpublished].freeze
end
```

## Create PostgreSQL enum

`rails g migration add_content_status_type`

```ruby
class AddContentStatusType < ActiveRecord::Migration[6.0]
  def change
    create_enum :content_status, Publishable::STATUSES
  end
end
```

This will create the PostgreSQL ENUM type.

## Add status to Article model

`rails g migration add_status_to_articles status:content_status`

This will create a migration to add `status` to the `Article` model.

Define the default value:

```ruby
add_column :articles, :status, :content_status, default: 'draft'
```

For better query performance, add an index:

```ruby
add_index :articles, :status
```

Add the publishing ability to your article:

```ruby
class Article < ApplicationRecord
  include Publishable
end
```

## The updated version of Publishable concern

```ruby
module Publishable
  extend ActiveSupport::Concern
  STATUSES = %w[draft reviewing published unpublished].freeze

  included do
    enum status: STATUSES.zip(STATUSES).to_h
  end
end
```

This adds all Rails scopes and magic. For example:

- `Article.published`

- `article.published?`

- `article.published!`
