deprecate_soft 1.1.0 โ†’ 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b9799b61944284b4206b894196574252ccbcf7e550b127d7f45dfe524a943a5
4
- data.tar.gz: 1474ec114cd60edcd85a7c975efb69121654f19ea0659ca4b13f577ca9370520
3
+ metadata.gz: 71f04af257e3e75e4c00ab45333c7e800a440f29f7677361bb6057d300eb6553
4
+ data.tar.gz: 62e5028bb462ac1cfec9d91a462baaaca81ba0f9211392c387cbff926aaf5a06
5
5
  SHA512:
6
- metadata.gz: fd8cd841c2c67e77b3b7aed65e4fe0405f19d296c727c051346ba139662c395c3542e2848ee5d9c09146653bd6bdc5fdfa3756fcb57f95412d29a355d729841f
7
- data.tar.gz: 8662fc4dec07bfc90b334d3aa5127b5c9042af70168d3013e03045f35d19beec572ffb5f16dfc386e169e48e590c83c600c9c7d823b724a5ee48615a7045f5b7
6
+ metadata.gz: 93a50dfb57c19b479a103192f8e86f2bd3abed9bf1400db03e6ad4d1f3aba1eddd67eff0226a101b8c3d3813d69839e7ac505a8feb38252a521d1c9038b9a3aa
7
+ data.tar.gz: 7ffb74d9dfdf8d2051d20a7fa1c8efca196248bd2c8358e8077534f7900bea851ef30868c6a5cb3ed267b3b49ed2ebecb9fea166394b0280c5ebe284036b00de
data/.rubocop.yml CHANGED
@@ -1,11 +1,14 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 2.5 # purposely an old Ruby version
3
3
 
4
- Style/StringLiterals:
5
- EnforcedStyle: single_quotes
4
+ Layout/LineLength:
5
+ Max: 180
6
6
 
7
- Style/StringLiteralsInInterpolation:
8
- EnforcedStyle: single_quotes
7
+ Lint/ConstantDefinitionInBlock:
8
+ Enabled: false
9
+
10
+ Lint/UnusedBlockArgument:
11
+ Enabled: false
9
12
 
10
13
  Metrics/AbcSize:
11
14
  Enabled: false
@@ -22,9 +25,6 @@ Metrics/CyclomaticComplexity:
22
25
  Metrics/MethodLength:
23
26
  Enabled: false
24
27
 
25
- Lint/UnusedBlockArgument:
26
- Enabled: false
27
-
28
28
  Naming/MethodParameterName:
29
29
  Enabled: false
30
30
 
@@ -34,8 +34,20 @@ Style/SafeNavigation:
34
34
  Style/Documentation:
35
35
  Enabled: false
36
36
 
37
+ Style/IfUnlessModifier:
38
+ Enabled: false
39
+
37
40
  Style/RedundantSelf:
38
41
  Enabled: false
39
42
 
40
43
  Style/SingleLineMethods:
41
44
  Enabled: false
