activerecord-pg_enum 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 67d75573d2938384fe7b152068e7ea8574c06edd54a568288d32fc02e97ba91d
4
- data.tar.gz: 8eb7a669608474a001058437252519035b6a59d4663ab83aab470b92603f3869
3
+ metadata.gz: 33a876e540cf1813b1d54ed406ce47ef39c49168e45967452e587f3e34617348
4
+ data.tar.gz: acd215db0882fac1c90303721b1118b06a036f006e7b4eb66a1efbb6df5d781c
5
5
  SHA512:
6
- metadata.gz: da008c7e1bbc9304dd4ce5570b4800abefc6e1caca83d20c11fa1bdf3e29e8665ff6184f569edde7a1b106b5b4976ad23eb3dc4dc62b7c2d8854b66935f5483a
7
- data.tar.gz: dd7f6e35923433c9cc97cc44560904407a04c1f50036fcb3e5ec13b8a9be41e65de3b1b67632dbc0d0f98130e36fedeeee4407070e15e36a111bde4e19ec9984
6
+ metadata.gz: 4d897a53720eebf23d808eb4a5c927db868a69055d6f77919a0f3f20d6a8ece2a27be4d53edc0e94d767e17711b8e50d24e30055f37da8985e2e3ecefe26bab9
7
+ data.tar.gz: 5c733a6b3c41a56325c290ee6f46756f18217f3d64b0a8e9b70d9bccbe4a6b01be893f788ddf3fc4ccb92c1de64573b590b11a95eb226e4252077b41b65a98e3
data/.travis.yml CHANGED
@@ -1,6 +1,7 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
+ - 2.1
4
5
  - 2.5
5
6
  services:
6
7
  - postgresql
data/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.0] - 2018-08-12
10
+ ### Added
11
+ - `add_to_enum` for modifying existing types
12
+ - `ActiveRecord::Migration::CommandRecorder` is patched to make `create_enum`, and `drop_enum` reversible.
13
+
14
+ ### Changed
15
+ - Ruby 2.1 is defined as the earliest supported version (for kwargs)
16
+ - `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#enum_types` returns a Hash instead of a nested Array
@@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
18
18
  f.match(%r{^(test|spec|features)/})
19
19
  end
20
20
 
21
+ spec.required_ruby_version = ">= 2.1"
22
+
21
23
  spec.bindir = "exe"
22
24
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
25
  spec.require_paths = ["lib"]
@@ -5,6 +5,7 @@ require "active_record/connection_adapters/postgresql_adapter"
5
5
  require "active_support/lazy_load_hooks"
6
6
 
7
7
  ActiveSupport.on_load(:active_record) do
8
+ require "active_record/pg_enum/command_recorder"
8
9
  require "active_record/pg_enum/postgresql_adapter"
9
10
  require "active_record/pg_enum/schema_dumper"
10
11
  require "active_record/pg_enum/schema_statements"
@@ -16,4 +17,5 @@ ActiveSupport.on_load(:active_record) do
16
17
 
17
18
  ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.include ActiveRecord::PGEnum::PostgreSQLAdapter
18
19
  ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.include ActiveRecord::PGEnum::SchemaStatements
20
+ ActiveRecord::Migration::CommandRecorder.include ActiveRecord::PGEnum::CommandRecorder
19
21
  end
@@ -0,0 +1,48 @@
1
+ module ActiveRecord
2
+ module PGEnum
3
+ # ActiveRecord::Migration::CommandRecorder is a class used by reversible migrations.
4
+ # It captures the forward migration commands and translates them into their inverse
5
+ # by way of some simple metaprogramming.
6
+ #
7
+ # The Migrator class uses CommandRecorder during the reverse migration instead of
8
+ # the connection object. Forward migration calls are translated to their inverse
9
+ # where possible, and then forwarded to the connetion. Irreversible migrations
10
+ # raise an exception.
11
+ #
12
+ # Known schema statement methods are metaprogrammed into an inverse method like so:
13
+ #
14
+ # create_table => invert_create_table
15
+ #
16
+ # which returns:
17
+ #
18
+ # [:drop_table, args.first]
19
+ module CommandRecorder
20
+ def create_enum(*args, &block)
21
+ record(:create_enum, args, &block)
22
+ end
23
+
24
+ def drop_enum(*args, &block)
25
+ record(:drop_enum, args, &block)
26
+ end
27
+
28
+ def add_enum_value(*args, &block)
29
+ record(:add_enum_value, args, &block)
30
+ end
31
+
32
+ private
33
+
34
+ def invert_create_enum(args)
35
+ [:drop_enum, args]
36
+ end
37
+
38
+ def invert_drop_enum(args)
39
+ raise ActiveRecord::IrreversibleMigration, "drop_enum is only reversible if given a list of values" unless args.length > 1
40
+ [:create_enum, args]
41
+ end
42
+
43
+ def invert_add_enum_value(args)
44
+ raise ActiveRecord::IrreversibleMigration, "ENUM values cannot be removed once added. Drop and Replace it instead at your own risk."
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,6 +1,11 @@
1
1
  module ActiveRecord
2
2
  module PGEnum
3
3
  module PostgreSQLAdapter
