facets 3.2.2 → 4.0.0

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +44 -15
  3. data/HISTORY.md +99 -0
  4. data/LICENSE.txt +1 -1
  5. data/README.md +50 -219
  6. data/lib/core/facets/array/nonuniq.rb +2 -2
  7. data/lib/core/facets/array/standard_deviation.rb +1 -1
  8. data/lib/core/facets/array/uniq_by.rb +5 -1
  9. data/lib/core/facets/array.rb +5 -1
  10. data/lib/core/facets/binding/self.rb +2 -1
  11. data/lib/core/facets/comparable/clip.rb +2 -1
  12. data/lib/core/facets/dir/recurse.rb +17 -4
  13. data/lib/core/facets/enumerable/compact_map.rb +1 -1
  14. data/lib/core/facets/enumerable/defer.rb +1 -1
  15. data/lib/core/facets/enumerable/frequency.rb +1 -1
  16. data/lib/core/facets/enumerable/hashify.rb +2 -2
  17. data/lib/core/facets/enumerable/hinge.rb +1 -1
  18. data/lib/core/facets/enumerable/map_with_index.rb +1 -1
  19. data/lib/core/facets/enumerable/mash.rb +2 -1
  20. data/lib/core/facets/enumerable/uniq_by.rb +3 -1
  21. data/lib/core/facets/essentials.rb +4 -1
  22. data/lib/core/facets/exception/error_print.rb +4 -2
  23. data/lib/core/facets/file/null.rb +2 -1
  24. data/lib/core/facets/file/read_binary.rb +2 -1
  25. data/lib/core/facets/file.rb +1 -1
  26. data/lib/core/facets/hash/fetch_nested.rb +2 -1
  27. data/lib/core/facets/hash/update_keys.rb +2 -1
  28. data/lib/core/facets/hash/update_values.rb +2 -1
  29. data/lib/core/facets/hash.rb +6 -4
  30. data/lib/core/facets/kernel/eigenclass.rb +2 -1
  31. data/lib/core/facets/kernel/extension.rb +2 -1
  32. data/lib/core/facets/kernel/instance_class.rb +2 -1
  33. data/lib/core/facets/kernel/instance_send.rb +2 -1
  34. data/lib/core/facets/kernel/like.rb +7 -2
  35. data/lib/core/facets/kernel/load_relative.rb +2 -1
  36. data/lib/core/facets/kernel/memo.rb +2 -1
  37. data/lib/core/facets/kernel/meta.rb +1 -1
  38. data/lib/core/facets/kernel/object_class.rb +2 -1
  39. data/lib/core/facets/kernel/object_send.rb +2 -1
  40. data/lib/core/facets/kernel/qua_class.rb +2 -1
  41. data/lib/core/facets/kernel/returning.rb +3 -1
  42. data/lib/core/facets/kernel/silence.rb +38 -30
  43. data/lib/core/facets/kernel/tee.rb +3 -0
  44. data/lib/core/facets/kernel/try.rb +25 -14
  45. data/lib/core/facets/kernel/with.rb +15 -9
  46. data/lib/core/facets/kernel.rb +1 -1
  47. data/lib/core/facets/module/alias_method_chain.rb +3 -1
  48. data/lib/core/facets/module/alias_module_function.rb +4 -1
  49. data/lib/core/facets/module/can.rb +2 -1
  50. data/lib/core/facets/objectspace/op_fetch.rb +2 -1
  51. data/lib/core/facets/proc/compose.rb +4 -2
  52. data/lib/core/facets/rails_bridge.rb +27 -0
  53. data/lib/core/facets/string/camelcase.rb +6 -0
  54. data/lib/core/facets/string/similarity.rb +3 -2
  55. data/lib/core/facets/struct/attributes.rb +1 -1
  56. data/lib/core/facets/time/to_time.rb +7 -2
  57. data/lib/core/facets/time/trunc.rb +2 -1
  58. data/lib/core/facets/unboundmethod/arguments.rb +1 -1
  59. data/lib/core/facets/version.rb +1 -1
  60. data/lib/rails/facets/hash/to_options.rb +14 -0
  61. data/lib/{core → rails}/facets/module/mattr.rb +30 -30
  62. data/lib/standard/facets/cloneable.rb +2 -1
  63. data/lib/standard/facets/continuation.rb +2 -1
  64. data/lib/standard/facets/enumargs.rb +14 -2
  65. data/lib/standard/facets/getoptlong.rb +2 -1
  66. data/lib/standard/facets/interval.rb +4 -3
  67. data/lib/standard/facets/load_monitor.rb +2 -1
  68. data/lib/standard/facets/pathname/null.rb +2 -1
  69. data/lib/standard/facets/random.rb +8 -4
  70. metadata +14 -12
  71. data/lib/core/facets/hash/to_options.rb +0 -1
  72. /data/lib/{core → rails}/facets/array/extract_options.rb +0 -0
  73. /data/lib/{core → rails}/facets/cattr.rb +0 -0
  74. /data/lib/{core → rails}/facets/class/cattr.rb +0 -0
  75. /data/lib/{standard → rails}/facets/date.rb +0 -0
  76. /data/lib/{core → rails}/facets/file/atomic_write.rb +0 -0
  77. /data/lib/{core → rails}/facets/hash/slice.rb +0 -0
  78. /data/lib/{core → rails}/facets/hash/stringify_keys.rb +0 -0
  79. /data/lib/{core → rails}/facets/hash/symbolize_keys.rb +0 -0
  80. /data/lib/{core → rails}/facets/module/cattr.rb +0 -0
