module PGTrunk::Generators

@private @abstract Module to build object-specific generators

Public Class Methods

build_generator(operation) click to toggle source

rubocop: disable Metrics/MethodLength

# File lib/pg_trunk/core/generators.rb, line 23
def build_generator(operation)
  Class.new(Rails::Generators::NamedBase) do
    include Rails::Generators::Migration
    include PGTrunk::Generators

    # Add the same arguments as in ruby method
    operation.ruby_params.each do |name|
      argument(name, **operation.attributes[name])
    end

    # Add the same options as in ruby method
    operation.attributes.except(*operation.ruby_params).each do |name, opts|
      class_option(name, **opts)
    end

    # The only command of the generator is to create a migration file
    create_command(:create_migration_file)
  end
end
register(operation) click to toggle source

Add new generator for given operation @param [Class < PGTrunk::Operation] operation

# File lib/pg_trunk/core/generators.rb, line 15
def register(operation)
  klass = build_generator(operation)
  class_name = klass.name.split("::").last.to_sym
  remove_const(class_name) if const_defined?(class_name)
  const_set(class_name, klass)
end

Public Instance Methods

create_migration_file() click to toggle source
# File lib/pg_trunk/core/generators.rb, line 84
  def create_migration_file
    file_name = "db/migrate/#{migration_number}_#{migration_name}.rb"
    file = create_migration(file_name, nil, {}) do
      <<~RUBY
        # frozen_string_literal: true

        class #{migration_name.camelize} < #{migration_base}
          def change
            #{command}
          end
        end
      RUBY
    end
    Rails::Generators.add_generated_file(file)
  end
handle(*arguments, **options) click to toggle source

Ruby handler to add positional arguments to options

# File lib/pg_trunk/core/generators.rb, line 75
def handle(*arguments, **options)
  options.ruby_params.zip(arguments).merge(options)
end
name() click to toggle source

Use the name of the object as a name of the generator class

# File lib/pg_trunk/core/generators.rb, line 65
def name
  @name ||= "PGTrunk::Generators::#{object_name.camelize}"
end
next_migration_number(dir) click to toggle source
# File lib/pg_trunk/core/generators.rb, line 79
def next_migration_number(dir)
  ::ActiveRecord::Generators::Base.next_migration_number(dir)
end
object_name() click to toggle source

The name of the generated object like ‘foreign_key` for the `add_foreign_key` operation so that the command

rails g foreign_key 'users', 'roles'

to build the migration containing

def change
  add_foreign_key 'users', 'roles'
end
# File lib/pg_trunk/core/generators.rb, line 60
def object_name
  @object_name ||= operation.object.singularize
end
operation_name() click to toggle source

The name of the operation to be added to the migration

# File lib/pg_trunk/core/generators.rb, line 70
def operation_name
  @operation_name ||= operation.ruby_name
end

Private Instance Methods

command() click to toggle source
# File lib/pg_trunk/core/generators.rb, line 135
def command
  opts = self.class.handle(*arguments, **options.symbolize_keys)
  operation = self.class.operation.new(opts)
  operation.to_ruby.indent(4).strip
end
current_version() click to toggle source
# File lib/pg_trunk/core/generators.rb, line 102
def current_version
  return @current_version if instance_variable_defined?(:@current_version)

  @current_version = nil
  return unless ActiveRecord::Migration.respond_to?(:current_version)

  @current_version = ActiveRecord::Migration.current_version
end
migration_base() click to toggle source
# File lib/pg_trunk/core/generators.rb, line 127
def migration_base
  @migration_base ||= "::ActiveRecord::Migration".tap do |mb|
    next if Rails::Version::MAJOR < "5"

    mb << "[#{current_version}]" if current_version.present?
  end
end
migration_name() click to toggle source

Build the name of the migration from given params like:

rails g foreign_key 'users', 'roles'

to generate the migration named as:

class AddForeignKeyUsersRoles < ::ActiveRecord::Migration[6.2]
  # ...
end
# File lib/pg_trunk/core/generators.rb, line 120
def migration_name
  @migration_name ||= [
    self.class.operation_name,
    *(self.class.operation.ruby_params.map { |p| send(p) }),
  ].join("_")
end