module Faker::Deprecator

Provides a way to rename generators, including their namespaces, with a deprecation cycle in which both the old and new names work, but using the old one prints a deprecation message.

Deprecator provides a deprecate_generator method to be used when renaming a generator. For example, let’s say we want to change the following Generator’s name to Faker::NewGenerator:

module Faker
  class Generator
    def self.generate
      "be kind"
    end
  end
end

To rename it, you need to do the update the name and declare the deprecation by including the Deprecator module and using the deprecate_generator method:

module Faker
  class NewGenerator
    def self.generate
      "be kind"
    end
  end

  include Deprecator
  deprecate_generator('DeprecatedGenerator', NewGenerator)
end

The first argument is a constant name (no colons) as a string. It is the name of the constant you want to deprecate.

The second argument is the constant path of the replacement (no colons) as a constant.

For this to work, a const_missing hook is installed. When users reference the deprecated constant, the callback prints the message and constantizes the replacement.

With that in place, references to Faker::Deprecator still work, they evaluate to Faker::NewGenerator now, and trigger a deprecation warning:

Faker::Generator.generate
# DEPRECATION WARNING: Faker::Generator is deprecated. Use Faker::NewGenerator instead
# "be kind"

For testing the deprecations, we provide assert_deprecated and assert_not_deprecated matchers.

There’s also a Faker::Deprecator.skip_warning helper to silence the deprecation messages in the test output. Use it for generators that have lots of tests to avoid too many noise when running the tests.

Public Class Methods

included(base) click to toggle source
# File lib/helpers/deprecator.rb, line 60
def self.included(base)
  extension = Module.new do
    def const_missing(missing_const_name)
      if class_variable_defined?(:@@_deprecated_constants) && (replacement = class_variable_get(:@@_deprecated_constants)[missing_const_name.to_s])
        unless Faker::Deprecator.skip_warning?
          deprecated_message = "#{name}::#{replacement[:old_generator]} is deprecated."
          replacement_message = "Use #{replacement[:new_constant]} instead."
          $stdout.puts("DEPRECATION WARNING: #{deprecated_message} #{replacement_message}")
        end

        return replacement[:new_constant]
      end

      super
    end

    def deprecate_generator(old_generator_name, new_generator_constant)
      class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
      class_variable_get(:@@_deprecated_constants)[old_generator_name] = {
        new_constant: new_generator_constant,
        old_generator: old_generator_name
      }
    end
  end

  base.singleton_class.prepend extension
end
skip() click to toggle source
# File lib/helpers/deprecator.rb, line 109
def self.skip
  @skip ||= false
end
skip=(value) click to toggle source
# File lib/helpers/deprecator.rb, line 113
def self.skip=(value)
  @skip = value
end
skip_warning() { || ... } click to toggle source

Silence deprecation warnings within the block.

Faker::Generator.generate
# => DEPRECATION WARNING: Faker::Generator is deprecated. Use Faker::NewGenerator instead.

Faker::Deprecator.skip_warning do
  Faker::Generator.generate
end
# => nil
# File lib/helpers/deprecator.rb, line 97
def self.skip_warning
  original = Faker::Deprecator.skip
  Faker::Deprecator.skip = true
  yield
ensure
  Faker::Deprecator.skip = original
end
skip_warning?() click to toggle source
# File lib/helpers/deprecator.rb, line 105
def self.skip_warning?
  skip == true
end

Public Instance Methods

const_missing(missing_const_name) click to toggle source
Calls superclass method
# File lib/helpers/deprecator.rb, line 62
def const_missing(missing_const_name)
  if class_variable_defined?(:@@_deprecated_constants) && (replacement = class_variable_get(:@@_deprecated_constants)[missing_const_name.to_s])
    unless Faker::Deprecator.skip_warning?
      deprecated_message = "#{name}::#{replacement[:old_generator]} is deprecated."
      replacement_message = "Use #{replacement[:new_constant]} instead."
      $stdout.puts("DEPRECATION WARNING: #{deprecated_message} #{replacement_message}")
    end

    return replacement[:new_constant]
  end

  super
end
deprecate_generator(old_generator_name, new_generator_constant) click to toggle source
# File lib/helpers/deprecator.rb, line 76
def deprecate_generator(old_generator_name, new_generator_constant)
  class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
  class_variable_get(:@@_deprecated_constants)[old_generator_name] = {
    new_constant: new_generator_constant,
    old_generator: old_generator_name
  }
end