@@ -39,12 +39,12 @@ module Enumerable
39
39
 
40
40
  def hashify(val=nil, &block)
41
41
  if val
42
- warn "The old Enumerable#hashify method has been be deprecated. Use #value_by instead."
42
+ warn "The old Enumerable#hashify method is deprecated. Use #value_by instead. It will be removed after 2027-09-30.", uplevel: 1
43
43
  value_by{ val }
44
44
  end
45
45
 
46
46
  if block
47
- warn "The old Enumerable#hashify method has been be deprecated. Use #value_by instead."
47
+ warn "The old Enumerable#hashify method is deprecated. Use #value_by instead. It will be removed after 2027-09-30.", uplevel: 1
48
48
  value_by(&block)
49
49
  end
50
50
 
@@ -10,7 +10,7 @@ module Enumerable
10
10
  # TODO: Enumerable#hinge will get a new name.
11
11
  #
12
12
  def hinge(init={}, &block)
13
- warn "Enumerable#hinge is deprecated. Use Enumerable#each_with_object instead (note: block args are reversed).", uplevel: 1
13
+ warn "Enumerable#hinge is deprecated. Use Enumerable#each_with_object instead (note: block args are reversed). It will be removed after 2027-09-30.", uplevel: 1
14
14
  each_with_object(init) { |e, obj| block.call(obj, e) }
15
15
  end
16
16
 
@@ -8,7 +8,7 @@ module Enumerable
8
8
  # CREDIT: Gavin Sinclair
9
9
 
10
10
  def map_with_index(&block)
11
- warn "Enumerable#map_with_index is deprecated. Use Enumerable#map.with_index instead.", uplevel: 1
11
+ warn "Enumerable#map_with_index is deprecated. Use Enumerable#map.with_index instead. It will be removed after 2027-09-30.", uplevel: 1
12
12
  map.with_index(&block)
13
13
  end
14
14
 
@@ -3,8 +3,9 @@ require 'facets/enumerable/graph'
3
3
  module Enumerable
4
4
 
5
5
  # @deprecated Use Enumerable#graph instead.
6
+ # Scheduled for removal after 2027-09-30.
6
7
  def mash(&yld)
7
- warn "Enumerable#mash is deprecated. Use Enumerable#graph instead.", uplevel: 1
8
+ warn "Enumerable#mash is deprecated. Use Enumerable#graph instead. It will be removed after 2027-09-30.", uplevel: 1
8
9
  graph(&yld)
9
10
  end
10
11
 
@@ -1,8 +1,10 @@
1
1
  module Enumerable
2
2
 
3
3
  # @deprecated Use Enumerable#uniq with a block instead (Ruby 1.9.2+).
4
+ # Scheduled for removal after 2027-09-30.
4
5
  def uniq_by(&block)
5
- warn "Enumerable#uniq_by is deprecated. Use Enumerable#uniq(&block) instead.", uplevel: 1
6
+ warn "Enumerable#uniq_by is deprecated. Use Enumerable#uniq(&block) instead. " \
7
+ "It will be removed after 2027-09-30.", uplevel: 1
6
8
  uniq(&block)
7
9
  end
8
10
 
@@ -47,7 +47,6 @@ require_relative 'hash/delete_values'
47
47
  require_relative 'hash/except'
48
48
  require_relative 'hash/rekey'
49
49
  require_relative 'hash/revalue'
50
- require_relative 'hash/slice'
51
50
 
52
51
  ### Proc
53
52
  #require_relative 'proc/wrap'
