core_ext 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|