class Dont

Defines a `dont_use` method which can be used to deprecate methods. Whenever the deprecated method is used the specified handler will get triggered.

@example

# Register a deprecation handler.
# Anything that responds to `.call(deprecation)` will work.
LOGGER = Logger.new
Dont.register_handler(:logger, ->(deprecation) { LOGGER.warn(deprecation.message) })
class Shouter
  include Dont.new(:logger)

  def shout(msg)
    msg.upcase
  end

  def scream(msg)
    shout(msg)
  end
  dont_use :scream, use: :shout
end

# Logs "DEPRECATED: Don't use Shouter#scream. It's deprecated in favor of
# shout.", before executing the method.
Shouter.new.scream("hello")

# The :exception deprecation handler is provided by default.
# It raises an exception whenever the method is called, which is handy in
# test or development mode.
class Person
  include Dont.new(:exception)

  attr_accessor :firstname
  attr_accessor :first_name

  dont_use :firstname, use: :first_name
end
Person.new.firstname # => fails with Dont::DeprecationError

Constants

DeprecationError
Error
MissingHandlerError
VERSION
WithException
WithWarn

Public Class Methods

fetch_handler(key) click to toggle source
# File lib/dont.rb, line 95
def fetch_handler(key)
  handlers.resolve(key)
rescue Dry::Container::Error => e
  fail MissingHandlerError, e.message
end
new(key) click to toggle source
# File lib/dont.rb, line 49
def initialize(key)
  handler = Dont.fetch_handler(key)
  @implementation = ->(old_method, use: nil) {
    # The moment `dont_use` is called in ActiveRecord is before AR defines
    # the attributes in the model. So you get an error when calling
    # instance_method with the regular implementation.
    #
    # This hack determines if it's an ActiveRecord attribute or not, and
    # adapts the code.
    is_ar_attribute = defined?(ActiveRecord::Base) &&
      ancestors.include?(ActiveRecord::Base) &&
      !method_defined?(old_method)

    original = instance_method(old_method) unless is_ar_attribute
    define_method(old_method) do |*args|
      deprecation = Deprecation.new(
        subject: self,
        new_method: use,
        old_method: old_method,
      )
      handler.call(deprecation)
      if is_ar_attribute
        if old_method =~ /=\z/
          attr = old_method.to_s.sub(/=\z/, '')
          public_send(:[]=, attr, *args)
        else
          self[old_method.to_s.sub(/\?\z/, '')]
        end
      else
        original.bind(self).call(*args)
      end
    end
  }
end
register_handler(key, callable) click to toggle source
# File lib/dont.rb, line 91
def register_handler(key, callable)
  handlers.register(key, callable)
end

Protected Class Methods

handlers() click to toggle source
# File lib/dont.rb, line 103
def handlers
  @handlers ||= Dry::Container.new
end

Public Instance Methods

included(base) click to toggle source
# File lib/dont.rb, line 84
def included(base)
  base.instance_exec(@implementation) do |impl|
    define_singleton_method(:dont_use, &impl)
  end
end