@@ -63,3 +62,7 @@ require_relative 'string/trim'
63
62
  require_relative 'string/unindent'
64
63
  #require_realtive 'string/word_wrap'
65
64
 
65
+
66
+ # Rails-compatible methods from lib/rails; see facets/rails_bridge.
67
+ require_relative 'rails_bridge'
68
+ Facets.rails_bridge(Hash, 'facets/hash/slice', :slice!)
@@ -1,14 +1,16 @@
1
1
  class Exception
2
2
 
3
3
  # @deprecated Use Exception#full_message instead (built-in since Ruby 2.5).
4
+ # Scheduled for removal after 2027-09-30.
4
5
  def self.error_print(e)
5
- warn "Exception.error_print is deprecated. Use Exception#full_message instead.", uplevel: 1
6
+ warn "Exception.error_print is deprecated. Use Exception#full_message instead. It will be removed after 2027-09-30.", uplevel: 1
6
7
  e.full_message
7
8
  end
8
9
 
9
10
  # @deprecated Use Exception#full_message instead (built-in since Ruby 2.5).
11
+ # Scheduled for removal after 2027-09-30.
10
12
  def error_print
11
- warn "Exception#error_print is deprecated. Use Exception#full_message instead.", uplevel: 1
13
+ warn "Exception#error_print is deprecated. Use Exception#full_message instead. It will be removed after 2027-09-30.", uplevel: 1
12
14
  full_message
13
15
  end
14
16
 
@@ -1,8 +1,9 @@
1
1
  class File
2
2
 
3
3
  # @deprecated Use File::NULL constant instead (built-in since Ruby 1.9.3).
4
+ # Scheduled for removal after 2027-09-30.
4
5
  def self.null
5
- warn "File.null is deprecated. Use File::NULL instead.", uplevel: 1
6
+ warn "File.null is deprecated. Use File::NULL instead. It will be removed after 2027-09-30.", uplevel: 1
6
7
  File::NULL
7
8
  end
8
9
 
@@ -1,8 +1,9 @@
1
1
  class File
2
2
 
3
3
  # @deprecated Use File.binread instead (built-in since Ruby 1.9.3).
4
+ # Scheduled for removal after 2027-09-30.
4
5
  def self.read_binary(fname)
5
- warn "File.read_binary is deprecated. Use File.binread instead.", uplevel: 1
6
+ warn "File.read_binary is deprecated. Use File.binread instead. It will be removed after 2027-09-30.", uplevel: 1
6
7
  binread(fname)
7
8
  end
8
9
 
@@ -1,5 +1,5 @@
1
1
  require_relative 'file/append.rb'
2
- #require_relative 'file/atomic_write.rb' # uncommon
2
+ #require 'facets/file/atomic_write' # lib/rails, uncommon
3
3
  require_relative 'file/common_path.rb'
4
4
  require_relative 'file/create.rb'
5
5
  require_relative 'file/ext.rb'
@@ -1,6 +1,7 @@
1
1
  class Hash
2
2
 
3
3
  # @deprecated Use Hash#dig instead (built-in since Ruby 2.3).
4
+ # Scheduled for removal after 2027-09-30.
4
5
  #
5
6
  # Similar to Hash#dig but supports a block for missing keys,
6
7
  # like Hash#fetch does. Ruby's #dig does not support a block.
@@ -8,7 +9,7 @@ class Hash
8
9
  # TODO: Consider proposing block support for Hash#dig to Ruby core.
9
10
  #
10
11
  def fetch_nested(*keys, &block)
11
- warn "Hash#fetch_nested is deprecated. Use Hash#dig instead.", uplevel: 1
12
+ warn "Hash#fetch_nested is deprecated. Use Hash#dig instead. It will be removed after 2027-09-30.", uplevel: 1
12
13
  begin
13
14
  keys.reduce(self) { |accum, k| accum.fetch(k) }
14
15
  rescue KeyError
@@ -1,9 +1,10 @@
1
1
  class Hash
2
2
 
3
3
  # @deprecated Use Hash#transform_keys! (Ruby 2.5+) or Hash#rekey! instead.
4
+ # Scheduled for removal after 2027-09-30.
4
5
  #
5
6
  def update_keys(&block)
6
- warn "Hash#update_keys is deprecated. Use Hash#transform_keys! or Hash#rekey! instead.", uplevel: 1
7
+ warn "Hash#update_keys is deprecated. Use Hash#transform_keys! or Hash#rekey! instead. It will be removed after 2027-09-30.", uplevel: 1
7
8
  if block_given?