45
+
46
+ Style/StringLiterals:
47
+ EnforcedStyle: single_quotes
48
+
49
+ Style/StringLiteralsInInterpolation:
50
+ EnforcedStyle: single_quotes
51
+
52
+ Style/TrivialAccessors:
53
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,17 +1,38 @@
1
- ## DepracateSoft Change Log
1
+
2
+ ## ๐Ÿ“ DepracateSoft Change Log
3
+
4
+ ## [1.2.0] - 2025-04-05
5
+ ### โœจ Added Support
6
+ - improving handling of class methods
7
+ - added deprecate_class_soft for class methods. Fixed [Issue #1](https://github.com/tilo/deprecate_soft/issues/1)
8
+ - support to define the method after the declaration
9
+ ### ๐Ÿ› ๏ธ Internals
10
+ - stream-lined include DeprecateSoft
11
+ ### ๐Ÿ“ Deliberate Limitations
12
+ - Class methods need to be defined via `def self.method`, not in `class << self` blocks.
13
+ Simply move the to-be-deprecated method out of the `self << class` and declare it via `self.method_name`.
14
+ This also makes the to be deleted method stand out more.
2
15
 
3
16
  ## [1.1.0] - 2025-03-29
4
- - simplify initialization
5
- - added tests for corner cases:
6
- - deprecate_soft called before method definition
7
- - deprecate_soft called twice
8
- - deprecate_soft for private methods
9
- - before_hook or after_hook raise
10
- - prevent double-wrapping methods
11
- - ensure that methods run undisturbed, even if the before_hook or after_hook raise an exception
17
+ ### โœจ Added Support
18
+ - Errors in `before_hook` / `after_hook` do not prevent method execution.
19
+ - `Kernel.warn` is used to log hook exceptions instead of raising.
20
+ - No impact if `deprecate_soft` is called twice for the same method
21
+ ### ๐Ÿงช Test Coverage
22
+ - deprecate_soft called before method definition
23
+ - deprecate_soft called twice
24
+ - deprecate_soft for private instance and class methods
25
+ - errors in `before_hook` or `after_hook`
26
+ ### ๐Ÿ› ๏ธ Internals
27
+ - simplified initialization
12
28
 
13
29
  ## [1.0.0] - 2025-03-24
14
- - Initial release
30
+ - Initial release of `deprecate_soft`.
31
+ - Support for soft-deprecating instance and class methods, as well as private methods.
32
+ - Added `before_hook` and `after_hook` for custom instrumentation or logging.
33
+ - Safe wrapping of methods with optional message.
34
+ - Skips wrapping if method is not yet defined.
35
+ - Supports defining deprecations inline with method definitions.
15
36
 
16
37
  ## [0.0.1] - 2025-03-22
17
38
  - pre-release
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
 
2
2
  # DeprecateSoft
3
3
 
4
+ [![Gem Version](https://badge.fury.io/rb/deprecate_soft.svg)](https://badge.fury.io/rb/deprecate_soft)
5
+ [![CI](https://github.com/tilo/deprecate_soft/actions/workflows/main.yml/badge.svg)](https://github.com/tilo/deprecate_soft/actions/workflows/main.yml)
6
+ [![codecov](https://codecov.io/gh/tilo/deprecate_soft/branch/main/graph/badge.svg)](https://codecov.io/gh/tilo/deprecate_soft)
7
+
4
8
  DeprecateSoft is a lightweight and flexible Ruby gem designed to help you gracefully and safely delete methods.
5
9
 
6
10
  It was inspired by the need to track deprecated method usage in large codebases before safely removing old code โ€” with zero disruption and flexible metrics support.
@@ -28,6 +32,7 @@ This mechanism has been **proven in large-scale production systems** to safely c
28
32
  ## ๐Ÿ“– Blog Posts
29
33
  - [Safely Delete Old Ruby Code with deprecate_soft](https://medium.com/@tilo-sloboda/safely-delete-old-code-with-deprecate-soft-89e819b41d52)
30
34
  ---
35
+ ## ๐Ÿ“ [Change Log](https://github.com/tilo/deprecate_soft/blob/main/CHANGELOG.md)
31
36
 
32
37
  ## ๐Ÿš€ Installation
33
38
 
@@ -53,6 +58,8 @@ Declare `deprecate_soft` **after** the method definition.
53
58
 
54
59
  ### For Instance Methods:
55
60
 
61
+ use `deprecate_soft`
62
+
56
63
  ```ruby
57
64
  class MyService
58
65
  include DeprecateSoft
@@ -69,15 +76,17 @@ MyService.new.deprecated_method(1, 2) # will exercise the tracking hooks
69
76
 
70
77
  ### For Class Methods:
71
78
 
79
+ use `deprecate_class_soft`
80
+
72
81
  ```ruby
73
82
  class MyService
74
- extend DeprecateSoft
83
+ include DeprecateSoft
75
84
 
76
85
  def self.deprecated_method(a, b)
77
86
  puts "doing something with #{a} and #{b}"
78
87
  end
79
88
 
80
- deprecate_soft :deprecated_method, "will be removed"
89
+ deprecate_class_soft :deprecated_method, "will be removed" # โš ๏ธ
81
90
  end
82
91
 
83
92
  MyService.deprecated_method(1, 2) # will exercise the tracking hooks
@@ -325,6 +334,9 @@ end
325
334
  - Make sure hooks do not raise or interfere with production behavior.
326
335
  - Only use non-blocking, low-latency methods for tracking!
327
336
  - Currently assumes Ruby 2.5+ (for `&.` and keyword args support).
337
+ - Class methods need to be defined via `def self.method`, not in `class << self` blocks.
338
+ Simply move the to-be-deprecated method out of the `self << class` and declare it via `self.method_name`.
339
+ This also makes the to be deleted method stand out more.
328
340
 
329
341
  ---
330
342
 
@@ -3,17 +3,13 @@
3
3
  module DeprecateSoft
4
4
  module GlobalMonkeyPatch
5
5
  def deprecate_soft(method_name, message)
6
- if self.singleton_class.method_defined?(method_name) || self.singleton_class.private_method_defined?(method_name)
7
- # Class method
8
- DeprecateSoft::MethodWrapper.wrap_method(self, method_name, message, is_class_method: true)
9
- elsif self.instance_methods.include?(method_name) || self.private_instance_methods.include?(method_name)
10
- # Instance method
11
- DeprecateSoft::MethodWrapper.wrap_method(self, method_name, message, is_class_method: false)
12
- else # rubocop:disable Style/EmptyElse
13
- # protect against declaring deprecate_soft before method is defined
14
- #
15
- # Do nothing โ€” fail-safe in production
16
- end
6
+ extend DeprecateSoft::ClassMethods unless is_a?(DeprecateSoft::ClassMethods)
7
+ deprecate_soft(method_name, message)
8
+ end
9
+
10
+ def deprecate_class_soft(method_name, message = nil)
11
+ extend DeprecateSoft::ClassMethods unless is_a?(DeprecateSoft::ClassMethods)
12
+ deprecate_class_soft(method_name, message)
17
13
  end
18
14
  end
19
15
  end
@@ -14,7 +14,8 @@ module DeprecateSoft
14
14
  target.define_method(hidden_method_name, original_method)
15
15
 
16
16
  target.define_method(method_name) do |*args, &block|
17
- full_name = "#{self.name}.#{method_name}"
17
+ klass_name = self.class.name || self.class.to_s
18
+ full_name = "#{klass_name}.#{method_name}"
18
19
 
19
20
  begin
20
21
  DeprecateSoft.before_hook&.call(full_name, message, args: args)
@@ -39,7 +40,8 @@ module DeprecateSoft
39
40
  context.define_method(hidden_method_name, original_method)
40
41
 
41
42
  context.define_method(method_name) do |*args, &block|
42
- full_name = "#{self.class}##{method_name}"
43
+ klass_name = self.class.name || self.to_s
44
+ full_name = "#{klass_name}.#{method_name}"
43
45
 
44
46
  begin
45
47
  DeprecateSoft.before_hook&.call(full_name, message, args: args)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeprecateSoft
4
- VERSION = '1.1.0'
4
+ VERSION = '1.2.0'
5
5
  end
@@ -1,24 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'deprecate_soft/version'
4
-
5
- require_relative 'deprecate_soft/method_wrapper'
3
+ # require all files under lib/deprecate_soft
4
+ Dir[File.join(__dir__, 'deprecate_soft', '*.rb')].sort.each do |file|
5
+ require file
6
+ end
6
7
 
7
8
  module DeprecateSoft
8
- def configure_base(base)
9
- base.extend(ClassMethods)
10
- base.extend(InstanceMethods)
11
- end
12
- module_function :configure_base
13
-
14
- def included(base)
15
- configure_base(base)
16
- end
17
-
18
- def extended(base)
19
- configure_base(base)
20
- end
21
-
22
9
  class << self
23
10
  attr_accessor :before_hook, :after_hook
24
11
  attr_writer :prefix, :suffix
@@ -34,23 +21,58 @@ module DeprecateSoft
34
21
  def configure
35
22
  yield self
36
23
  end
37
- end
38
24
 
39
- module InstanceMethods
40
- def deprecate_soft(method_name, message)
41
- # protect against declaring deprecate_soft before method is defined
42
- return unless method_defined?(method_name) || private_method_defined?(method_name)
25
+ def prefixed_name(method_name)
26
+ "#{prefix}#{method_name}_#{suffix}".to_sym
27
+ end
28
+
29
+ def included(base)
30
+ base.extend(ClassMethods)
43
31
 
44
- DeprecateSoft::MethodWrapper.wrap_method(self, method_name, message, is_class_method: false)
32
+ base.define_singleton_method(:method_added) do |method_name|
33
+ pending = base.instance_variable_get(:@__pending_soft_wraps)
34
+ if pending&.key?(method_name)
35
+ DeprecateSoft::MethodWrapper.wrap_method(base, method_name, pending.delete(method_name), is_class_method: false)
36
+ end
37
+ super(method_name) if defined?(super)
38
+ end
39
+
40
+ base.singleton_class.define_method(:singleton_method_added) do |method_name|
41
+ pending = instance_variable_get(:@_pending_soft_wraps)
42
+ if pending&.key?(method_name)
43
+ DeprecateSoft::MethodWrapper.wrap_method(base, method_name, pending.delete(method_name), is_class_method: true)
44
+ end
45
+ super(method_name) if defined?(super)
46
+ end
45
47
  end
46
48
  end
47
49
 
48
50
  module ClassMethods
49
- def deprecate_soft(method_name, message)
50
- # protect against declaring deprecate_soft before method is defined
51
- return unless singleton_class.method_defined?(method_name) || singleton_class.private_method_defined?(method_name)
51
+ def deprecate_soft(method_name, message = nil)
52
+ hidden = DeprecateSoft.prefixed_name(method_name)
53
+
54
+ if method_defined?(method_name) || private_method_defined?(method_name)
55
+ return if method_defined?(hidden) || private_method_defined?(hidden)
56
+
57
+ DeprecateSoft::MethodWrapper.wrap_method(self, method_name, message, is_class_method: false)
58
+ else
59
+ @__pending_soft_wraps ||= {}
60
+ @__pending_soft_wraps[method_name] = message
61
+ end
62
+ end
63
+
64
+ def deprecate_class_soft(method_name, message = nil)
65
+ hidden = DeprecateSoft.prefixed_name(method_name)
66
+ target = singleton_class
67
+
68
+ if target.method_defined?(method_name) || target.private_method_defined?(method_name)
69
+ return if target.method_defined?(hidden) || target.private_method_defined?(hidden)
52
70
 
53
- DeprecateSoft::MethodWrapper.wrap_method(self, method_name, message, is_class_method: true)
71
+ DeprecateSoft::MethodWrapper.wrap_method(self, method_name, message, is_class_method: true)
72
+ else
73
+ @_pending_soft_wraps ||= {}
74
+ @_pending_soft_wraps[method_name] = message
75
+ end
54
76
  end
55
77
  end
56
78
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deprecate_soft
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tilo Sloboda
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-03-29 00:00:00.000000000 Z
11
+ date: 2025-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dogstatsd-ruby
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '1.21'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  description: |
98
112
  DeprecateSoft is a lightweight Ruby gem that lets you gracefully deprecate methods
99
113
  in your codebase without breaking functionality. It wraps existing instance or