inheritance-helper 0.2.6 → 0.3.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 +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +33 -5
- data/lib/inheritance-helper/class_builder/utils.rb +3 -11
- data/lib/inheritance-helper/methods.rb +18 -2
- data/lib/inheritance-helper/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5d1e8987c76ed0af5063986813c435c9e755bce6f0d145ab7d63e9f0a35ba0f9
|
|
4
|
+
data.tar.gz: f1c481bd51c45d74e3e36a6e95fe656e29457fb489a9d99a1760539554577462
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c67b0fb5d1bbdcb65186c689c9e088739132de2cda3cc3d44ef51f131b868c64f73a4df073dfe8f4171257dedd4d8770af3dac7e47b451ca605574766c7add21
|
|
7
|
+
data.tar.gz: 7ef84095e953df92ee231e364ee9446e2020ee9f2d1fe9063c847bf389e13e594abe153c428669ef9f7e1f0ac00dd62b564790592fae2628622ffa80ee6cf386
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.0](https://github.com/dougyouch/inheritance-helper/compare/v0.2.6...v0.3.0) (2026-10-05)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* get_class_name no longer calls String#classify when ActiveSupport is loaded, so names are no longer singularized there (:line_items now gives LineItems, not LineItem). Class names are now the same whether or not ActiveSupport is loaded.
|
|
9
|
+
|
|
10
|
+
### 1.0
|
|
11
|
+
|
|
12
|
+
* clearer nil error, consistent class names, Ruby 3.3 ([#5](https://github.com/dougyouch/inheritance-helper/issues/5)) ([11bb5a8](https://github.com/dougyouch/inheritance-helper/commit/11bb5a8d056d7b6c2794895bd01c9d9bce14805d))
|
|
13
|
+
|
|
3
14
|
## [0.2.6](https://github.com/dougyouch/inheritance-helper/compare/v0.2.5...v0.2.6) (2026-10-05)
|
|
4
15
|
|
|
5
16
|
|
data/README.md
CHANGED
|
@@ -20,7 +20,7 @@ attribute definitions.
|
|
|
20
20
|
|
|
21
21
|
## Installation
|
|
22
22
|
|
|
23
|
-
Requires Ruby 3.
|
|
23
|
+
Requires Ruby 3.3 or newer. Add this line to your application's Gemfile:
|
|
24
24
|
|
|
25
25
|
```ruby
|
|
26
26
|
gem 'inheritance-helper'
|
|
@@ -149,10 +149,38 @@ method keeps the visibility of the one it replaces, so a private class method st
|
|
|
149
149
|
`InheritanceHelper::Methods.redefine_class_method(klass, method, value)` does the same for a class that
|
|
150
150
|
doesn't extend the module.
|
|
151
151
|
|
|
152
|
+
### Copy nested values before changing them
|
|
153
|
+
|
|
154
|
+
Once a value is set with these helpers, every call returns the same object, and a subclass starts with its
|
|
155
|
+
parent's object. Freezing covers only the top-level value: a hash or array *inside* it is shared by the parent
|
|
156
|
+
and the subclass, so changing it in place changes both:
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
class Base
|
|
160
|
+
extend InheritanceHelper::Methods
|
|
161
|
+
|
|
162
|
+
def self.config = {}.freeze
|
|
163
|
+
|
|
164
|
+
add_value_to_class_method :config, skip: []
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
class Child < Base
|
|
168
|
+
# wrong: appends to Base.config[:skip] too
|
|
169
|
+
config[:skip] << :logs
|
|
170
|
+
|
|
171
|
+
# right: build a new nested value and replace the key
|
|
172
|
+
add_value_to_class_method :config, skip: config[:skip] + [:logs]
|
|
173
|
+
end
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The same applies to a value from `redefine_class_method`: `dup` the value (and any nested values you change)
|
|
177
|
+
before changing it, then pass the copy to `redefine_class_method`.
|
|
178
|
+
|
|
152
179
|
### Notes
|
|
153
180
|
|
|
154
181
|
- The class method must already return a value: `add_value_to_class_method` and
|
|
155
|
-
`append_value_to_class_method` call it to get the current value
|
|
182
|
+
`append_value_to_class_method` call it to get the current value, and raise a `TypeError` naming the method
|
|
183
|
+
when it returns `nil`.
|
|
156
184
|
- Each call defines a method on the class's singleton class. Classes declared at load time (the usual DSL
|
|
157
185
|
case) are fine; redefining class methods from several threads at once is not synchronized.
|
|
158
186
|
|
|
@@ -179,9 +207,9 @@ InheritanceHelper::ClassBuilder::Utils.get_class_name(:line_item, 'Has', 'Class'
|
|
|
179
207
|
`nil`), assigns it to the constant in `base_module`, and evaluates the block in the new class. If the constant
|
|
180
208
|
already exists it is replaced, with Ruby's "already initialized constant" warning.
|
|
181
209
|
|
|
182
|
-
`get_class_name`
|
|
183
|
-
|
|
184
|
-
|
|
210
|
+
`get_class_name` splits the name on underscores and capitalizes the first letter of each part, so
|
|
211
|
+
`line_items` becomes `LineItems`. The result is the same whether or not ActiveSupport is loaded (before 1.0 it
|
|
212
|
+
used `String#classify`, which singularized the name).
|
|
185
213
|
|
|
186
214
|
## Development
|
|
187
215
|
|
|
@@ -12,8 +12,8 @@ module InheritanceHelper
|
|
|
12
12
|
|
|
13
13
|
# Builds a class name from `name` with an optional prefix and suffix.
|
|
14
14
|
#
|
|
15
|
-
# `name` is
|
|
16
|
-
#
|
|
15
|
+
# `name` is split on underscores and the first letter of each part is capitalized. The result doesn't depend
|
|
16
|
+
# on whether ActiveSupport is loaded, and the name isn't singularized (`:line_items` gives `"LineItems"`).
|
|
17
17
|
#
|
|
18
18
|
# @param name [String, Symbol] the base name, such as `:line_item`
|
|
19
19
|
# @param prefix_class_name [String, nil] text to put before the converted name
|
|
@@ -22,15 +22,7 @@ module InheritanceHelper
|
|
|
22
22
|
# @example
|
|
23
23
|
# get_class_name(:line_item, 'Schema', 'Class') # => "SchemaLineItemClass"
|
|
24
24
|
def get_class_name(name, prefix_class_name, suffix_class_name)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class_name =
|
|
28
|
-
if name.respond_to?(:classify)
|
|
29
|
-
name.classify
|
|
30
|
-
else
|
|
31
|
-
name.split('_').map { |part| part.sub(/\A./, &:upcase) }.join
|
|
32
|
-
end
|
|
33
|
-
|
|
25
|
+
class_name = name.to_s.split('_').map { |part| part.sub(/\A./, &:upcase) }.join
|
|
34
26
|
"#{prefix_class_name}#{class_name}#{suffix_class_name}"
|
|
35
27
|
end
|
|
36
28
|
|
|
@@ -80,11 +80,12 @@ module InheritanceHelper
|
|
|
80
80
|
# @param method [Symbol, String] name of a class method that returns a Hash, Array or Set
|
|
81
81
|
# @param value [Object] the value or values to add
|
|
82
82
|
# @return [Module] this class
|
|
83
|
+
# @raise [TypeError] if the class method returns `nil`
|
|
83
84
|
# @example
|
|
84
85
|
# add_value_to_class_method(:attributes, name: :string) # {} => {name: :string}
|
|
85
86
|
# add_value_to_class_method(:fields, [:a, :b]) # [] => [:a, :b]
|
|
86
87
|
def add_value_to_class_method(method, value)
|
|
87
|
-
old_value =
|
|
88
|
+
old_value = current_class_method_value(method)
|
|
88
89
|
|
|
89
90
|
new_value =
|
|
90
91
|
case old_value
|
|
@@ -106,12 +107,27 @@ module InheritanceHelper
|
|
|
106
107
|
# to `dup` and `<<`)
|
|
107
108
|
# @param value [Object] the element to append
|
|
108
109
|
# @return [Module] this class
|
|
110
|
+
# @raise [TypeError] if the class method returns `nil`
|
|
109
111
|
# @example
|
|
110
112
|
# append_value_to_class_method(:callbacks, [:save, :log]) # [] => [[:save, :log]]
|
|
111
113
|
def append_value_to_class_method(method, value)
|
|
112
|
-
old_value =
|
|
114
|
+
old_value = current_class_method_value(method)
|
|
113
115
|
new_value = old_value.dup << value
|
|
114
116
|
redefine_class_method(method, old_value.frozen? ? new_value.freeze : new_value)
|
|
115
117
|
end
|
|
118
|
+
|
|
119
|
+
private
|
|
120
|
+
|
|
121
|
+
# @api private
|
|
122
|
+
# @param method [Symbol, String] name of the class method
|
|
123
|
+
# @return [Object] the method's current value
|
|
124
|
+
# @raise [TypeError] if the method returns `nil`
|
|
125
|
+
def current_class_method_value(method)
|
|
126
|
+
value = send(method)
|
|
127
|
+
return value unless value.nil?
|
|
128
|
+
|
|
129
|
+
raise TypeError, "#{self}.#{method} returned nil; define it to return a starting value such as {}.freeze " \
|
|
130
|
+
'or [].freeze'
|
|
131
|
+
end
|
|
116
132
|
end
|
|
117
133
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: inheritance-helper
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Doug Youch
|
|
@@ -42,7 +42,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
42
42
|
requirements:
|
|
43
43
|
- - ">="
|
|
44
44
|
- !ruby/object:Gem::Version
|
|
45
|
-
version: '3.
|
|
45
|
+
version: '3.3'
|
|
46
46
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
47
|
requirements:
|
|
48
48
|
- - ">="
|