8
9
  transform_keys!(&block)
9
10
  else
@@ -1,9 +1,10 @@
1
1
  class Hash
2
2
 
3
3
  # @deprecated Use Hash#transform_values! (Ruby 2.4+) or Hash#revalue! instead.
4
+ # Scheduled for removal after 2027-09-30.
4
5
  #
5
6
  def update_values(&block)
6
- warn "Hash#update_values is deprecated. Use Hash#transform_values! or Hash#revalue! instead.", uplevel: 1
7
+ warn "Hash#update_values is deprecated. Use Hash#transform_values! or Hash#revalue! instead. It will be removed after 2027-09-30.", uplevel: 1
7
8
  if block_given?
8
9
  transform_values!(&block)
9
10
  else
@@ -33,13 +33,9 @@ require_relative 'hash/recursively.rb'
33
33
  require_relative 'hash/rekey.rb'
34
34
  require_relative 'hash/replace_each.rb'
35
35
  require_relative 'hash/reverse_merge.rb'
36
- require_relative 'hash/slice.rb'
37
- require_relative 'hash/stringify_keys.rb'
38
36
  require_relative 'hash/subset.rb'
39
37
  require_relative 'hash/swap.rb'
40
- require_relative 'hash/symbolize_keys.rb'
41
38
  require_relative 'hash/to_mod.rb'
42
- require_relative 'hash/to_options.rb'
43
39
  require_relative 'hash/setter.rb'
44
40
  require_relative 'hash/to_struct.rb'
45
41
  require_relative 'hash/traverse.rb'
@@ -51,3 +47,9 @@ require_relative 'hash/update_values.rb'
51
47
  require_relative 'hash/weave.rb'
52
48
  require_relative 'hash/zip.rb'
53
49
 
50
+
51
+ # Rails-compatible methods from lib/rails; see facets/rails_bridge.
52
+ require_relative 'rails_bridge.rb'
53
+ Facets.rails_bridge(Hash, 'facets/hash/slice', :slice!)
54
+ Facets.rails_bridge(Hash, 'facets/hash/symbolize_keys', :symbolize_keys, :symbolize_keys!, :stringify_keys, :stringify_keys!)
55
+ Facets.rails_bridge(Hash, 'facets/hash/to_options', :to_options, :to_options!)
@@ -10,6 +10,7 @@ module Kernel
10
10
  #
11
11
  # @deprecated Use singleton_class or meta_class instead.
12
12
  # Kept in tribute to WhyTheLuckyStiff who coined the term.
13
+ # Scheduled for removal after 2027-09-30.
13
14
  #
14
15
  # CREDIT: WhyTheLuckyStiff
15
16
  #
@@ -17,7 +18,7 @@ module Kernel
17
18
  # require 'facets/kernel/eigenclass'
18
19
  #
19
20
  def eigenclass
20
- warn "Kernel#eigenclass is deprecated. Use singleton_class or meta_class instead.", uplevel: 1
21
+ warn "Kernel#eigenclass is deprecated. Use singleton_class or meta_class instead. It will be removed after 2027-09-30.", uplevel: 1
21
22
  singleton_class
22
23
  end
23
24
 
@@ -1,8 +1,9 @@
1
1
  module Kernel
2
2
 
3
3
  # @deprecated Use singleton_class or meta_class instead.
4
+ # Scheduled for removal after 2027-09-30.
4
5
  def extension
5
- warn "Kernel#extension is deprecated. Use singleton_class or meta_class instead.", uplevel: 1
6
+ warn "Kernel#extension is deprecated. Use singleton_class or meta_class instead. It will be removed after 2027-09-30.", uplevel: 1
6
7
  singleton_class
7
8
  end
8
9
 
@@ -1,8 +1,9 @@
1
1
  module Kernel
2
2
 
3
3
  # @deprecated Use singleton_class or meta_class instead.
4
+ # Scheduled for removal after 2027-09-30.
4
5
  def instance_class(&block)
5
- warn "Kernel#instance_class is deprecated. Use singleton_class or meta_class instead.", uplevel: 1
6
+ warn "Kernel#instance_class is deprecated. Use singleton_class or meta_class instead. It will be removed after 2027-09-30.", uplevel: 1
6
7
  singleton_class.module_eval(&block) if block
7
8
  singleton_class
8
9
  end
@@ -1,8 +1,9 @@
1
1
  module Kernel
2
2
 
3
3
  # @deprecated Use __send__ instead.
4
+ # Scheduled for removal after 2027-09-30.
4
5
  def instance_send(name, *args, &blk)
