module PGTrunk::Operations::Enums

@private Namespace for operations with functions

@!parse

class ActiveRecord::Migration
  # Modify an enumerated type
  #
  # @param [#to_s] name (nil) The qualified name of the type
  # @yield [e] the block with the type's definition
  # @yieldparam Object receiver of methods specifying the type
  # @return [void]
  #
  # The operation can be used to rename or add values to the
  # enumerated type. The commend can be changed as well.
  #
  # ```ruby
  # change_enum "currencies" do |e|
  #   e.add_value "EUR", after: "BTC"
  #   e.add_value "GBP", before: "usd"
  #   e.add_value "JPY" # to the end of the list
  #   e.rename_value "usd", to: "USD"
  #   e.comment <<~COMMENT, from: <<~COMMENT
  #     Supported currencies
  #   COMMENT
  #     Currencies
  #   COMMENT
  # end
  # ```
  #
  # Please, keep in mind that all values will be added before
  # the first rename. That's why you should use old values
  # (like the `usd` instead of the `USD` in the example above)
  # in `before` and `after` options.
  #
  # Also notice that PostgreSQL doesn't support value deletion,
  # that's why adding any value makes the migration irreversible.
  #
  # It is also irreversible if you changed the comment, but
  # not defined its previous value.
  def change_enum(name, &block); end
end

@!parse

class ActiveRecord::Migration
  # Create an enumerated type by qualified name
  #
  # @param [#to_s] name (nil) The qualified name of the type
  # @option options [Array<#to_s>] :values ([]) The list of values
  # @option options [#to_s] :comment (nil) The comment describing the constraint
  # @yield [e] the block with the type's definition
  # @yieldparam Object receiver of methods specifying the type
  # @return [void]
  #
  # ```ruby
  # create_enum "finances.currency" do |e|
  #   e.values "BTC", "EUR", "GBP", "USD"
  #   e.value "JPY" # the alternative way to add a value to the tail
  #   e.comment <<~COMMENT
  #     The list of values for supported currencies.
  #   COMMENT
  # end
  # ```
  #
  # It is always reversible.
  def create_enum(name, **options, &block); end
end

@!parse

class ActiveRecord::Migration
  # Drop an enumerated type by qualified name
  #
  # @param [#to_s] name (nil) The qualified name of the type
  # @option options [Boolean] :if_exists (false) Suppress the error when the type is absent
  # @option options [Symbol] :force (:restrict) How to process dependent objects (`:cascade` or `:restrict`)
  # @option options [Array<#to_s>] :values ([]) The list of values
  # @option options [#to_s] :comment (nil) The comment describing the constraint
  # @yield [e] the block with the type's definition
  # @yieldparam Object receiver of methods specifying the type
  # @return [void]
  #
  # The operation drops a enumerated type identified by its
  # qualified name (it can include a schema).
  #
  # ```ruby
  # drop_enum "finances.currency"
  # ```
  #
  # To make the operation invertible, use the same options
  # as in the `create_enum` operation.
  #
  # ```ruby
  # drop_enum "finances.currency" do |e|
  #   e.values "BTC", "EUR", "GBP", "USD"
  #   e.value "JPY" # the alternative way to add a value
  #   e.comment <<~COMMENT
  #     The list of values for supported currencies.
  #   COMMENT
  # end
  # ```
  #
  # With the `force: :cascade` option the operation would remove
  # all the objects that use the type.
  #
  # ```ruby
  # drop_enum "finances.currency", force: :cascade
  # ```
  #
  # With the `if_exists: true` option the operation won't fail
  # even when the view was absent in the database.
  #
  # ```ruby
  # drop_enum "finances.currency", if_exists: true
  # ```
  #
  # Both options make a migration irreversible due to uncertainty
  # of the previous state of the database.
  def drop_enum(name, **options, &block); end
end

@!parse

class ActiveRecord::Migration
  # Change the name and/or schema of an enumerated type
  #
  # @param [#to_s] :name (nil) The qualified name of the type
  # @option options [#to_s] :to (nil) The new qualified name for the type
  # @return [void]
  #
  # @example:
  #
  # ```ruby
  # rename_enum "currencies", to: "finances.currency"
  # ```
  #
  # The operation is always reversible.
  def rename_enum(name, to:); end
end