File: behaviors.rb

package info (click to toggle)
rails 2%3A7.2.2.1%2Bdfsg-7
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 43,352 kB
  • sloc: ruby: 349,799; javascript: 30,703; yacc: 46; sql: 43; sh: 29; makefile: 27
file content (148 lines) | stat: -rw-r--r-- 5,812 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# frozen_string_literal: true

require "active_support/notifications"

module ActiveSupport
  # Raised when ActiveSupport::Deprecation::Behavior#behavior is set with <tt>:raise</tt>.
  # You would set <tt>:raise</tt>, as a behavior to raise errors and proactively report exceptions from deprecations.
  class DeprecationException < StandardError
  end

  class Deprecation
    # Default warning behaviors per Rails.env.
    DEFAULT_BEHAVIORS = {
      raise: ->(message, callstack, deprecator) do
        e = DeprecationException.new(message)
        e.set_backtrace(callstack.map(&:to_s))
        raise e
      end,

      stderr: ->(message, callstack, deprecator) do
        $stderr.puts(message)
        $stderr.puts callstack.join("\n  ") if deprecator.debug
      end,

      log: ->(message, callstack, deprecator) do
        logger =
            if defined?(Rails.logger) && Rails.logger
              Rails.logger
            else
              require "active_support/logger"
              ActiveSupport::Logger.new($stderr)
            end
        logger.warn message
        logger.debug callstack.join("\n  ") if deprecator.debug
      end,

      notify: ->(message, callstack, deprecator) do
        ActiveSupport::Notifications.instrument(
          "deprecation.#{deprecator.gem_name.underscore.tr("/", "_")}",
          message: message,
          callstack: callstack,
          gem_name: deprecator.gem_name,
          deprecation_horizon: deprecator.deprecation_horizon,
        )
      end,

      silence: ->(message, callstack, deprecator) { },

      report: ->(message, callstack, deprecator) do
        error = DeprecationException.new(message)
        error.set_backtrace(callstack.map(&:to_s))
        ActiveSupport.error_reporter.report(error)
      end
    }

    # Behavior module allows to determine how to display deprecation messages.
    # You can create a custom behavior or set any from the +DEFAULT_BEHAVIORS+
    # constant. Available behaviors are:
    #
    # [+:raise+]   Raise ActiveSupport::DeprecationException.
    # [+:stderr+]  Log all deprecation warnings to <tt>$stderr</tt>.
    # [+:log+]     Log all deprecation warnings to +Rails.logger+.
    # [+:notify+]  Use ActiveSupport::Notifications to notify +deprecation.rails+.
    # [+:report+]  Use ActiveSupport::ErrorReporter to report deprecations.
    # [+:silence+] Do nothing. On \Rails, set <tt>config.active_support.report_deprecations = false</tt> to disable all behaviors.
    #
    # Setting behaviors only affects deprecations that happen after boot time.
    # For more information you can read the documentation of the #behavior= method.
    module Behavior
      # Whether to print a backtrace along with the warning.
      attr_accessor :debug

      # Returns the current behavior or if one isn't set, defaults to +:stderr+.
      def behavior
        @behavior ||= [DEFAULT_BEHAVIORS[:stderr]]
      end

      # Returns the current behavior for disallowed deprecations or if one isn't set, defaults to +:raise+.
      def disallowed_behavior
        @disallowed_behavior ||= [DEFAULT_BEHAVIORS[:raise]]
      end

      # Sets the behavior to the specified value. Can be a single value, array,
      # or an object that responds to +call+.
      #
      # Available behaviors:
      #
      # [+:raise+]   Raise ActiveSupport::DeprecationException.
      # [+:stderr+]  Log all deprecation warnings to <tt>$stderr</tt>.
      # [+:log+]     Log all deprecation warnings to +Rails.logger+.
      # [+:notify+]  Use ActiveSupport::Notifications to notify +deprecation.rails+.
      # [+:report+]  Use ActiveSupport::ErrorReporter to report deprecations.
      # [+:silence+] Do nothing.
      #
      # Setting behaviors only affects deprecations that happen after boot time.
      # Deprecation warnings raised by gems are not affected by this setting
      # because they happen before \Rails boots up.
      #
      #   deprecator = ActiveSupport::Deprecation.new
      #   deprecator.behavior = :stderr
      #   deprecator.behavior = [:stderr, :log]
      #   deprecator.behavior = MyCustomHandler
      #   deprecator.behavior = ->(message, callstack, deprecation_horizon, gem_name) {
      #     # custom stuff
      #   }
      #
      # If you are using \Rails, you can set
      # <tt>config.active_support.report_deprecations = false</tt> to disable
      # all deprecation behaviors. This is similar to the +:silence+ option but
      # more performant.
      def behavior=(behavior)
        @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
      end

      # Sets the behavior for disallowed deprecations (those configured by
      # ActiveSupport::Deprecation#disallowed_warnings=) to the specified
      # value. As with #behavior=, this can be a single value, array, or an
      # object that responds to +call+.
      def disallowed_behavior=(behavior)
        @disallowed_behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
      end

      private
        def arity_coerce(behavior)
          unless behavior.respond_to?(:call)
            raise ArgumentError, "#{behavior.inspect} is not a valid deprecation behavior."
          end

          case arity_of_callable(behavior)
          when 2
            ->(message, callstack, deprecator) do
              behavior.call(message, callstack)
            end
          when -2..3
            behavior
          else
            ->(message, callstack, deprecator) do
              behavior.call(message, callstack, deprecator.deprecation_horizon, deprecator.gem_name)
            end
          end
        end

        def arity_of_callable(callable)
          callable.respond_to?(:arity) ? callable.arity : callable.method(:call).arity
        end
    end
  end
end