5
- warn "Kernel#instance_send is deprecated. Use __send__ instead.", uplevel: 1
6
+ warn "Kernel#instance_send is deprecated. Use __send__ instead. It will be removed after 2027-09-30.", uplevel: 1
6
7
  __send__(name, *args, &blk)
7
8
  end
8
9
 
@@ -12,8 +12,13 @@ module Kernel
12
12
  equal?(x) || eql?(x) || self == x || self === x
13
13
  end
14
14
 
15
- # @deprecated
16
- alias :equate? :like?
15
+ # @deprecated Use #like? instead.
16
+ # Scheduled for removal after 2027-09-30.
17
+ def equate?(x)
18
+ warn "Kernel#equate? is deprecated. Use Kernel#like? instead. " \
19
+ "It will be removed after 2027-09-30.", uplevel: 1
20
+ like?(x)
21
+ end
17
22
 
18
23
  end
19
24
 
@@ -2,8 +2,9 @@ module Kernel
2
2
 
3
3
  # @deprecated Use require_relative for requires; for load, use
4
4
  # an absolute path via File.expand_path.
5
+ # Scheduled for removal after 2027-09-30.
5
6
  def load_relative(relative_feature, safe=nil)
6
- warn "Kernel#load_relative is deprecated.", uplevel: 1
7
+ warn "Kernel#load_relative is deprecated. It will be removed after 2027-09-30.", uplevel: 1
7
8
  loc = caller_locations(1, 1).first
8
9
  file = loc.absolute_path || loc.path
9
10
  absolute = File.expand_path(relative_feature, File.dirname(file))
@@ -2,12 +2,13 @@ module Kernel
2
2
 
3
3
  # @deprecated Use Module#memoize instead, which provides proper
4
4
  # per-object memoization without a global variable.
5
+ # Scheduled for removal after 2027-09-30.
5
6
  #
6
7
  # @uncommon
7
8
  # require 'facets/kernel/memo'
8
9
  #
9
10
  def memo(*args, &block)
10
- warn "Kernel#memo is deprecated. Use Module#memoize instead.", uplevel: 1
11
+ warn "Kernel#memo is deprecated. Use Module#memoize instead. It will be removed after 2027-09-30.", uplevel: 1
11
12
  $MEMO ||= {}
12
13
  if args.empty?
13
14
  args = block.binding.eval('[self, __method__]')
@@ -28,7 +28,7 @@ module Kernel
28
28
  end
29
29
 
30
30
  def eigen
31
- warn "The `eigen' method is deprecated. Please use `meta' instead."
31
+ warn "The `eigen' method is deprecated. Please use `meta' instead. It will be removed after 2027-09-30.", uplevel: 1
32
32
  meta
33
33
  end
34
34
 
@@ -1,8 +1,9 @@
1
1
  module Kernel
2
2
 
3
3
  # @deprecated Use __class__ instead.
4
+ # Scheduled for removal after 2027-09-30.
4
5
  def object_class
5
- warn "Kernel#object_class is deprecated. Use __class__ instead.", uplevel: 1
6
+ warn "Kernel#object_class is deprecated. Use __class__ instead. It will be removed after 2027-09-30.", uplevel: 1
6
7
  self.class
7
8
  end
8
9
 
@@ -1,8 +1,9 @@
1
1
  module Kernel
2
2
 
3
3
  # @deprecated Use public_send instead (built-in since Ruby 1.9.2).
4
+ # Scheduled for removal after 2027-09-30.
4
5
  def object_send(name, *args, &blk)
5
- warn "Kernel#object_send is deprecated. Use public_send instead.", uplevel: 1
6
+ warn "Kernel#object_send is deprecated. Use public_send instead. It will be removed after 2027-09-30.", uplevel: 1
6
7
  public_send(name, *args, &blk)
7
8
  end
8
9
 
@@ -1,8 +1,9 @@
1
1
  module Kernel
2
2
 
3
3
  # @deprecated Use singleton_class or meta_class instead.
4
+ # Scheduled for removal after 2027-09-30.
4
5
  def qua_class(&block)
5
- warn "Kernel#qua_class is deprecated. Use singleton_class or meta_class instead.", uplevel: 1
6
+ warn "Kernel#qua_class is deprecated. Use singleton_class or meta_class instead. It will be removed after 2027-09-30.", uplevel: 1
6
7
  if block_given?
7
8
  singleton_class.class_eval(&block)
8
9
  else
@@ -1,9 +1,11 @@
1
1
  module Kernel
