Skip to content

Instantly share code, notes, and snippets.

@theaxel
Last active February 4, 2019 20:08
Show Gist options
  • Select an option

  • Save theaxel/6735b1f83fc9ca78c4f06dd45dc65d92 to your computer and use it in GitHub Desktop.

Select an option

Save theaxel/6735b1f83fc9ca78c4f06dd45dc65d92 to your computer and use it in GitHub Desktop.

Revisions

  1. theaxel revised this gist Feb 4, 2019. 1 changed file with 6 additions and 8 deletions.
    14 changes: 6 additions & 8 deletions rails_postgres_enum.rb
    Original file line number Diff line number Diff line change
    @@ -16,19 +16,17 @@ def dump(stream)

    def enums(stream)
    enum_types = @connection.enum_types
    if enum_types.any?
    stream.puts " # These are custom enum types that must be created before they can be used in the schema definition"
    enum_types.each do |enum_type|
    stream.puts " create_enum \"#{enum_type.first}\", \"#{enum_type.second.join('", "')}\""
    end
    stream.puts
    return unless enum_types.any?
    stream.puts " # These are custom enum types that must be created before they can be used in the schema definition"
    enum_types.each do |enum_type|
    stream.puts " create_enum \"#{enum_type.first}\", \"#{enum_type.second.join('", "')}\""
    end
    stream.puts
    end

    def format_colspec(colspec)
    if colspec.is_a? Array
    specs = colspec.reject {|item| item.blank? }.map do |value|
    colspec.reject(&:blank?).map do |value|
    value.is_a?(Hash) ? format_colspec(value) : value
    end.flatten.join(", ")
    else
    @@ -91,7 +89,7 @@ def default_primary_key?(column)

    module PostgreSQL::SchemaStatements
    def create_enum(name, *values)
    execute "CREATE TYPE #{name} AS ENUM (#{values.map{|v| "'#{v}'"}.join(', ')})"
    execute "CREATE TYPE #{name} AS ENUM (#{ values.map {|v| "'#{v}'" }.join(', ')})"
    end

    def drop_enum(name)
  2. theaxel revised this gist Feb 1, 2019. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions rails_postgres_enum.rb
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    # frozen_string_literal: true

    # Support for PostgreSQL enum types in Rails 5.2 (including schema dump)
    module ActiveRecord
    class SchemaDumper
  3. theaxel revised this gist May 13, 2018. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion rails_postgres_enum.rb
    Original file line number Diff line number Diff line change
    @@ -62,7 +62,6 @@ def enum_types
    module PostgreSQL
    class SchemaDumper
    def column_spec(column)
    puts "CALLED column_spec"
    type = schema_type_with_virtual(column)
    spec = prepare_column_options(column)

  4. theaxel revised this gist May 13, 2018. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions rails_postgres_enum.rb
    Original file line number Diff line number Diff line change
    @@ -82,8 +82,6 @@ def prepare_column_options(column)
    spec
    end

    # Needs overwrite as some tables report different primary key type
    # Problem was introduced by switch to activerecord 5.*
    def default_primary_key?(column)
    schema_type(column) == :bigserial || schema_type(column) == :serial
    end
  5. theaxel created this gist May 13, 2018.
    103 changes: 103 additions & 0 deletions rails_postgres_enum.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,103 @@
    # Support for PostgreSQL enum types in Rails 5.2 (including schema dump)
    module ActiveRecord
    class SchemaDumper
    def dump(stream)
    header(stream)
    extensions(stream)
    enums(stream)
    tables(stream)
    trailer(stream)
    stream
    end

    private

    def enums(stream)
    enum_types = @connection.enum_types
    if enum_types.any?
    stream.puts " # These are custom enum types that must be created before they can be used in the schema definition"
    enum_types.each do |enum_type|
    stream.puts " create_enum \"#{enum_type.first}\", \"#{enum_type.second.join('", "')}\""
    end
    stream.puts
    end
    stream.puts
    end

    def format_colspec(colspec)
    if colspec.is_a? Array
    specs = colspec.reject {|item| item.blank? }.map do |value|
    value.is_a?(Hash) ? format_colspec(value) : value
    end.flatten.join(", ")
    else
    colspec.map { |key, value| "#{key}: #{value}" }.join(", ")
    end
    end
    end

    module ConnectionAdapters
    class PostgreSQLAdapter
    def native_database_types
    NATIVE_DATABASE_TYPES.merge(enum: { name: "enum" })
    end

    def enum_types
    query = <<-SQL
    SELECT t.typname AS enum_name,
    string_agg(e.enumlabel, ' ') AS enum_value
    FROM pg_type t
    JOIN pg_enum e ON t.oid = e.enumtypid
    JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
    WHERE n.nspname = 'public'
    GROUP BY enum_name
    SQL
    res = exec_query(query, 'SCHEMA').cast_values
    res.each do |line|
    line[1] = line[1].split(' ')
    end
    res
    end
    end

    module PostgreSQL
    class SchemaDumper
    def column_spec(column)
    puts "CALLED column_spec"
    type = schema_type_with_virtual(column)
    spec = prepare_column_options(column)

    if column.type == :enum
    type = 'column'
    enum_type = spec.delete(:enum_type)
    spec = [":#{enum_type}", spec]
    end

    [type, spec]
    end

    def prepare_column_options(column)
    spec = super
    spec[:enum_type] = column.sql_type if column.type == :enum
    spec[:array] = 'true' if column.respond_to?(:array) && column.array
    spec
    end

    # Needs overwrite as some tables report different primary key type
    # Problem was introduced by switch to activerecord 5.*
    def default_primary_key?(column)
    schema_type(column) == :bigserial || schema_type(column) == :serial
    end
    end
    end

    module PostgreSQL::SchemaStatements
    def create_enum(name, *values)
    execute "CREATE TYPE #{name} AS ENUM (#{values.map{|v| "'#{v}'"}.join(', ')})"
    end

    def drop_enum(name)
    execute "DROP TYPE #{name}"
    end
    end
    end
    end