core_ext 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +3 -0
- data/lib/core_ext/array/access.rb +76 -0
- data/lib/core_ext/array/conversions.rb +211 -0
- data/lib/core_ext/array/extract_options.rb +29 -0
- data/lib/core_ext/array/grouping.rb +116 -0
- data/lib/core_ext/array/inquiry.rb +17 -0
- data/lib/core_ext/array/prepend_and_append.rb +7 -0
- data/lib/core_ext/array/wrap.rb +46 -0
- data/lib/core_ext/array.rb +7 -0
- data/lib/core_ext/array_inquirer.rb +44 -0
- data/lib/core_ext/benchmark.rb +14 -0
- data/lib/core_ext/benchmarkable.rb +49 -0
- data/lib/core_ext/big_decimal/conversions.rb +14 -0
- data/lib/core_ext/big_decimal.rb +1 -0
- data/lib/core_ext/builder.rb +6 -0
- data/lib/core_ext/callbacks.rb +770 -0
- data/lib/core_ext/class/attribute.rb +128 -0
- data/lib/core_ext/class/attribute_accessors.rb +4 -0
- data/lib/core_ext/class/subclasses.rb +42 -0
- data/lib/core_ext/class.rb +2 -0
- data/lib/core_ext/concern.rb +142 -0
- data/lib/core_ext/configurable.rb +148 -0
- data/lib/core_ext/date/acts_like.rb +8 -0
- data/lib/core_ext/date/blank.rb +12 -0
- data/lib/core_ext/date/calculations.rb +143 -0
- data/lib/core_ext/date/conversions.rb +93 -0
- data/lib/core_ext/date/zones.rb +6 -0
- data/lib/core_ext/date.rb +5 -0
- data/lib/core_ext/date_and_time/calculations.rb +328 -0
- data/lib/core_ext/date_and_time/zones.rb +40 -0
- data/lib/core_ext/date_time/acts_like.rb +14 -0
- data/lib/core_ext/date_time/blank.rb +12 -0
- data/lib/core_ext/date_time/calculations.rb +177 -0
- data/lib/core_ext/date_time/conversions.rb +104 -0
- data/lib/core_ext/date_time/zones.rb +6 -0
- data/lib/core_ext/date_time.rb +5 -0
- data/lib/core_ext/deprecation/behaviors.rb +86 -0
- data/lib/core_ext/deprecation/instance_delegator.rb +24 -0
- data/lib/core_ext/deprecation/method_wrappers.rb +70 -0
- data/lib/core_ext/deprecation/proxy_wrappers.rb +149 -0
- data/lib/core_ext/deprecation/reporting.rb +105 -0
- data/lib/core_ext/deprecation.rb +43 -0
- data/lib/core_ext/digest/uuid.rb +51 -0
- data/lib/core_ext/duration.rb +157 -0
- data/lib/core_ext/enumerable.rb +106 -0
- data/lib/core_ext/file/atomic.rb +68 -0
- data/lib/core_ext/file.rb +1 -0
- data/lib/core_ext/hash/compact.rb +20 -0
- data/lib/core_ext/hash/conversions.rb +261 -0
- data/lib/core_ext/hash/deep_merge.rb +38 -0
- data/lib/core_ext/hash/except.rb +22 -0
- data/lib/core_ext/hash/indifferent_access.rb +23 -0
- data/lib/core_ext/hash/keys.rb +170 -0
- data/lib/core_ext/hash/reverse_merge.rb +22 -0
- data/lib/core_ext/hash/slice.rb +48 -0
- data/lib/core_ext/hash/transform_values.rb +29 -0
- data/lib/core_ext/hash.rb +9 -0
- data/lib/core_ext/hash_with_indifferent_access.rb +298 -0
- data/lib/core_ext/inflections.rb +70 -0
- data/lib/core_ext/inflector/inflections.rb +244 -0
- data/lib/core_ext/inflector/methods.rb +381 -0
- data/lib/core_ext/inflector/transliterate.rb +112 -0
- data/lib/core_ext/inflector.rb +7 -0
- data/lib/core_ext/integer/inflections.rb +29 -0
- data/lib/core_ext/integer/multiple.rb +10 -0
- data/lib/core_ext/integer/time.rb +29 -0
- data/lib/core_ext/integer.rb +3 -0
- data/lib/core_ext/json/decoding.rb +67 -0
- data/lib/core_ext/json/encoding.rb +127 -0
- data/lib/core_ext/json.rb +2 -0
- data/lib/core_ext/kernel/agnostics.rb +11 -0
- data/lib/core_ext/kernel/concern.rb +10 -0
- data/lib/core_ext/kernel/reporting.rb +41 -0
- data/lib/core_ext/kernel/singleton_class.rb +6 -0
- data/lib/core_ext/kernel.rb +4 -0
- data/lib/core_ext/load_error.rb +30 -0
- data/lib/core_ext/logger.rb +57 -0
- data/lib/core_ext/logger_silence.rb +24 -0
- data/lib/core_ext/marshal.rb +19 -0
- data/lib/core_ext/module/aliasing.rb +74 -0
- data/lib/core_ext/module/anonymous.rb +28 -0
- data/lib/core_ext/module/attr_internal.rb +36 -0
- data/lib/core_ext/module/attribute_accessors.rb +212 -0
- data/lib/core_ext/module/concerning.rb +135 -0
- data/lib/core_ext/module/delegation.rb +218 -0
- data/lib/core_ext/module/deprecation.rb +23 -0
- data/lib/core_ext/module/introspection.rb +62 -0
- data/lib/core_ext/module/method_transplanting.rb +3 -0
- data/lib/core_ext/module/qualified_const.rb +52 -0
- data/lib/core_ext/module/reachable.rb +8 -0
- data/lib/core_ext/module/remove_method.rb +35 -0
- data/lib/core_ext/module.rb +11 -0
- data/lib/core_ext/multibyte/chars.rb +231 -0
- data/lib/core_ext/multibyte/unicode.rb +388 -0
- data/lib/core_ext/multibyte.rb +21 -0
- data/lib/core_ext/name_error.rb +31 -0
- data/lib/core_ext/numeric/bytes.rb +64 -0
- data/lib/core_ext/numeric/conversions.rb +132 -0
- data/lib/core_ext/numeric/inquiry.rb +26 -0
- data/lib/core_ext/numeric/time.rb +74 -0
- data/lib/core_ext/numeric.rb +4 -0
- data/lib/core_ext/object/acts_like.rb +10 -0
- data/lib/core_ext/object/blank.rb +140 -0
- data/lib/core_ext/object/conversions.rb +4 -0
- data/lib/core_ext/object/deep_dup.rb +53 -0
- data/lib/core_ext/object/duplicable.rb +98 -0
- data/lib/core_ext/object/inclusion.rb +27 -0
- data/lib/core_ext/object/instance_variables.rb +28 -0
- data/lib/core_ext/object/json.rb +199 -0
- data/lib/core_ext/object/to_param.rb +1 -0
- data/lib/core_ext/object/to_query.rb +84 -0
- data/lib/core_ext/object/try.rb +146 -0
- data/lib/core_ext/object/with_options.rb +69 -0
- data/lib/core_ext/object.rb +14 -0
- data/lib/core_ext/option_merger.rb +25 -0
- data/lib/core_ext/ordered_hash.rb +48 -0
- data/lib/core_ext/ordered_options.rb +81 -0
- data/lib/core_ext/range/conversions.rb +34 -0
- data/lib/core_ext/range/each.rb +21 -0
- data/lib/core_ext/range/include_range.rb +23 -0
- data/lib/core_ext/range/overlaps.rb +8 -0
- data/lib/core_ext/range.rb +4 -0
- data/lib/core_ext/regexp.rb +5 -0
- data/lib/core_ext/rescuable.rb +119 -0
- data/lib/core_ext/securerandom.rb +23 -0
- data/lib/core_ext/security_utils.rb +20 -0
- data/lib/core_ext/string/access.rb +104 -0
- data/lib/core_ext/string/behavior.rb +6 -0
- data/lib/core_ext/string/conversions.rb +56 -0
- data/lib/core_ext/string/exclude.rb +11 -0
- data/lib/core_ext/string/filters.rb +102 -0
- data/lib/core_ext/string/indent.rb +43 -0
- data/lib/core_ext/string/inflections.rb +235 -0
- data/lib/core_ext/string/inquiry.rb +13 -0
- data/lib/core_ext/string/multibyte.rb +53 -0
- data/lib/core_ext/string/output_safety.rb +261 -0
- data/lib/core_ext/string/starts_ends_with.rb +4 -0
- data/lib/core_ext/string/strip.rb +23 -0
- data/lib/core_ext/string/zones.rb +14 -0
- data/lib/core_ext/string.rb +13 -0
- data/lib/core_ext/string_inquirer.rb +26 -0
- data/lib/core_ext/tagged_logging.rb +78 -0
- data/lib/core_ext/test_case.rb +88 -0
- data/lib/core_ext/testing/assertions.rb +99 -0
- data/lib/core_ext/testing/autorun.rb +12 -0
- data/lib/core_ext/testing/composite_filter.rb +54 -0
- data/lib/core_ext/testing/constant_lookup.rb +50 -0
- data/lib/core_ext/testing/declarative.rb +26 -0
- data/lib/core_ext/testing/deprecation.rb +36 -0
- data/lib/core_ext/testing/file_fixtures.rb +34 -0
- data/lib/core_ext/testing/isolation.rb +115 -0
- data/lib/core_ext/testing/method_call_assertions.rb +41 -0
- data/lib/core_ext/testing/setup_and_teardown.rb +50 -0
- data/lib/core_ext/testing/stream.rb +42 -0
- data/lib/core_ext/testing/tagged_logging.rb +25 -0
- data/lib/core_ext/testing/time_helpers.rb +134 -0
- data/lib/core_ext/time/acts_like.rb +8 -0
- data/lib/core_ext/time/calculations.rb +284 -0
- data/lib/core_ext/time/conversions.rb +66 -0
- data/lib/core_ext/time/zones.rb +95 -0
- data/lib/core_ext/time.rb +20 -0
- data/lib/core_ext/time_with_zone.rb +503 -0
- data/lib/core_ext/time_zone.rb +464 -0
- data/lib/core_ext/uri.rb +25 -0
- data/lib/core_ext/version.rb +3 -0
- data/lib/core_ext/xml_mini/jdom.rb +181 -0
- data/lib/core_ext/xml_mini/libxml.rb +79 -0
- data/lib/core_ext/xml_mini/libxmlsax.rb +85 -0
- data/lib/core_ext/xml_mini/nokogiri.rb +83 -0
- data/lib/core_ext/xml_mini/nokogirisax.rb +87 -0
- data/lib/core_ext/xml_mini/rexml.rb +130 -0
- data/lib/core_ext/xml_mini.rb +194 -0
- data/lib/core_ext.rb +3 -0
- metadata +310 -0
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'core_ext/time/conversions'
|
3
|
+
require 'core_ext/date_time/calculations'
|
4
|
+
require 'core_ext/time_zone'
|
5
|
+
|
6
|
+
class DateTime
|
7
|
+
# Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
|
8
|
+
#
|
9
|
+
# This method is aliased to <tt>to_s</tt>.
|
10
|
+
#
|
11
|
+
# === Examples
|
12
|
+
# datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000
|
13
|
+
#
|
14
|
+
# datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00"
|
15
|
+
# datetime.to_s(:db) # => "2007-12-04 00:00:00"
|
16
|
+
# datetime.to_s(:number) # => "20071204000000"
|
17
|
+
# datetime.to_formatted_s(:short) # => "04 Dec 00:00"
|
18
|
+
# datetime.to_formatted_s(:long) # => "December 04, 2007 00:00"
|
19
|
+
# datetime.to_formatted_s(:long_ordinal) # => "December 4th, 2007 00:00"
|
20
|
+
# datetime.to_formatted_s(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
|
21
|
+
# datetime.to_formatted_s(:iso8601) # => "2007-12-04T00:00:00+00:00"
|
22
|
+
#
|
23
|
+
# == Adding your own datetime formats to to_formatted_s
|
24
|
+
# DateTime formats are shared with Time. You can add your own to the
|
25
|
+
# Time::DATE_FORMATS hash. Use the format name as the hash key and
|
26
|
+
# either a strftime string or Proc instance that takes a time or
|
27
|
+
# datetime argument as the value.
|
28
|
+
#
|
29
|
+
# # config/initializers/time_formats.rb
|
30
|
+
# Time::DATE_FORMATS[:month_and_year] = '%B %Y'
|
31
|
+
# Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
|
32
|
+
def to_formatted_s(format = :default)
|
33
|
+
if formatter = ::Time::DATE_FORMATS[format]
|
34
|
+
formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
|
35
|
+
else
|
36
|
+
to_default_s
|
37
|
+
end
|
38
|
+
end
|
39
|
+
alias_method :to_default_s, :to_s if instance_methods(false).include?(:to_s)
|
40
|
+
alias_method :to_s, :to_formatted_s
|
41
|
+
|
42
|
+
# Returns a formatted string of the offset from UTC, or an alternative
|
43
|
+
# string if the time zone is already UTC.
|
44
|
+
#
|
45
|
+
# datetime = DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-6, 24))
|
46
|
+
# datetime.formatted_offset # => "-06:00"
|
47
|
+
# datetime.formatted_offset(false) # => "-0600"
|
48
|
+
def formatted_offset(colon = true, alternate_utc_string = nil)
|
49
|
+
utc? && alternate_utc_string || CoreExt::TimeZone.seconds_to_utc_offset(utc_offset, colon)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005 14:30:00 +0000".
|
53
|
+
def readable_inspect
|
54
|
+
to_s(:rfc822)
|
55
|
+
end
|
56
|
+
alias_method :default_inspect, :inspect
|
57
|
+
alias_method :inspect, :readable_inspect
|
58
|
+
|
59
|
+
# Returns DateTime with local offset for given year if format is local else
|
60
|
+
# offset is zero.
|
61
|
+
#
|
62
|
+
# DateTime.civil_from_format :local, 2012
|
63
|
+
# # => Sun, 01 Jan 2012 00:00:00 +0300
|
64
|
+
# DateTime.civil_from_format :local, 2012, 12, 17
|
65
|
+
# # => Mon, 17 Dec 2012 00:00:00 +0000
|
66
|
+
def self.civil_from_format(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0)
|
67
|
+
if utc_or_local.to_sym == :local
|
68
|
+
offset = ::Time.local(year, month, day).utc_offset.to_r / 86400
|
69
|
+
else
|
70
|
+
offset = 0
|
71
|
+
end
|
72
|
+
civil(year, month, day, hour, min, sec, offset)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Converts +self+ to a floating-point number of seconds, including fractional microseconds, since the Unix epoch.
|
76
|
+
def to_f
|
77
|
+
seconds_since_unix_epoch.to_f + sec_fraction
|
78
|
+
end
|
79
|
+
|
80
|
+
# Converts +self+ to an integer number of seconds since the Unix epoch.
|
81
|
+
def to_i
|
82
|
+
seconds_since_unix_epoch.to_i
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns the fraction of a second as microseconds
|
86
|
+
def usec
|
87
|
+
(sec_fraction * 1_000_000).to_i
|
88
|
+
end
|
89
|
+
|
90
|
+
# Returns the fraction of a second as nanoseconds
|
91
|
+
def nsec
|
92
|
+
(sec_fraction * 1_000_000_000).to_i
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def offset_in_seconds
|
98
|
+
(offset * 86400).to_i
|
99
|
+
end
|
100
|
+
|
101
|
+
def seconds_since_unix_epoch
|
102
|
+
(jd - 2440588) * 86400 - offset_in_seconds + seconds_since_midnight
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module CoreExt
|
2
|
+
class DeprecationException < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class Deprecation
|
6
|
+
# Default warning behaviors per Rails.env.
|
7
|
+
DEFAULT_BEHAVIORS = {
|
8
|
+
raise: ->(message, callstack) {
|
9
|
+
e = DeprecationException.new(message)
|
10
|
+
e.set_backtrace(callstack)
|
11
|
+
raise e
|
12
|
+
},
|
13
|
+
|
14
|
+
stderr: ->(message, callstack) {
|
15
|
+
$stderr.puts(message)
|
16
|
+
$stderr.puts callstack.join("\n ") if debug
|
17
|
+
},
|
18
|
+
|
19
|
+
log: ->(message, callstack) {
|
20
|
+
logger =
|
21
|
+
if defined?(Rails.logger) && Rails.logger
|
22
|
+
Rails.logger
|
23
|
+
else
|
24
|
+
require 'active_support/logger'
|
25
|
+
CoreExt::Logger.new($stderr)
|
26
|
+
end
|
27
|
+
logger.warn message
|
28
|
+
logger.debug callstack.join("\n ") if debug
|
29
|
+
},
|
30
|
+
|
31
|
+
notify: ->(message, callstack) {
|
32
|
+
CoreExt::Notifications.instrument("deprecation.rails",
|
33
|
+
:message => message, :callstack => callstack)
|
34
|
+
},
|
35
|
+
|
36
|
+
silence: ->(message, callstack) {},
|
37
|
+
}
|
38
|
+
|
39
|
+
# Behavior module allows to determine how to display deprecation messages.
|
40
|
+
# You can create a custom behavior or set any from the +DEFAULT_BEHAVIORS+
|
41
|
+
# constant. Available behaviors are:
|
42
|
+
#
|
43
|
+
# [+raise+] Raise <tt>CoreExt::DeprecationException</tt>.
|
44
|
+
# [+stderr+] Log all deprecation warnings to +$stderr+.
|
45
|
+
# [+log+] Log all deprecation warnings to +Rails.logger+.
|
46
|
+
# [+notify+] Use +CoreExt::Notifications+ to notify +deprecation.rails+.
|
47
|
+
# [+silence+] Do nothing.
|
48
|
+
#
|
49
|
+
# Setting behaviors only affects deprecations that happen after boot time.
|
50
|
+
# For more information you can read the documentation of the +behavior=+ method.
|
51
|
+
module Behavior
|
52
|
+
# Whether to print a backtrace along with the warning.
|
53
|
+
attr_accessor :debug
|
54
|
+
|
55
|
+
# Returns the current behavior or if one isn't set, defaults to +:stderr+.
|
56
|
+
def behavior
|
57
|
+
@behavior ||= [DEFAULT_BEHAVIORS[:stderr]]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Sets the behavior to the specified value. Can be a single value, array,
|
61
|
+
# or an object that responds to +call+.
|
62
|
+
#
|
63
|
+
# Available behaviors:
|
64
|
+
#
|
65
|
+
# [+raise+] Raise <tt>CoreExt::DeprecationException</tt>.
|
66
|
+
# [+stderr+] Log all deprecation warnings to +$stderr+.
|
67
|
+
# [+log+] Log all deprecation warnings to +Rails.logger+.
|
68
|
+
# [+notify+] Use +CoreExt::Notifications+ to notify +deprecation.rails+.
|
69
|
+
# [+silence+] Do nothing.
|
70
|
+
#
|
71
|
+
# Setting behaviors only affects deprecations that happen after boot time.
|
72
|
+
# Deprecation warnings raised by gems are not affected by this setting
|
73
|
+
# because they happen before Rails boots up.
|
74
|
+
#
|
75
|
+
# CoreExt::Deprecation.behavior = :stderr
|
76
|
+
# CoreExt::Deprecation.behavior = [:stderr, :log]
|
77
|
+
# CoreExt::Deprecation.behavior = MyCustomHandler
|
78
|
+
# CoreExt::Deprecation.behavior = ->(message, callstack) {
|
79
|
+
# # custom stuff
|
80
|
+
# }
|
81
|
+
def behavior=(behavior)
|
82
|
+
@behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || b }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'core_ext/kernel/singleton_class'
|
2
|
+
require 'core_ext/module/delegation'
|
3
|
+
|
4
|
+
module CoreExt
|
5
|
+
class Deprecation
|
6
|
+
module InstanceDelegator # :nodoc:
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
base.public_class_method :new
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods # :nodoc:
|
13
|
+
def include(included_module)
|
14
|
+
included_module.instance_methods.each { |m| method_added(m) }
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def method_added(method_name)
|
19
|
+
singleton_class.delegate(method_name, to: :instance)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'core_ext/module/aliasing'
|
2
|
+
require 'core_ext/array/extract_options'
|
3
|
+
|
4
|
+
module CoreExt
|
5
|
+
class Deprecation
|
6
|
+
module MethodWrapper
|
7
|
+
# Declare that a method has been deprecated.
|
8
|
+
#
|
9
|
+
# module Fred
|
10
|
+
# extend self
|
11
|
+
#
|
12
|
+
# def aaa; end
|
13
|
+
# def bbb; end
|
14
|
+
# def ccc; end
|
15
|
+
# def ddd; end
|
16
|
+
# def eee; end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# Using the default deprecator:
|
20
|
+
# CoreExt::Deprecation.deprecate_methods(Fred, :aaa, bbb: :zzz, ccc: 'use Bar#ccc instead')
|
21
|
+
# # => [:aaa, :bbb, :ccc]
|
22
|
+
#
|
23
|
+
# Fred.aaa
|
24
|
+
# # DEPRECATION WARNING: aaa is deprecated and will be removed from Rails 5.0. (called from irb_binding at (irb):10)
|
25
|
+
# # => nil
|
26
|
+
#
|
27
|
+
# Fred.bbb
|
28
|
+
# # DEPRECATION WARNING: bbb is deprecated and will be removed from Rails 5.0 (use zzz instead). (called from irb_binding at (irb):11)
|
29
|
+
# # => nil
|
30
|
+
#
|
31
|
+
# Fred.ccc
|
32
|
+
# # DEPRECATION WARNING: ccc is deprecated and will be removed from Rails 5.0 (use Bar#ccc instead). (called from irb_binding at (irb):12)
|
33
|
+
# # => nil
|
34
|
+
#
|
35
|
+
# Passing in a custom deprecator:
|
36
|
+
# custom_deprecator = CoreExt::Deprecation.new('next-release', 'MyGem')
|
37
|
+
# CoreExt::Deprecation.deprecate_methods(Fred, ddd: :zzz, deprecator: custom_deprecator)
|
38
|
+
# # => [:ddd]
|
39
|
+
#
|
40
|
+
# Fred.ddd
|
41
|
+
# DEPRECATION WARNING: ddd is deprecated and will be removed from MyGem next-release (use zzz instead). (called from irb_binding at (irb):15)
|
42
|
+
# # => nil
|
43
|
+
#
|
44
|
+
# Using a custom deprecator directly:
|
45
|
+
# custom_deprecator = CoreExt::Deprecation.new('next-release', 'MyGem')
|
46
|
+
# custom_deprecator.deprecate_methods(Fred, eee: :zzz)
|
47
|
+
# # => [:eee]
|
48
|
+
#
|
49
|
+
# Fred.eee
|
50
|
+
# DEPRECATION WARNING: eee is deprecated and will be removed from MyGem next-release (use zzz instead). (called from irb_binding at (irb):18)
|
51
|
+
# # => nil
|
52
|
+
def deprecate_methods(target_module, *method_names)
|
53
|
+
options = method_names.extract_options!
|
54
|
+
deprecator = options.delete(:deprecator) || self
|
55
|
+
method_names += options.keys
|
56
|
+
|
57
|
+
mod = Module.new do
|
58
|
+
method_names.each do |method_name|
|
59
|
+
define_method(method_name) do |*args, &block|
|
60
|
+
deprecator.deprecation_warning(method_name, options[method_name])
|
61
|
+
super(*args, &block)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
target_module.prepend(mod)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'core_ext/inflector/methods'
|
2
|
+
|
3
|
+
module CoreExt
|
4
|
+
class Deprecation
|
5
|
+
class DeprecationProxy #:nodoc:
|
6
|
+
def self.new(*args, &block)
|
7
|
+
object = args.first
|
8
|
+
|
9
|
+
return object unless object
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
instance_methods.each { |m| undef_method m unless m =~ /^__|^object_id$/ }
|
14
|
+
|
15
|
+
# Don't give a deprecation warning on inspect since test/unit and error
|
16
|
+
# logs rely on it for diagnostics.
|
17
|
+
def inspect
|
18
|
+
target.inspect
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def method_missing(called, *args, &block)
|
23
|
+
warn caller_locations, called, args
|
24
|
+
target.__send__(called, *args, &block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# DeprecatedObjectProxy transforms an object into a deprecated one. It
|
29
|
+
# takes an object, a deprecation message and optionally a deprecator. The
|
30
|
+
# deprecator defaults to +CoreExt::Deprecator+ if none is specified.
|
31
|
+
#
|
32
|
+
# deprecated_object = CoreExt::Deprecation::DeprecatedObjectProxy.new(Object.new, "This object is now deprecated")
|
33
|
+
# # => #<Object:0x007fb9b34c34b0>
|
34
|
+
#
|
35
|
+
# deprecated_object.to_s
|
36
|
+
# DEPRECATION WARNING: This object is now deprecated.
|
37
|
+
# (Backtrace)
|
38
|
+
# # => "#<Object:0x007fb9b34c34b0>"
|
39
|
+
class DeprecatedObjectProxy < DeprecationProxy
|
40
|
+
def initialize(object, message, deprecator = CoreExt::Deprecation.instance)
|
41
|
+
@object = object
|
42
|
+
@message = message
|
43
|
+
@deprecator = deprecator
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def target
|
48
|
+
@object
|
49
|
+
end
|
50
|
+
|
51
|
+
def warn(callstack, called, args)
|
52
|
+
@deprecator.warn(@message, callstack)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# DeprecatedInstanceVariableProxy transforms an instance variable into a
|
57
|
+
# deprecated one. It takes an instance of a class, a method on that class
|
58
|
+
# and an instance variable. It optionally takes a deprecator as the last
|
59
|
+
# argument. The deprecator defaults to +CoreExt::Deprecator+ if none
|
60
|
+
# is specified.
|
61
|
+
#
|
62
|
+
# class Example
|
63
|
+
# def initialize
|
64
|
+
# @request = CoreExt::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request)
|
65
|
+
# @_request = :special_request
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# def request
|
69
|
+
# @_request
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# def old_request
|
73
|
+
# @request
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# example = Example.new
|
78
|
+
# # => #<Example:0x007fb9b31090b8 @_request=:special_request, @request=:special_request>
|
79
|
+
#
|
80
|
+
# example.old_request.to_s
|
81
|
+
# # => DEPRECATION WARNING: @request is deprecated! Call request.to_s instead of
|
82
|
+
# @request.to_s
|
83
|
+
# (Bactrace information…)
|
84
|
+
# "special_request"
|
85
|
+
#
|
86
|
+
# example.request.to_s
|
87
|
+
# # => "special_request"
|
88
|
+
class DeprecatedInstanceVariableProxy < DeprecationProxy
|
89
|
+
def initialize(instance, method, var = "@#{method}", deprecator = CoreExt::Deprecation.instance)
|
90
|
+
@instance = instance
|
91
|
+
@method = method
|
92
|
+
@var = var
|
93
|
+
@deprecator = deprecator
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def target
|
98
|
+
@instance.__send__(@method)
|
99
|
+
end
|
100
|
+
|
101
|
+
def warn(callstack, called, args)
|
102
|
+
@deprecator.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# DeprecatedConstantProxy transforms a constant into a deprecated one. It
|
107
|
+
# takes the names of an old (deprecated) constant and of a new constant
|
108
|
+
# (both in string form) and optionally a deprecator. The deprecator defaults
|
109
|
+
# to +CoreExt::Deprecator+ if none is specified. The deprecated constant
|
110
|
+
# now returns the value of the new one.
|
111
|
+
#
|
112
|
+
# PLANETS = %w(mercury venus earth mars jupiter saturn uranus neptune pluto)
|
113
|
+
#
|
114
|
+
# (In a later update, the original implementation of `PLANETS` has been removed.)
|
115
|
+
#
|
116
|
+
# PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
|
117
|
+
# PLANETS = CoreExt::Deprecation::DeprecatedConstantProxy.new('PLANETS', 'PLANETS_POST_2006')
|
118
|
+
#
|
119
|
+
# PLANETS.map { |planet| planet.capitalize }
|
120
|
+
# # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
|
121
|
+
# (Bactrace information…)
|
122
|
+
# ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
|
123
|
+
class DeprecatedConstantProxy < DeprecationProxy
|
124
|
+
def initialize(old_const, new_const, deprecator = CoreExt::Deprecation.instance)
|
125
|
+
@old_const = old_const
|
126
|
+
@new_const = new_const
|
127
|
+
@deprecator = deprecator
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns the class of the new constant.
|
131
|
+
#
|
132
|
+
# PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
|
133
|
+
# PLANETS = CoreExt::Deprecation::DeprecatedConstantProxy.new('PLANETS', 'PLANETS_POST_2006')
|
134
|
+
# PLANETS.class # => Array
|
135
|
+
def class
|
136
|
+
target.class
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
def target
|
141
|
+
CoreExt::Inflector.constantize(@new_const.to_s)
|
142
|
+
end
|
143
|
+
|
144
|
+
def warn(callstack, called, args)
|
145
|
+
@deprecator.warn("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module CoreExt
|
2
|
+
class Deprecation
|
3
|
+
module Reporting
|
4
|
+
# Whether to print a message (silent mode)
|
5
|
+
attr_accessor :silenced
|
6
|
+
# Name of gem where method is deprecated
|
7
|
+
attr_accessor :gem_name
|
8
|
+
|
9
|
+
# Outputs a deprecation warning to the output configured by
|
10
|
+
# <tt>CoreExt::Deprecation.behavior</tt>.
|
11
|
+
#
|
12
|
+
# CoreExt::Deprecation.warn('something broke!')
|
13
|
+
# # => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"
|
14
|
+
def warn(message = nil, callstack = nil)
|
15
|
+
return if silenced
|
16
|
+
|
17
|
+
callstack ||= caller_locations(2)
|
18
|
+
deprecation_message(callstack, message).tap do |m|
|
19
|
+
behavior.each { |b| b.call(m, callstack) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Silence deprecation warnings within the block.
|
24
|
+
#
|
25
|
+
# CoreExt::Deprecation.warn('something broke!')
|
26
|
+
# # => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"
|
27
|
+
#
|
28
|
+
# CoreExt::Deprecation.silence do
|
29
|
+
# CoreExt::Deprecation.warn('something broke!')
|
30
|
+
# end
|
31
|
+
# # => nil
|
32
|
+
def silence
|
33
|
+
old_silenced, @silenced = @silenced, true
|
34
|
+
yield
|
35
|
+
ensure
|
36
|
+
@silenced = old_silenced
|
37
|
+
end
|
38
|
+
|
39
|
+
def deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = nil)
|
40
|
+
caller_backtrace ||= caller_locations(2)
|
41
|
+
deprecated_method_warning(deprecated_method_name, message).tap do |msg|
|
42
|
+
warn(msg, caller_backtrace)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
# Outputs a deprecation warning message
|
48
|
+
#
|
49
|
+
# CoreExt::Deprecation.deprecated_method_warning(:method_name)
|
50
|
+
# # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon}"
|
51
|
+
# CoreExt::Deprecation.deprecated_method_warning(:method_name, :another_method)
|
52
|
+
# # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon} (use another_method instead)"
|
53
|
+
# CoreExt::Deprecation.deprecated_method_warning(:method_name, "Optional message")
|
54
|
+
# # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon} (Optional message)"
|
55
|
+
def deprecated_method_warning(method_name, message = nil)
|
56
|
+
warning = "#{method_name} is deprecated and will be removed from #{gem_name} #{deprecation_horizon}"
|
57
|
+
case message
|
58
|
+
when Symbol then "#{warning} (use #{message} instead)"
|
59
|
+
when String then "#{warning} (#{message})"
|
60
|
+
else warning
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def deprecation_message(callstack, message = nil)
|
65
|
+
message ||= "You are using deprecated behavior which will be removed from the next major or minor release."
|
66
|
+
message += '.' unless message =~ /\.$/
|
67
|
+
"DEPRECATION WARNING: #{message} #{deprecation_caller_message(callstack)}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def deprecation_caller_message(callstack)
|
71
|
+
file, line, method = extract_callstack(callstack)
|
72
|
+
if file
|
73
|
+
if line && method
|
74
|
+
"(called from #{method} at #{file}:#{line})"
|
75
|
+
else
|
76
|
+
"(called from #{file}:#{line})"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def extract_callstack(callstack)
|
82
|
+
return _extract_callstack(callstack) if callstack.first.is_a? String
|
83
|
+
|
84
|
+
rails_gem_root = File.expand_path("../../../../..", __FILE__) + "/"
|
85
|
+
offending_line = callstack.find { |frame|
|
86
|
+
frame.absolute_path && !frame.absolute_path.start_with?(rails_gem_root)
|
87
|
+
} || callstack.first
|
88
|
+
[offending_line.path, offending_line.lineno, offending_line.label]
|
89
|
+
end
|
90
|
+
|
91
|
+
def _extract_callstack(callstack)
|
92
|
+
warn "Please pass `caller_locations` to the deprecation API" if $VERBOSE
|
93
|
+
rails_gem_root = File.expand_path("../../../../..", __FILE__) + "/"
|
94
|
+
offending_line = callstack.find { |line| !line.start_with?(rails_gem_root) } || callstack.first
|
95
|
+
if offending_line
|
96
|
+
if md = offending_line.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
|
97
|
+
md.captures
|
98
|
+
else
|
99
|
+
offending_line
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module CoreExt
|
4
|
+
# \Deprecation specifies the API used by Rails to deprecate methods, instance
|
5
|
+
# variables, objects and constants.
|
6
|
+
class Deprecation
|
7
|
+
# active_support.rb sets an autoload for CoreExt::Deprecation.
|
8
|
+
#
|
9
|
+
# If these requires were at the top of the file the constant would not be
|
10
|
+
# defined by the time their files were loaded. Since some of them reopen
|
11
|
+
# CoreExt::Deprecation its autoload would be triggered, resulting in
|
12
|
+
# a circular require warning for active_support/deprecation.rb.
|
13
|
+
#
|
14
|
+
# So, we define the constant first, and load dependencies later.
|
15
|
+
require 'core_ext/deprecation/instance_delegator'
|
16
|
+
require 'core_ext/deprecation/behaviors'
|
17
|
+
require 'core_ext/deprecation/reporting'
|
18
|
+
require 'core_ext/deprecation/method_wrappers'
|
19
|
+
require 'core_ext/deprecation/proxy_wrappers'
|
20
|
+
require 'core_ext/module/deprecation'
|
21
|
+
|
22
|
+
include Singleton
|
23
|
+
include InstanceDelegator
|
24
|
+
include Behavior
|
25
|
+
include Reporting
|
26
|
+
include MethodWrapper
|
27
|
+
|
28
|
+
# The version number in which the deprecated behavior will be removed, by default.
|
29
|
+
attr_accessor :deprecation_horizon
|
30
|
+
|
31
|
+
# It accepts two parameters on initialization. The first is a version of library
|
32
|
+
# and the second is a library name
|
33
|
+
#
|
34
|
+
# CoreExt::Deprecation.new('2.0', 'MyLibrary')
|
35
|
+
def initialize(deprecation_horizon = '5.0', gem_name = 'Rails')
|
36
|
+
self.gem_name = gem_name
|
37
|
+
self.deprecation_horizon = deprecation_horizon
|
38
|
+
# By default, warnings are not silenced and debugging is off.
|
39
|
+
self.silenced = false
|
40
|
+
self.debug = false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module Digest
|
4
|
+
module UUID
|
5
|
+
DNS_NAMESPACE = "k\xA7\xB8\x10\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
|
6
|
+
URL_NAMESPACE = "k\xA7\xB8\x11\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
|
7
|
+
OID_NAMESPACE = "k\xA7\xB8\x12\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
|
8
|
+
X500_NAMESPACE = "k\xA7\xB8\x14\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
|
9
|
+
|
10
|
+
# Generates a v5 non-random UUID (Universally Unique IDentifier).
|
11
|
+
#
|
12
|
+
# Using Digest::MD5 generates version 3 UUIDs; Digest::SHA1 generates version 5 UUIDs.
|
13
|
+
# uuid_from_hash always generates the same UUID for a given name and namespace combination.
|
14
|
+
#
|
15
|
+
# See RFC 4122 for details of UUID at: http://www.ietf.org/rfc/rfc4122.txt
|
16
|
+
def self.uuid_from_hash(hash_class, uuid_namespace, name)
|
17
|
+
if hash_class == Digest::MD5
|
18
|
+
version = 3
|
19
|
+
elsif hash_class == Digest::SHA1
|
20
|
+
version = 5
|
21
|
+
else
|
22
|
+
raise ArgumentError, "Expected Digest::SHA1 or Digest::MD5, got #{hash_class.name}."
|
23
|
+
end
|
24
|
+
|
25
|
+
hash = hash_class.new
|
26
|
+
hash.update(uuid_namespace)
|
27
|
+
hash.update(name)
|
28
|
+
|
29
|
+
ary = hash.digest.unpack('NnnnnN')
|
30
|
+
ary[2] = (ary[2] & 0x0FFF) | (version << 12)
|
31
|
+
ary[3] = (ary[3] & 0x3FFF) | 0x8000
|
32
|
+
|
33
|
+
"%08x-%04x-%04x-%04x-%04x%08x" % ary
|
34
|
+
end
|
35
|
+
|
36
|
+
# Convenience method for uuid_from_hash using Digest::MD5.
|
37
|
+
def self.uuid_v3(uuid_namespace, name)
|
38
|
+
self.uuid_from_hash(Digest::MD5, uuid_namespace, name)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Convenience method for uuid_from_hash using Digest::SHA1.
|
42
|
+
def self.uuid_v5(uuid_namespace, name)
|
43
|
+
self.uuid_from_hash(Digest::SHA1, uuid_namespace, name)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Convenience method for SecureRandom.uuid.
|
47
|
+
def self.uuid_v4
|
48
|
+
SecureRandom.uuid
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|