2
2
 
3
3
  # @deprecated Use Kernel#tap instead (built-in since Ruby 1.9).
4
+ # Scheduled for removal after 2027-09-30.
4
5
  #
5
6
  def returning(obj=self)
6
- warn "Kernel#returning is deprecated. Use Kernel#tap instead.", uplevel: 1
7
+ warn "Kernel#returning is deprecated. Use Kernel#tap instead. " \
8
+ "It will be removed after 2027-09-30.", uplevel: 1
7
9
  yield obj
8
10
  obj
9
11
  end
@@ -9,31 +9,44 @@ module Kernel
9
9
  # Supported +streams+ are +stderr+, +stdout+, +verbose+, +debug+,
10
10
  # and +warnings+, which is the same as +verbose+. You can also
11
11
  # use the actual streams, STDERR and STDOUT.
12
+ #
13
+ # silence(:verbose) do
14
+ # warn "won't see me either"
15
+ # end
16
+ #
17
+ # +verbose+ sets $VERBOSE to nil and +debug+ sets $DEBUG to false
18
+ # for the duration of the block.
19
+ #
20
+ # Silencing a stream works by reopening it on the null device, so it
21
+ # affects the whole process, not just the current thread.
12
22
  def silence(*streams) #:yield:
13
- streams = streams.map do |stream|
14
- case stream
15
- when :stderr
16
- STDERR
17
- when :stdout
18
- STDOUT
19
- else
20
- stream
21
- end
23
+ verbose, debug = $VERBOSE, $DEBUG
24
+ $VERBOSE = nil if (streams & [:verbose, :warnings]).any?
25
+ $DEBUG = false if streams.include?(:debug)
26
+
27
+ streams = (streams - [:verbose, :warnings, :debug]).map do |stream|
28
+ {stderr: STDERR, stdout: STDOUT}.fetch(stream, stream)
22
29
  end
23
30
 
24
- if streams.empty?
25
- yield
26
- else
27
- silence_stream(*streams){ yield }
31
+ on_hold = streams.collect{ |stream| stream.dup }
32
+ streams.each do |stream|
33
+ stream.reopen(File::NULL)
34
+ stream.sync = true
28
35
  end
36
+ yield
37
+ ensure
38
+ streams.each_with_index do |stream, i|
39
+ stream.reopen(on_hold[i])
40
+ end if on_hold
41
+ $VERBOSE, $DEBUG = verbose, debug
29
42
  end
30
43
 
31
- # Just like silence_stream, but will default to
44
+ # Just like #silence, but will default to
32
45
  # STDOUT, STDERR if no streams are given.
33
46
 
34
47
  def silently(*streams) #:yeild:
35
48
  streams = [STDOUT, STDERR] if streams.empty?
36
- silence_stream(*streams){ yield }
49
+ silence(*streams){ yield }
37
50
  end
38
51
 
39
52
  # Silences any stream for the duration of the block...
@@ -45,29 +58,24 @@ module Kernel
45
58
  # puts 'But this will'
46
59
  #
47
60
  # CREDIT: David Heinemeier Hansson
61
+ #
62
+ # @deprecated Use #silence instead, which takes the same arguments.
63
+ # Scheduled for removal after 2027-09-30.
48
64
 
49
65
  def silence_stream(*streams) #:yeild:
50
- on_hold = streams.collect{ |stream| stream.dup }
51
- streams.each do |stream|
52
- stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
53
- stream.sync = true
54
- end
55
- yield
56
- ensure
57
- streams.each_with_index do |stream, i|
58
- stream.reopen(on_hold[i])
59
- end
66
+ warn "Kernel#silence_stream is deprecated. Use Kernel#silence instead. " \
67
+ "It will be removed after 2027-09-30.", uplevel: 1
68
+ silence(*streams){ yield }
60
69
  end
61
70
 
62
- # Equivalent to `silence_stream(STDERR)`.
71
+ # Equivalent to `silence(STDERR)`.
63
72
  def silence_stderr #:yeild:
64
- silence_stream(STDERR) { yield }
73
+ silence(STDERR) { yield }
65
74
  end
66
75
 
67
- # Equivalent to `silence_stream(STDOUT)`.
76
+ # Equivalent to `silence(STDOUT)`.
68
77
  def silence_stdout #:yeild:
69
- silence_stream(STDOUT) { yield }
78
+ silence(STDOUT) { yield }
70
79
  end
71
80
 
72
81
  end
73
-
@@ -1,2 +1,5 @@
1
1
  # @deprecated Use Kernel#functor instead.
