All Projects → alassek → Activerecord Pg_enum

alassek / Activerecord Pg_enum

Licence: mit
Integrate PostgreSQL's enumerated types with the Rails enum feature

Programming Languages

ruby
36898 projects - #4 most used programming language
enum
40 projects

Projects that are alternatives of or similar to Activerecord Pg enum

Postgres Migrations
🐦 A Stack Overflow-inspired PostgreSQL migration library with strict ordering and immutable migrations
Stars: ✭ 161 (+28.8%)
Mutual labels:  migrations, postgresql
Migrator
Opinionated database migration library for Go applications.
Stars: ✭ 7 (-94.4%)
Mutual labels:  migrations, postgresql
Dbmate
🚀 A lightweight, framework-agnostic database migration tool.
Stars: ✭ 2,228 (+1682.4%)
Mutual labels:  migrations, postgresql
Websiteone
A website for Agile Ventures
Stars: ✭ 132 (+5.6%)
Mutual labels:  postgresql, ruby-on-rails
Rpg Boilerplate
Relay (React), Postgres, and Graphile (GraphQL): A Modern Frontend and API Boilerplate
Stars: ✭ 62 (-50.4%)
Mutual labels:  migrations, postgresql
Node Pg Migrate
Node.js database migration management for Postgresql
Stars: ✭ 838 (+570.4%)
Mutual labels:  migrations, postgresql
Django Migration Linter
🚀 Detect backward incompatible migrations for your django project
Stars: ✭ 231 (+84.8%)
Mutual labels:  migrations, postgresql
Graphjin
GraphJin - Build APIs in 5 minutes with GraphQL. An instant GraphQL to SQL compiler.
Stars: ✭ 1,264 (+911.2%)
Mutual labels:  postgresql, ruby-on-rails
Pop
A Tasty Treat For All Your Database Needs
Stars: ✭ 1,045 (+736%)
Mutual labels:  migrations, postgresql
Niklick
Rails Versioned API solution template for hipsters! (Ruby, Ruby on Rails, REST API, GraphQL, Docker, RSpec, Devise, Postgress DB)
Stars: ✭ 39 (-68.8%)
Mutual labels:  postgresql, ruby-on-rails
Go Pg Migrations
A Go package to help write migrations with go-pg/pg.
Stars: ✭ 74 (-40.8%)
Mutual labels:  migrations, postgresql
Lol dba
lol_dba is a small package of rake tasks that scan your application models and displays a list of columns that probably should be indexed. Also, it can generate .sql migration scripts.
Stars: ✭ 1,363 (+990.4%)
Mutual labels:  migrations, ruby-on-rails
Mailjet Gem
[API v3] Mailjet official Ruby GEM
Stars: ✭ 119 (-4.8%)
Mutual labels:  ruby-on-rails
Deploy Strapi On Aws
Deploying a Strapi API on AWS (EC2 & RDS & S3)
Stars: ✭ 121 (-3.2%)
Mutual labels:  postgresql
Csharp Datatables Parser
C# Serverside parser for the popuplar jQuery datatables plugin.
Stars: ✭ 119 (-4.8%)
Mutual labels:  postgresql
Dockerized Flask
Dockerized web app using NGINX, Flask and PostgreSQL
Stars: ✭ 119 (-4.8%)
Mutual labels:  postgresql
Postgres Showcase
Postgres features showcase (commented SQL samples) for beginners
Stars: ✭ 121 (-3.2%)
Mutual labels:  postgresql
Docker Rails Base
Optimized Docker base images for Rails applications
Stars: ✭ 120 (-4%)
Mutual labels:  ruby-on-rails
Symfony 4 Docker Env
Docker Environment for Symfony. PHP-FPM, NGINX SSL Proxy, MySQL, LEMP
Stars: ✭ 119 (-4.8%)
Mutual labels:  postgresql
Pg query state
Tool for query progress monitoring in PostgreSQL
Stars: ✭ 118 (-5.6%)
Mutual labels:  postgresql

ActiveRecord::PGEnum Build Status

The enum feature in Rails has bad developer ergonomics. It uses integer types at the DB layer, which means trying to understand SQL output is a pain.

