module Deprecation class << self # Outputs a deprecation warning to the output configured by ActiveSupport::Deprecation.behavior # # Deprecation.warn("something broke!") # # => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)" def warn(context, message = nil, callstack = caller) return if context.silenced deprecation_message(callstack, message).tap do |m| context.deprecation_behavior.each { |b| b.call(m, callstack) } end end # Silence deprecation warnings within the block. def silence context old_silenced, context.silenced = context.silenced, true yield ensure context.silenced = old_silenced end def collect(context) old_behavior = context.deprecation_behavior deprecations = [] context.deprecation_behavior = Proc.new do |message, callstack| deprecations << message end result = yield [result, deprecations] ensure context.deprecation_behavior = old_behavior end def deprecated_method_warning(context, method_name, options = nil) options ||= {} if options.is_a? String or options.is_a? Symbol message = options options = {} end warning = "#{method_name} is deprecated and will be removed from #{options[:deprecation_horizon] || context.deprecation_horizon}" case message when Symbol then "#{warning} (use #{message} instead)" when String then "#{warning} (#{message})" else warning end end private def deprecation_message(callstack, message = nil) message ||= "You are using deprecated behavior which will be removed from the next major or minor release." message += '.' unless message =~ /\.$/ "DEPRECATION WARNING: #{message} #{deprecation_caller_message(callstack)}" end def deprecation_caller_message(callstack) file, line, method = extract_callstack(callstack) if file if line && method "(called from #{method} at #{file}:#{line})" else "(called from #{file}:#{line})" end end end def extract_callstack(callstack) deprecation_gem_root = File.expand_path("../..", __FILE__) + "/" offending_line = callstack.find { |line| !line.start_with?(deprecation_gem_root) } || callstack.first if offending_line if md = offending_line.match(/^(.+?):(\d+)(?::in `(.*?)')?/) md.captures else offending_line end end end end end