2
+ # Scheduled for removal after 2027-09-30.
3
+ warn "facets/kernel/tee is deprecated. Use facets/kernel/functor instead. " \
4
+ "It will be removed after 2027-09-30.", uplevel: 1
2
5
  require 'facets/kernel/functor'
@@ -3,21 +3,26 @@ require 'facets/functor'
3
3
  module Kernel
4
4
 
5
5
  # Invokes the method identified by the symbol +method+, passing it any
6
- # arguments and/or the block specified.
7
- #
8
- # Unlike regular send, a +NoMethodError+ exception will *not* be raised
9
- # if the receiving object is +nil+ (see NilClass#try below).
10
- #
11
- # Compatible with ActiveSupport's #try, plus an additional Functor
12
- # form when called with no arguments and no block.
6
+ # arguments and/or the block specified. If the receiver is +nil+, it
7
+ # returns +nil+ instead (see NilClass#try below). Otherwise it behaves
8
+ # exactly like a normal call (or &.): a method the receiver doesn't have,
9
+ # or a private one, raises NoMethodError.
13
10
  #
14
11
  # @example.try(:name) #=> "bob"
15
- # @example.try { |o| o.name } #=> "bob" (ActiveSupport block form)
16
- # @example.try.name #=> "bob" (Facets Functor form)
12
+ # @example.try { |o| o.name } #=> "bob"
13
+ # @example.try.name #=> "bob" (Functor form)
14
+ # nil.try.name #=> nil
15
+ #
16
+ # NOTE: THIS IS NOT ACTIVESUPPORT'S #try. SINCE RAILS 4.0, ACTIVESUPPORT'S
17
+ # #try RETURNS NIL FOR A METHOD THE RECEIVER DOESN'T HAVE, SO A TYPO LIKE
18
+ # user.try(:nmae) QUIETLY BECOMES NIL AND HIDES THE BUG. FACETS KEEPS #try
19
+ # STRICT AND PUTS THE LENIENT BEHAVIOR IN #try!, WHERE IT BELONGS: IN RUBY,
20
+ # THE BANG MARKS THE MORE DANGEROUS VERSION OF A METHOD, AND SWALLOWING A
21
+ # MISSING METHOD IS THE DANGEROUS ONE. RAILS HAS THE TWO BACKWARD.
17
22
  #
18
23
  def try(method=nil, *args, &block)
19
24
  if method
20
- __send__(method, *args, &block)
25
+ public_send(method, *args, &block)
21
26
  elsif block_given?
22
27
  yield self
23
28
  else
@@ -25,12 +30,19 @@ module Kernel
25
30
  end
26
31
  end
27
32
 
28
- # Like #try, but raises NoMethodError if the method doesn't exist
29
- # (unless receiver is nil). Compatible with ActiveSupport's #try!.
33
+ # Like #try, but also returns +nil+ if the receiver doesn't respond to
34
+ # +method+ (or it is private), instead of raising NoMethodError.
35
+ #
36
+ # @example.try!(:name) #=> "bob"
37
+ # @example.try!(:nmae) #=> nil
38
+ #
39
+ # NOTE: THIS IS THE OPPOSITE OF ACTIVESUPPORT'S #try!, WHICH RAISES. THE
40
+ # BANG IS HERE BECAUSE QUIETLY IGNORING A MISSING METHOD IS THE DANGEROUS
41
+ # BEHAVIOR; SEE #try ABOVE.
30
42
  #
31
43
  def try!(method=nil, *args, &block)
32
44
  if method
33
- public_send(method, *args, &block)
45
+ public_send(method, *args, &block) if respond_to?(method)
34
46
  elsif block_given?
35
47
  yield self
36
48
  else
@@ -40,7 +52,6 @@ module Kernel
40
52
 
41
53
  end
42
54
 
43
-
44
55
  class NilClass
45
56
 
46
57
  # See Kernel#try.
@@ -1,20 +1,26 @@
1
1
  module Kernel
2
2
 
3
- # Like returning but exectues the block
4
- # via instance_eval.
3
+ # Evaluate the block with +obj+ as self and return the block's value.
4
+ # It is simply a more readable spelling of #instance_eval.
5
5
  #
6
- # def foo
7
- # with values = [] do
8
- # self << 'bar'
9
- # self << 'baz'
10
- # end
6
+ # values = []
7
+ # with values do
8
+ # self << 'bar'
9
+ # self << 'baz'
11
10
  # end
11
+ # values # => ['bar', 'baz']
12
12
  #