Using the easy form of the helper syntax is a minor footgun:

enum status: %w[new active archived]

It's not obvious that the above code is order-dependent, but if you decide to add a new enum anywhere but the end, you're in trouble.

If you choose the use varchar fields instead, now you have to write annoying check constraints and lose the efficient storage.

enum status: { new: "new", active: "active", archived: "archived" }

Nobody has time to write that nonsense.

Enumerated Types: The Best of Both Worlds

Did you know you can define your own types in PostgreSQL? You can, and this type system also supports enumeration.

CREATE TYPE status_type AS ENUM ('new', 'active', 'archived');

Not only does this give you full type safety at the DB layer, the implementation is highly efficient. An enum value only takes up four bytes.

The best part is that PostgreSQL supports inserting new values at any point of the list without having to migrate your data.

ALTER TYPE status_type ADD VALUE 'pending' BEFORE 'active';

schema.rb Support

The principle motivation of this gem is to seamlessly integrate PG enums into your schema.rb file. This means you can use them in your database columns without switching to structure.sql.

ActiveRecord::Schema.define(version: 2019_06_19_214914) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_enum "status_type", %w[new pending active archived]
  
  create_table "orders", id: :serial, force: :cascade do |t|
    t.enum "status", as: "status_type", default: "new"
  end

end

Version support

Every version of Rails with an enum macro is supported. This means 4.1 through master. Yes, this was annoying and difficult.

The monkeypatches in this library are extremely narrow and contained; the dirty hacks I had to do to make 4.1 work, for instance, have no impact on 6.0.

Monkeypatching Rails internals is scary. So this library has a comprehensive test suite that runs against every known minor version.

Installation

Add this line to your application's Gemfile:

gem 'activerecord-pg_enum'

And then execute:

$ bundle

Usage

Migrations

Defining a new ENUM

class AddContactMethodType < ActiveRecord::Migration[5.2]
  def up
    create_enum "contact_method_type", %w[Email Phone]
  end

  def down
    drop_enum "contact_method_type"
  end
end

Adding a value to an existing ENUM

class AddSMSToContactMethodType < ActiveRecord::Migration[5.2]
  def up
    add_enum_value "contact_method_type", "SMS", before: "Phone"
  end

  def down
    raise ActiveRecord::IrreversibleMigration
  end
end

Adding an enum column to a table

class AddStatusToOrder < ActiveRecord::Migration[5.2]
  def change
    change_table :orders do |t|
      t.enum :status, as: "status_type", default: "new"
    end
  end
end

Renaming an enum type

class RenameStatusType < ActiveRecord::Migration[6.0]
  def change
    rename_enum "status_type", to: "order_status_type"
  end
end
ALTER TYPE status_type RENAME TO order_status_type;

PostgreSQL 10+ required:

Changing an enum label

class ChangeStatusHoldLabel < ActiveRecord::Migration[6.0]
  def change
    rename_enum_value "status_type", from: "on hold", to: "OnHold"
  end
end
ALTER TYPE status_type RENAME VALUE 'on hold' TO 'OnHold';

Module Builder

class ContactInfo < ActiveRecord::Base
  include PGEnum(contact_method: %w[Email SMS Phone])
end

The generated module calls the official enum method converting array syntax into strings. The above example is equivalent to:

class ContactInfo < ActiveRecord::Base
  enum contact_method: { Email: "Email", SMS: "SMS", Phone: "Phone" }
end

Additionally, enum options are fully supported, for example

class User < ActiveRecord::Base
  include PGEnum(status: %w[active inactive deleted], _prefix: 'user', _suffix: true)
end

is equivalent to

class User < ActiveRecord::Base
  enum status: { active: 'active', inactive: 'inactive', deleted: 'deleted' }, _prefix: 'user', _suffix: true
end

There's no technical reason why you couldn't detect enum columns at startup time and automatically do this wireup, but I feel that the benefit of self-documenting outweighs the convenience.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run appraisal rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

Test a specific version with appraisal 6.0 rake spec. This is usually necessary because different versions have different Ruby version support.

To install this gem onto your local machine, run bundle exec rake install.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/alassek/activerecord-pg_enum.

License

The gem is available as open source under the terms of the MIT License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].