4
+ # Helper method used by the monkeypatch internals. Provides a hash of ENUM types as they exist currently.
5
+ #
6
+ # Example:
7
+ #
8
+ # { "foo_type" => ["foo", "bar", "baz"] }
4
9
  def enum_types
5
10
  res = exec_query(<<-SQL.strip_heredoc, "SCHEMA").cast_values
6
11
  SELECT t.typname AS enum_name, string_agg(e.enumlabel, ' ' ORDER BY e.enumsortorder) AS enum_value
@@ -11,8 +16,9 @@ module ActiveRecord
11
16
  GROUP BY enum_name
12
17
  SQL
13
18
 
14
- res.map do |(name, values)|
15
- [name, values.split(" ")]
19
+ res.inject({}) do |memo, (name, values)|
20
+ memo[name] = values.split(" ")
21
+ memo
16
22
  end
17
23
  end
18
24
  end
@@ -13,13 +13,14 @@ module ActiveRecord
13
13
 
14
14
  stream.puts " # These are custom enum types that must be created before they can be used in the schema definition"
15
15
 
16
- enum_types.each do |enum_type|
17
- stream.puts %Q{ create_enum "#{enum_type.first}", "#{enum_type.second.join("\", \"")}"}
16
+ enum_types.each do |name, definition|
17
+ stream.puts %Q{ create_enum "#{name}", "#{definition.join("\", \"")}"}
18
18
  end
19
19
 
20
20
  stream.puts
21
21
  end
22
22
 
23
+ # Gathers the arguments needed for the column line inside the create_table block.
23
24
  def column_spec(column)
24
25
  if column.type == :enum
25
26
  ["column", [column.sql_type.inspect, prepare_column_options(column)]]
@@ -28,6 +29,7 @@ module ActiveRecord
28
29
  end
29
30
  end
30
31
 
32
+ # Takes a column specification in Object form and serializes it into a String.
31
33
  def format_colspec(colspec)
32
34
  case colspec
33
35
  when String
@@ -1,13 +1,43 @@
1
1
  module ActiveRecord
2
2
  module PGEnum
3
3
  module SchemaStatements
4
+ # Create a new ENUM type, with an arbitrary number of values.
5
+ #
6
+ # Example:
7
+ #
8
+ # create_enum("foo_type", "foo", "bar", "baz")
4
9
  def create_enum(name, *values)
5
10
  execute "CREATE TYPE #{name} AS ENUM (#{values.map { |v| "'#{v}'" }.join(", ")})"
6
11
  end
7
12
 
8
- def drop_enum(name)
13
+ # Drop an ENUM type from the database.
14
+ def drop_enum(name, *values_for_revert)
9
15
  execute "DROP TYPE #{name}"
10
16
  end
17
+
18
+ # Add a new value to an existing ENUM type.
19
+ # Only one value at a time is supported by PostgreSQL.
20
+ #
21
+ # Options:
22
+ # before: add value BEFORE the given value
23
+ # after: add value AFTER the given value
24
+ #
25
+ # Example:
26
+ #
27
+ # add_enum_value("foo_type", "quux", before: "bar")
28
+ def add_enum_value(type, value, before: nil, after: nil)
29
+ cmd = "ALTER TYPE #{type} ADD VALUE '#{value}'"
30
+
31
+ if before && after
32
+ raise ArgumentError, "Cannot have both :before and :after at the same time"
33
+ elsif before
34
+ cmd << " BEFORE '#{before}'"
35
+ elsif after
36
+ cmd << " AFTER '#{after}'"
37
+ end
38
+
39
+ execute cmd
40
+ end
11
41
  end
12
42
  end
13
43
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module PGEnum
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-pg_enum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Lassek
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-06 00:00:00.000000000 Z
11
+ date: 2018-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -119,6 +119,7 @@ files:
119
119
  - ".rspec"
120
120
  - ".rubocop.yml"
121
121
  - ".travis.yml"
122
+ - CHANGELOG.md
122
123
  - Gemfile
123
124
  - LICENSE
124
125
  - README.md
@@ -127,6 +128,7 @@ files:
127
128
  - bin/console
128
129
  - bin/setup
129
130
  - lib/active_record/pg_enum.rb
131
+ - lib/active_record/pg_enum/command_recorder.rb
130
132
  - lib/active_record/pg_enum/helper.rb
131
133
  - lib/active_record/pg_enum/postgresql_adapter.rb
132
134
  - lib/active_record/pg_enum/schema_dumper.rb
@@ -145,7 +147,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
145
147
  requirements:
146
148
  - - ">="
147
149
  - !ruby/object:Gem::Version
148
- version: '0'
150
+ version: '2.1'
149
151
  required_rubygems_version: !ruby/object:Gem::Requirement
150
152
  requirements:
151
153
  - - ">="
@@ -153,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
155
  version: '0'
154
156
  requirements: []
155
157
  rubyforge_project:
156
- rubygems_version: 2.7.6
158
+ rubygems_version: 2.7.7
157
159
  signing_key:
158
160
  specification_version: 4
159
161
  summary: Integrate PostgreSQL's enumerated types with the Rails enum feature