13
- # foo # => ['bar', 'baz']
13
+ # @deprecated Use obj.instance_eval { ... } instead. Rails 7.1 defines an
14
+ # unrelated Object#with that temporarily sets attributes, and this one
15
+ # silently replaces it. Scheduled for removal after 2027-09-30.
16
+ #
17
+ # @uncommon
18
+ # require 'facets/kernel/with'
14
19
  #
15
20
  def with(obj=self, &block)
21
+ warn "Kernel#with is deprecated. Use obj.instance_eval { ... } instead. " \
22
+ "It will be removed after 2027-09-30.", uplevel: 1
16
23
  obj.instance_eval(&block)
17
24
  end
18
25
 
19
26
  end
20
-
@@ -63,7 +63,7 @@ require_relative 'kernel/temporarily.rb'
63
63
  require_relative 'kernel/true.rb'
64
64
  require_relative 'kernel/try.rb'
65
65
  require_relative 'kernel/val.rb'
66
- require_relative 'kernel/with.rb'
66
+ #require_relative 'kernel/with.rb' # uncommon
67
67
  require_relative 'kernel/writers.rb'
68
68
  #require_relative 'kernel/y.rb' # uncommon
69
69
  require_relative 'kernel/yes.rb'
@@ -1,12 +1,14 @@
1
1
  class Module
2
2
 
3
3
  # @deprecated Use Module#prepend instead (built-in since Ruby 2.0).
4
+ # Scheduled for removal after 2027-09-30.
4
5
  #
5
6
  # The alias_method_chain pattern has been superseded by Module#prepend,
6
7
  # which provides a cleaner way to wrap methods.
7
8
  #
8
9
  def alias_method_chain(target, feature)
9
- warn "Module#alias_method_chain is deprecated. Use Module#prepend instead.", uplevel: 1
10
+ warn "Module#alias_method_chain is deprecated. Use Module#prepend instead. " \
11
+ "It will be removed after 2027-09-30.", uplevel: 1
10
12
  aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
11
13
  yield(aliased_target, punctuation) if block_given?
12
14
 
@@ -23,7 +23,10 @@ class Module
23
23
  #
24
24
  def alias_module_function(new, old)
25
25
  alias_method(new, old)
26
- module_function(new)
26
+ return module_function(new) unless singleton_class.method_defined?(old)
27
+ # Alias the singleton method directly. On JRuby, a singleton method made
28
+ # by #module_function turns private when it is itself aliased later.
29
+ singleton_class.send(:alias_method, new, old)
27
30
  end
28
31
 
29
32
  end
@@ -1,8 +1,9 @@
1
1
  class Module
2
2
 
3
3
  # @deprecated Use Module#extend instead.
4
+ # Scheduled for removal after 2027-09-30.
4
5
  def can(*mods)
5
- warn "Module#can is deprecated. Use Module#extend instead.", uplevel: 1
6
+ warn "Module#can is deprecated. Use Module#extend instead. It will be removed after 2027-09-30.", uplevel: 1
6
7
  extend(*mods)
7
8
  end
8
9
 
@@ -1,3 +1,4 @@
1
1
  class << ObjectSpace
2
- alias_method :[], :_id2ref
2
+ # Ruby 4.1 removed ObjectSpace._id2ref, so there is nothing to alias there.
3
+ alias_method :[], :_id2ref if method_defined?(:_id2ref)
3
4
  end
@@ -1,14 +1,16 @@
1
1
  class Proc
2
2
 
3
3
  # @deprecated Use Proc#>> or Proc#<< instead (built-in since Ruby 2.6).
4
+ # Scheduled for removal after 2027-09-30.
4
5
  def compose(g)
5
- warn "Proc#compose is deprecated. Use Proc#<< instead (right-to-left composition).", uplevel: 1
6
+ warn "Proc#compose is deprecated. Use Proc#<< instead (right-to-left composition). It will be removed after 2027-09-30.", uplevel: 1
6
7
  self << g
7
8
  end
8
9
 
9
10
  # @deprecated Use Proc#>> or Proc#<< for composition (built-in since Ruby 2.6).
11
+ # Scheduled for removal after 2027-09-30.
10
12
  def *(x)
11
- warn "Proc#* is deprecated. Use Proc#<< for composition (right-to-left).", uplevel: 1
13
+ warn "Proc#* is deprecated. Use Proc#<< for composition (right-to-left). It will be removed after 2027-09-30.", uplevel: 1
12
14
  if Integer === x
13
15
  c = []
14
16
  x.times{|i| c << call(i)}