alassek / activerecord-pg_enum Goto Github PK
View Code? Open in Web Editor NEWIntegrate PostgreSQL's enumerated types with the Rails enum feature
License: MIT License
Integrate PostgreSQL's enumerated types with the Rails enum feature
License: MIT License
Thanks for this gem! It would be nice if this gem had support for renaming and removing enum values as well. It's rare for me to get things right the first time, so being able to easily change them later is pretty valuable.
It looks like on Postgres 10 and up renaming a value is relatively painless. Removing a value isn't directly supported, but it looks like there is a workaround that isn't too horrendous.
Hi, seems like I found segfault for Ruby 3.0
When trying to load rails 6.1.1 environment:
/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/activerecord-pg_enum-1.2.2/lib/active_record/pg_enum/postgresql_adapter.rb:5: [BUG] Segmentation fault at 0x0000000300000004
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]
-- Crash Report log information --------------------------------------------
See Crash Report log file under the one of following:
* ~/Library/Logs/DiagnosticReports
* /Library/Logs/DiagnosticReports
for more details.
Don't forget to include the above Crash Report log file in bug reports.
There are currently some test failures on 6.1.0.rc1 related to the change to configuration objects.
Hi, thanks for your work!
I try to add a new enum value on an existing enum like the documentation
class AddNewValue < ActiveRecord::Migration[5.1]
def change
add_enum_value :my_test_enum, 'FOO', before: 'BAR'
end
end
But when i run migrations, i got this error
Caused by:
ActiveRecord::StatementInvalid: PG::ActiveSqlTransaction: ERROR: ALTER TYPE ... ADD cannot run inside a transaction block
: ALTER TYPE my_test_enum ADD VALUE 'FOO' BEFORE 'BAR'
I use this gem on a rails 5.1 application
Hi, is there any plan to add support for Rails 7?
I tried using the gem within a Rails 7 app, but it seems they are not compatible.
Hi ๐ !
I tried using activerecord-pg_enum
on a project which already uses active_record_extended
. Since active_record_extended
has been in use without issues I am reporting the issue here.
Traceback (most recent call last):
7: from pg_enum.rb:6:in `<main>'
6: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/inline.rb:70:in `gemfile'
5: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/runtime.rb:65:in `require'
4: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/runtime.rb:65:in `each'
3: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/runtime.rb:76:in `block in require'
2: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/runtime.rb:76:in `each'
1: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/runtime.rb:81:in `block (2 levels) in require'
/Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/runtime.rb:81:in `require': cannot load such file -- activerecord-pg_enum (LoadError)
16: from pg_enum.rb:6:in `<main>'
15: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/inline.rb:70:in `gemfile'
14: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/runtime.rb:65:in `require'
13: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/runtime.rb:65:in `each'
12: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/runtime.rb:72:in `block in require'
11: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/runtime.rb:95:in `rescue in block in require'
10: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/2.6.0/bundler/runtime.rb:95:in `require'
9: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/gems/2.6.0/gems/activerecord-pg_enum-1.0.1/lib/activerecord/pg_enum.rb:1:in `<top (required)>'
8: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/gems/2.6.0/gems/activerecord-pg_enum-1.0.1/lib/active_record/pg_enum.rb:4:in `<top (required)>'
7: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/gems/2.6.0/gems/activesupport-5.2.3/lib/active_support/lazy_load_hooks.rb:42:in `on_load'
6: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/gems/2.6.0/gems/activesupport-5.2.3/lib/active_support/lazy_load_hooks.rb:42:in `each'
5: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/gems/2.6.0/gems/activesupport-5.2.3/lib/active_support/lazy_load_hooks.rb:43:in `block in on_load'
4: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/gems/2.6.0/gems/activesupport-5.2.3/lib/active_support/lazy_load_hooks.rb:67:in `execute_hook'
3: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/gems/2.6.0/gems/activesupport-5.2.3/lib/active_support/lazy_load_hooks.rb:62:in `with_execution_control'
2: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/gems/2.6.0/gems/activesupport-5.2.3/lib/active_support/lazy_load_hooks.rb:71:in `block in execute_hook'
1: from /Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/gems/2.6.0/gems/activesupport-5.2.3/lib/active_support/lazy_load_hooks.rb:71:in `instance_eval'
/Users/dominik/.asdf/installs/ruby/2.6.1/lib/ruby/gems/2.6.0/gems/activerecord-pg_enum-1.0.1/lib/active_record/pg_enum.rb:5:in `block in <top (required)>': uninitialized constant ActiveRecord::PGEnum (NameError)
Reproduction script:
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "rails", "~> 5.2"
gem 'active_record_extended'
gem 'activerecord-pg_enum'
gem "pg"
end
require "active_record"
require "minitest/autorun"
require "logger"
Since Postgres defines types in the postgres
tables, running db:reset
can get you into a situation where you cannot re-run your migrations that define your Postgres enums. As a simple reproduction:
create_enum
db:migrate
db:reset
The migration will fail because the type already exists.
This all makes sense, but I wonder if there's a way we could make it so db:drop
also drops any enums defined by this gem?
Thanks for an awesome project! Couple notes on the readme:
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" }
You can actually continue to use integers in the db and do this:
enum status: { new: 0, active: 1, archived: 2 }`
Which solves the storage size and accidental reordering problems, but does not solve the ugly query problem.
An enum value only takes up four bytes.
You can actually back a rails enum with a 2-byte integer, with limit: 2
in the migration when creating the column.
I dream of a time when we can get the best of all worlds, where 1. postgres supports 1 or 2-byte columns, including for enums 2. rails supports postgres enums natively
๐ I ran into another use case which activerecord-pg_enum
doesn't seem to support yet, and wanted to start a discussion about whether we would want to support it, and if so how it would be implemented.
As with #3, I'm happy to attempt implementing this change, if it's decided that we want to support it.
When using activerecord-pg_enum
, we can't specify any of the options supported by the ActiveRecord::Enum
class, e.g. prefix
and suffix
.
This means that two enums with the same keys will collide when it comes to the autogenerated methods provided by this class, for example:
class Conversation < ActiveRecord::Base
enum status: [:active, :archived], _suffix: true
enum comments_status: [:active, :inactive], _prefix: :comments
end
conversation.active_status!
conversation.archived_status? # => false
conversation.comments_inactive!
conversation.comments_active? # => false
One option to implement this behaviour could be to accept any options to the include
and pass them through to the ActiveRecord::Enum
in the module definition
class Conversation < ActiveRecord::Base
include PGEnum(status: [:active, :archived], _suffix: true)
include PGEnum(status: [:active, :archived], _prefix: :comments)
end
conversation.active_status!
conversation.archived_status? # => false
conversation.comments_inactive!
conversation.comments_active? # => false
Hi ๐
I've been using activerecord-pg_enum
for a few weeks now, it's a fantastic gem, thanks for writing it.
Today I was adding a migration to create an enum which has values containing spaces, but the dumper doesn't appear to handle this correctly.
I've been taking a look at the codebase and would be happy to try and make this change, assuming it's deemed valid.
Rails version: 5.2.2.1
Ruby version: 2.6.3
activerecord-pg_enum version: 1.0.2
# frozen_string_literal: true
โ
class AddStatusEnum < ActiveRecord::Migration[5.2]
def up
create_enum 'status', ['sick', 'on vacation', 'working from home']
end
โ
def down
drop_enum 'status'
end
end
ActiveRecord::Schema.define(version: 2019_09_27_145140) do
# ...
# These are custom enum types that must be created before they can be used in the schema definition
create_enum "status", ['sick', 'on vacation', 'working from home']
end
ActiveRecord::Schema.define(version: 2019_09_27_145140) do
# ...
# These are custom enum types that must be created before they can be used in the schema definition
create_enum "status", %w[sick on vacation working from home]
end
This โ๏ธwill lead to the enum being created with values ["sick", "on", "vacation", "working", "from", "home"]
When I run rails db:setup
in my development environment and most the of the tables already exist, active record's create_table
will drop the table for me by default because of the force: :cascade
option in schema.rb. But when my schema.rb has instances of create_enum
, they fail with the following error:
-- create_enum("boolean_operator_enum_type", ["any", "all"])
rails aborted!
ActiveRecord::StatementInvalid: PG::DuplicateObject: ERROR: type "boolean_operator_enum_type" already exists
: CREATE TYPE boolean_operator_enum_type AS ENUM ('any', 'all')
What are your thoughts on adding a force: :cascade
option to create_enum
, so that the enum
can be dropped and db:setup
can be run easier? I'd be more than happy to create the PR, but wanted to check your thoughts on it first: good idea? bad idea?
Note: As a current solution, I temporarily change my schema.rb
to this:
module ActiveRecord
module PGEnum
module SchemaStatements
def drop_enum_if_exists_cascade(name, values_for_revert = nil)
execute("DROP TYPE IF EXISTS #{name} CASCADE").tap {
reload_type_map
}
end
end
end
end
ActiveRecord::Schema.define(version: 2020_12_22_214218) do
drop_enum_if_exists_cascade "boolean_operator_enum_type"
create_enum "boolean_operator_enum_type", ["any", "all"]
# ... rails schema here
end
https://github.com/alassek/activerecord-pg_enum implies that running a migration containing
class TestEnum < ActiveRecord::Migration[5.2]
def change
create_enum "status_type", %w[new pending active archived]
end
end
will add this line to your schema.rb
:
create_enum "status_type", %w[new pending active archived]
but it didn't add that line to my schema.rb
๐
(It only added the t.enum ...
line that depends on that type.)
Running bin/rails db:structure:dump
confirms that it did get added to my database:
CREATE TYPE app_name_development.status_type AS ENUM (
'new',
'pending',
'active',
'archived'
);
... just not to my schema.rb
, which was the main point of using this gem ๐
Using Rails 5.2
[PGEnum] Current ActiveRecord version unsupported! Falling back to: 6.1
I assumed that create_table
and change_table
use the same class but it appears not.
NoMethodError: undefined method `enum' for #<ActiveRecord::ConnectionAdapters::PostgreSQL::Table:0x00007fe990c40bb8>
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.