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.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +3 -0
  3. data/lib/core_ext/array/access.rb +76 -0
  4. data/lib/core_ext/array/conversions.rb +211 -0
  5. data/lib/core_ext/array/extract_options.rb +29 -0
  6. data/lib/core_ext/array/grouping.rb +116 -0
  7. data/lib/core_ext/array/inquiry.rb +17 -0
  8. data/lib/core_ext/array/prepend_and_append.rb +7 -0
  9. data/lib/core_ext/array/wrap.rb +46 -0
  10. data/lib/core_ext/array.rb +7 -0
  11. data/lib/core_ext/array_inquirer.rb +44 -0
  12. data/lib/core_ext/benchmark.rb +14 -0
  13. data/lib/core_ext/benchmarkable.rb +49 -0
  14. data/lib/core_ext/big_decimal/conversions.rb +14 -0
  15. data/lib/core_ext/big_decimal.rb +1 -0
  16. data/lib/core_ext/builder.rb +6 -0
  17. data/lib/core_ext/callbacks.rb +770 -0
  18. data/lib/core_ext/class/attribute.rb +128 -0
  19. data/lib/core_ext/class/attribute_accessors.rb +4 -0
  20. data/lib/core_ext/class/subclasses.rb +42 -0
  21. data/lib/core_ext/class.rb +2 -0
  22. data/lib/core_ext/concern.rb +142 -0
  23. data/lib/core_ext/configurable.rb +148 -0
  24. data/lib/core_ext/date/acts_like.rb +8 -0
  25. data/lib/core_ext/date/blank.rb +12 -0
  26. data/lib/core_ext/date/calculations.rb +143 -0
  27. data/lib/core_ext/date/conversions.rb +93 -0
  28. data/lib/core_ext/date/zones.rb +6 -0
  29. data/lib/core_ext/date.rb +5 -0
  30. data/lib/core_ext/date_and_time/calculations.rb +328 -0
  31. data/lib/core_ext/date_and_time/zones.rb +40 -0
  32. data/lib/core_ext/date_time/acts_like.rb +14 -0
  33. data/lib/core_ext/date_time/blank.rb +12 -0
  34. data/lib/core_ext/date_time/calculations.rb +177 -0
  35. data/lib/core_ext/date_time/conversions.rb +104 -0
  36. data/lib/core_ext/date_time/zones.rb +6 -0
  37. data/lib/core_ext/date_time.rb +5 -0
  38. data/lib/core_ext/deprecation/behaviors.rb +86 -0
  39. data/lib/core_ext/deprecation/instance_delegator.rb +24 -0
  40. data/lib/core_ext/deprecation/method_wrappers.rb +70 -0
  41. data/lib/core_ext/deprecation/proxy_wrappers.rb +149 -0
  42. data/lib/core_ext/deprecation/reporting.rb +105 -0
  43. data/lib/core_ext/deprecation.rb +43 -0
  44. data/lib/core_ext/digest/uuid.rb +51 -0
  45. data/lib/core_ext/duration.rb +157 -0
  46. data/lib/core_ext/enumerable.rb +106 -0
  47. data/lib/core_ext/file/atomic.rb +68 -0
  48. data/lib/core_ext/file.rb +1 -0
  49. data/lib/core_ext/hash/compact.rb +20 -0
  50. data/lib/core_ext/hash/conversions.rb +261 -0
  51. data/lib/core_ext/hash/deep_merge.rb +38 -0
  52. data/lib/core_ext/hash/except.rb +22 -0
  53. data/lib/core_ext/hash/indifferent_access.rb +23 -0
  54. data/lib/core_ext/hash/keys.rb +170 -0
  55. data/lib/core_ext/hash/reverse_merge.rb +22 -0
  56. data/lib/core_ext/hash/slice.rb +48 -0
  57. data/lib/core_ext/hash/transform_values.rb +29 -0
  58. data/lib/core_ext/hash.rb +9 -0
  59. data/lib/core_ext/hash_with_indifferent_access.rb +298 -0
  60. data/lib/core_ext/inflections.rb +70 -0
  61. data/lib/core_ext/inflector/inflections.rb +244 -0
  62. data/lib/core_ext/inflector/methods.rb +381 -0
  63. data/lib/core_ext/inflector/transliterate.rb +112 -0
  64. data/lib/core_ext/inflector.rb +7 -0
  65. data/lib/core_ext/integer/inflections.rb +29 -0
  66. data/lib/core_ext/integer/multiple.rb +10 -0
  67. data/lib/core_ext/integer/time.rb +29 -0
  68. data/lib/core_ext/integer.rb +3 -0
  69. data/lib/core_ext/json/decoding.rb +67 -0
  70. data/lib/core_ext/json/encoding.rb +127 -0
  71. data/lib/core_ext/json.rb +2 -0
  72. data/lib/core_ext/kernel/agnostics.rb +11 -0
  73. data/lib/core_ext/kernel/concern.rb +10 -0
  74. data/lib/core_ext/kernel/reporting.rb +41 -0
  75. data/lib/core_ext/kernel/singleton_class.rb +6 -0
  76. data/lib/core_ext/kernel.rb +4 -0
  77. data/lib/core_ext/load_error.rb +30 -0
  78. data/lib/core_ext/logger.rb +57 -0
  79. data/lib/core_ext/logger_silence.rb +24 -0
  80. data/lib/core_ext/marshal.rb +19 -0
  81. data/lib/core_ext/module/aliasing.rb +74 -0
  82. data/lib/core_ext/module/anonymous.rb +28 -0
  83. data/lib/core_ext/module/attr_internal.rb +36 -0
  84. data/lib/core_ext/module/attribute_accessors.rb +212 -0
  85. data/lib/core_ext/module/concerning.rb +135 -0
  86. data/lib/core_ext/module/delegation.rb +218 -0
  87. data/lib/core_ext/module/deprecation.rb +23 -0
  88. data/lib/core_ext/module/introspection.rb +62 -0
  89. data/lib/core_ext/module/method_transplanting.rb +3 -0
  90. data/lib/core_ext/module/qualified_const.rb +52 -0
  91. data/lib/core_ext/module/reachable.rb +8 -0
  92. data/lib/core_ext/module/remove_method.rb +35 -0
  93. data/lib/core_ext/module.rb +11 -0
  94. data/lib/core_ext/multibyte/chars.rb +231 -0
  95. data/lib/core_ext/multibyte/unicode.rb +388 -0
  96. data/lib/core_ext/multibyte.rb +21 -0
  97. data/lib/core_ext/name_error.rb +31 -0
  98. data/lib/core_ext/numeric/bytes.rb +64 -0
  99. data/lib/core_ext/numeric/conversions.rb +132 -0
  100. data/lib/core_ext/numeric/inquiry.rb +26 -0
  101. data/lib/core_ext/numeric/time.rb +74 -0
  102. data/lib/core_ext/numeric.rb +4 -0
  103. data/lib/core_ext/object/acts_like.rb +10 -0
  104. data/lib/core_ext/object/blank.rb +140 -0
  105. data/lib/core_ext/object/conversions.rb +4 -0
  106. data/lib/core_ext/object/deep_dup.rb +53 -0
  107. data/lib/core_ext/object/duplicable.rb +98 -0
  108. data/lib/core_ext/object/inclusion.rb +27 -0
  109. data/lib/core_ext/object/instance_variables.rb +28 -0
  110. data/lib/core_ext/object/json.rb +199 -0
  111. data/lib/core_ext/object/to_param.rb +1 -0
  112. data/lib/core_ext/object/to_query.rb +84 -0
  113. data/lib/core_ext/object/try.rb +146 -0
  114. data/lib/core_ext/object/with_options.rb +69 -0
  115. data/lib/core_ext/object.rb +14 -0
  116. data/lib/core_ext/option_merger.rb +25 -0
  117. data/lib/core_ext/ordered_hash.rb +48 -0
  118. data/lib/core_ext/ordered_options.rb +81 -0
  119. data/lib/core_ext/range/conversions.rb +34 -0
  120. data/lib/core_ext/range/each.rb +21 -0
  121. data/lib/core_ext/range/include_range.rb +23 -0
  122. data/lib/core_ext/range/overlaps.rb +8 -0
  123. data/lib/core_ext/range.rb +4 -0
  124. data/lib/core_ext/regexp.rb +5 -0
  125. data/lib/core_ext/rescuable.rb +119 -0
  126. data/lib/core_ext/securerandom.rb +23 -0
  127. data/lib/core_ext/security_utils.rb +20 -0
  128. data/lib/core_ext/string/access.rb +104 -0
  129. data/lib/core_ext/string/behavior.rb +6 -0
  130. data/lib/core_ext/string/conversions.rb +56 -0
  131. data/lib/core_ext/string/exclude.rb +11 -0
  132. data/lib/core_ext/string/filters.rb +102 -0
  133. data/lib/core_ext/string/indent.rb +43 -0
  134. data/lib/core_ext/string/inflections.rb +235 -0
  135. data/lib/core_ext/string/inquiry.rb +13 -0
  136. data/lib/core_ext/string/multibyte.rb +53 -0
  137. data/lib/core_ext/string/output_safety.rb +261 -0
  138. data/lib/core_ext/string/starts_ends_with.rb +4 -0
  139. data/lib/core_ext/string/strip.rb +23 -0
  140. data/lib/core_ext/string/zones.rb +14 -0
  141. data/lib/core_ext/string.rb +13 -0
  142. data/lib/core_ext/string_inquirer.rb +26 -0
  143. data/lib/core_ext/tagged_logging.rb +78 -0
  144. data/lib/core_ext/test_case.rb +88 -0
  145. data/lib/core_ext/testing/assertions.rb +99 -0
  146. data/lib/core_ext/testing/autorun.rb +12 -0
  147. data/lib/core_ext/testing/composite_filter.rb +54 -0
  148. data/lib/core_ext/testing/constant_lookup.rb +50 -0
  149. data/lib/core_ext/testing/declarative.rb +26 -0
  150. data/lib/core_ext/testing/deprecation.rb +36 -0
  151. data/lib/core_ext/testing/file_fixtures.rb +34 -0
  152. data/lib/core_ext/testing/isolation.rb +115 -0
  153. data/lib/core_ext/testing/method_call_assertions.rb +41 -0
  154. data/lib/core_ext/testing/setup_and_teardown.rb +50 -0
  155. data/lib/core_ext/testing/stream.rb +42 -0
  156. data/lib/core_ext/testing/tagged_logging.rb +25 -0
  157. data/lib/core_ext/testing/time_helpers.rb +134 -0
  158. data/lib/core_ext/time/acts_like.rb +8 -0
  159. data/lib/core_ext/time/calculations.rb +284 -0
  160. data/lib/core_ext/time/conversions.rb +66 -0
  161. data/lib/core_ext/time/zones.rb +95 -0
  162. data/lib/core_ext/time.rb +20 -0
  163. data/lib/core_ext/time_with_zone.rb +503 -0
  164. data/lib/core_ext/time_zone.rb +464 -0
  165. data/lib/core_ext/uri.rb +25 -0
  166. data/lib/core_ext/version.rb +3 -0
  167. data/lib/core_ext/xml_mini/jdom.rb +181 -0
  168. data/lib/core_ext/xml_mini/libxml.rb +79 -0
  169. data/lib/core_ext/xml_mini/libxmlsax.rb +85 -0
  170. data/lib/core_ext/xml_mini/nokogiri.rb +83 -0
  171. data/lib/core_ext/xml_mini/nokogirisax.rb +87 -0
  172. data/lib/core_ext/xml_mini/rexml.rb +130 -0
  173. data/lib/core_ext/xml_mini.rb +194 -0
  174. data/lib/core_ext.rb +3 -0
  175. 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,6 @@
1
+ require 'date'
2
+ require 'core_ext/date_and_time/zones'
3
+
4
+ class DateTime
5
+ include DateAndTime::Zones
6
+ end
@@ -0,0 +1,5 @@
1
+ require 'core_ext/date_time/acts_like'
2
+ require 'core_ext/date_time/blank'
3
+ require 'core_ext/date_time/calculations'
4
+ require 'core_ext/date_time/conversions'
5
+ require 'core_ext/date_time/zones'
@@ -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