inheritance-helper 0.2.5 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 562ea69d6c46e724638823857ec7df66ec87408b00c541cd63ce34f69fd9f1e7
4
- data.tar.gz: 806d2e7ba749dd237e4588794d393aaaf29b76b9c54f41d7174335145d51326b
3
+ metadata.gz: 5d1e8987c76ed0af5063986813c435c9e755bce6f0d145ab7d63e9f0a35ba0f9
4
+ data.tar.gz: f1c481bd51c45d74e3e36a6e95fe656e29457fb489a9d99a1760539554577462
5
5
  SHA512:
6
- metadata.gz: 9cb15000be0f56dd9a8fb48881d7766a07aee34d4330a67c049cbb8370646cccdf4d3a3d6c63f321b18dca91b9bd89ae103a6c9d0f93b339c193f3292a498d95
7
- data.tar.gz: 865ea2dbce6c43fdd02424e6936bf385d14e61e5ca5b8904a35f7e628bf142cc2ed332c6d66235789330839522cef3e1d8379b7d37a8e5154b069bb92637de4f
6
+ metadata.gz: c67b0fb5d1bbdcb65186c689c9e088739132de2cda3cc3d44ef51f131b868c64f73a4df073dfe8f4171257dedd4d8770af3dac7e47b451ca605574766c7add21
7
+ data.tar.gz: 7ef84095e953df92ee231e364ee9446e2020ee9f2d1fe9063c847bf389e13e594abe153c428669ef9f7e1f0ac00dd62b564790592fae2628622ffa80ee6cf386
data/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
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
+
14
+ ## [0.2.6](https://github.com/dougyouch/inheritance-helper/compare/v0.2.5...v0.2.6) (2026-10-05)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **class-builder:** handle repeated and trailing underscores in class names ([92488f2](https://github.com/dougyouch/inheritance-helper/commit/92488f260e9da03693745c46c9064cafb1f2159f))
20
+ * **methods:** keep the visibility of redefined class methods ([5cd1f79](https://github.com/dougyouch/inheritance-helper/commit/5cd1f79529de471c27249a163b6de66cc45d9453))
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Douglas Youch
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,239 @@
1
+ # inheritance-helper
2
+
3
+ Class-level settings that subclasses can extend without changing their parents.
4
+
5
+ [![CI](https://github.com/dougyouch/inheritance-helper/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/dougyouch/inheritance-helper/actions/workflows/ci.yml)
6
+ [![Coverage](https://raw.githubusercontent.com/dougyouch/inheritance-helper/badges/coverage.svg)](https://github.com/dougyouch/inheritance-helper/actions/workflows/ci.yml)
7
+ [![Branch Coverage](https://raw.githubusercontent.com/dougyouch/inheritance-helper/badges/branches.svg)](https://github.com/dougyouch/inheritance-helper/actions/workflows/ci.yml)
8
+ [![Gem Version](https://badge.fury.io/rb/inheritance-helper.svg)](https://rubygems.org/gems/inheritance-helper)
9
+
10
+ [API reference](https://rubydoc.info/gems/inheritance-helper) · [Changelog](CHANGELOG.md)
11
+
12
+ DSLs often collect data at the class level: attributes, options, callbacks. With a class instance variable,
13
+ subclasses don't see the parent's data. With a class variable (`@@attributes`), every class in the chain
14
+ shares and changes the same object. `inheritance-helper` avoids both: each call replaces the class method on
15
+ the class it's called on, so a subclass starts with its parent's value, adds to it, and the parent keeps its
16
+ own.
17
+
18
+ It has no dependencies. It is used by [schema-model](https://github.com/dougyouch/schema) to collect
19
+ attribute definitions.
20
+
21
+ ## Installation
22
+
23
+ Requires Ruby 3.3 or newer. Add this line to your application's Gemfile:
24
+
25
+ ```ruby
26
+ gem 'inheritance-helper'
27
+ ```
28
+
29
+ And then execute:
30
+
31
+ ```bash
32
+ $ bundle install
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ Extend a class with `InheritanceHelper::Methods` and define a class method that returns the starting value.
38
+ Freezing the value is recommended: values built from a frozen value are frozen too, so no class can change
39
+ another's data by mutating it.
40
+
41
+ ```ruby
42
+ require 'inheritance-helper'
43
+
44
+ class Model
45
+ extend InheritanceHelper::Methods
46
+
47
+ def self.attributes
48
+ {}.freeze
49
+ end
50
+
51
+ def self.attribute(name, type)
52
+ add_value_to_class_method(:attributes, name => type)
53
+ attr_accessor name
54
+ end
55
+ end
56
+
57
+ class Person < Model
58
+ attribute :name, :string
59
+ attribute :phone, :string
60
+ end
61
+
62
+ class Employee < Person
63
+ attribute :employee_id, :integer
64
+ end
65
+
66
+ Model.attributes # => {}
67
+ Person.attributes # => {name: :string, phone: :string}
68
+ Employee.attributes # => {name: :string, phone: :string, employee_id: :integer}
69
+ ```
70
+
71
+ ### add_value_to_class_method
72
+
73
+ Redefines a class method to return its current value with more added:
74
+
75
+ - a **Hash** is merged with the new hash
76
+ - an **Array** or **Set** is combined with `Array(value)`, so an array of values adds each one and the
77
+ result stays flat
78
+
79
+ ```ruby
80
+ class Base
81
+ extend InheritanceHelper::Methods
82
+
83
+ def self.fields = [].freeze
84
+ def self.tags = Set.new.freeze
85
+ end
86
+
87
+ class Child < Base
88
+ add_value_to_class_method :fields, :name
89
+ add_value_to_class_method :fields, %i[email phone]
90
+ add_value_to_class_method :tags, :admin
91
+ end
92
+
93
+ Child.fields # => [:name, :email, :phone]
94
+ Child.tags # => Set[:admin]
95
+ Base.fields # => []
96
+ ```
97
+
98
+ ### append_value_to_class_method
99
+
100
+ Redefines a class method to return its current array with one element appended. Unlike
101
+ `add_value_to_class_method`, an array is added as a single element:
102
+
103
+ ```ruby
104
+ class Base
105
+ extend InheritanceHelper::Methods
106
+
107
+ def self.callbacks = [].freeze
108
+
109
+ def self.before_save(*methods)
110
+ append_value_to_class_method(:callbacks, methods)
111
+ end
112
+ end
113
+
114
+ class Child < Base
115
+ before_save :normalize, :validate
116
+ before_save :log
117
+ end
118
+
119
+ Child.callbacks # => [[:normalize, :validate], [:log]]
120
+ ```
121
+
122
+ ### redefine_class_method
123
+
124
+ Replaces a class method with one that returns the given value. Use it for settings that are replaced rather
125
+ than added to:
126
+
127
+ ```ruby
128
+ class Base
129
+ extend InheritanceHelper::Methods
130
+
131
+ def self.table_name = 'records'
132
+
133
+ def self.table(name)
134
+ redefine_class_method(:table_name, name.freeze)
135
+ end
136
+ end
137
+
138
+ class User < Base
139
+ table 'users'
140
+ end
141
+
142
+ User.table_name # => "users"
143
+ Base.table_name # => "records"
144
+ ```
145
+
146
+ The method returns the same object on every call, so freeze values that callers shouldn't change. The new
147
+ method keeps the visibility of the one it replaces, so a private class method stays private.
148
+
149
+ `InheritanceHelper::Methods.redefine_class_method(klass, method, value)` does the same for a class that
150
+ doesn't extend the module.
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
+
179
+ ### Notes
180
+
181
+ - The class method must already return a value: `add_value_to_class_method` and
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`.
184
+ - Each call defines a method on the class's singleton class. Classes declared at load time (the usual DSL
185
+ case) are fine; redefining class methods from several threads at once is not synchronized.
186
+
187
+ ## ClassBuilder::Utils
188
+
189
+ `InheritanceHelper::ClassBuilder::Utils` creates named classes at runtime, which is useful for DSLs that
190
+ build nested classes (such as a `has_many :items do ... end` block):
191
+
192
+ ```ruby
193
+ module Shop; end
194
+
195
+ klass = InheritanceHelper::ClassBuilder::Utils.create_class(Shop, :line_item, nil, 'Schema', nil) do
196
+ attr_accessor :quantity
197
+ end
198
+
199
+ klass # => Shop::SchemaLineItem
200
+ klass.name # => "Shop::SchemaLineItem"
201
+
202
+ InheritanceHelper::ClassBuilder::Utils.get_class_name(:line_item, 'Has', 'Class')
203
+ # => "HasLineItemClass"
204
+ ```
205
+
206
+ `create_class(base_module, name, base_class, prefix, suffix, &block)` subclasses `base_class` (or `Object` when
207
+ `nil`), assigns it to the constant in `base_module`, and evaluates the block in the new class. If the constant
208
+ already exists it is replaced, with Ruby's "already initialized constant" warning.
209
+
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).
213
+
214
+ ## Development
215
+
216
+ ```bash
217
+ bundle install
218
+ bundle exec rspec # tests, with line and branch coverage in coverage/
219
+ bundle exec rubocop # lint
220
+ bundle exec yard doc # API docs in doc/
221
+ ```
222
+
223
+ CI requires 100% line and branch coverage, no RuboCop offenses, and every public method documented with YARD.
224
+
225
+ Releases are automated with [release-please](https://github.com/googleapis/release-please): conventional
226
+ commits on `master` (`fix:`, `feat:`) update a release PR, and merging it tags the release and publishes the
227
+ gem.
228
+
229
+ ## Contributing
230
+
231
+ 1. Fork the repository
232
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
233
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
234
+ 4. Push to the branch (`git push origin my-new-feature`)
235
+ 5. Create a new Pull Request
236
+
237
+ ## License
238
+
239
+ The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
@@ -1,31 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module InheritanceHelper
4
- # Utility methods for building dynamic classes
5
4
  module ClassBuilder
5
+ # Functions for creating named classes inside a module.
6
+ #
7
+ # @example
8
+ # InheritanceHelper::ClassBuilder::Utils.create_class(MyApp, :line_item, Struct.new(:id), 'Schema', nil)
9
+ # # => MyApp::SchemaLineItem
6
10
  module Utils
7
11
  module_function
8
12
 
9
- def get_class_name(name, preffix_class_name, postfix_class_name)
10
- name = name.to_s
11
-
12
- class_name =
13
- if name.respond_to?(:classify)
14
- name.classify
15
- else
16
- # simple naive method to convert a string to a class name
17
- name.gsub(/(^.|_.)/) { |_| ($1[1] || $1[0]).upcase }
18
- end
19
-
20
- preffix_class_name.to_s + class_name + postfix_class_name.to_s
13
+ # Builds a class name from `name` with an optional prefix and suffix.
14
+ #
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
+ #
18
+ # @param name [String, Symbol] the base name, such as `:line_item`
19
+ # @param prefix_class_name [String, nil] text to put before the converted name
20
+ # @param suffix_class_name [String, nil] text to put after the converted name
21
+ # @return [String] the class name, such as `"SchemaLineItem"`
22
+ # @example
23
+ # get_class_name(:line_item, 'Schema', 'Class') # => "SchemaLineItemClass"
24
+ def get_class_name(name, prefix_class_name, suffix_class_name)
25
+ class_name = name.to_s.split('_').map { |part| part.sub(/\A./, &:upcase) }.join
26
+ "#{prefix_class_name}#{class_name}#{suffix_class_name}"
21
27
  end
22
28
 
23
- # Purpose to create a class that is under a module with an actual class name
24
- def create_class(base_module, name, base_class, preffix_class_name, postfix_class_name, &block)
25
- class_name = get_class_name(name, preffix_class_name, postfix_class_name)
26
- kls = base_class ? Class.new(base_class) : Class.new
29
+ # Creates a class and assigns it to a constant in `base_module`, which gives the class a name.
30
+ #
31
+ # If the constant already exists it is replaced, and Ruby prints an "already initialized constant"
32
+ # warning.
33
+ #
34
+ # @param base_module [Module] the module the class is defined in
35
+ # @param name [String, Symbol] the base name, converted with {get_class_name}
36
+ # @param base_class [Class, nil] the superclass, or `nil` for `Object`
37
+ # @param prefix_class_name [String, nil] text to put before the converted name
38
+ # @param suffix_class_name [String, nil] text to put after the converted name
39
+ # @yield evaluated in the new class with `class_eval`, to define its methods
40
+ # @return [Class] the new class
41
+ # @raise [NameError] if the resulting name isn't a valid constant name
42
+ def create_class(base_module, name, base_class, prefix_class_name, suffix_class_name, &block)
43
+ class_name = get_class_name(name, prefix_class_name, suffix_class_name)
44
+ kls = Class.new(base_class || Object)
27
45
  base_module.const_set(class_name, kls)
28
- kls = base_module.const_get(class_name)
29
46
  kls.class_eval(&block) if block
30
47
  kls
31
48
  end
@@ -1,21 +1,91 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module InheritanceHelper
4
- # Collection of utility methods for rewriting class methods
4
+ # Class methods for redefining class methods on a subclass.
5
+ #
6
+ # Extend a class with this module. A class method on that class, or on any subclass, can then be replaced
7
+ # with one that returns a new value. The new method is defined on the receiving class's singleton class,
8
+ # so the parent class keeps its own method and value.
9
+ #
10
+ # @example Collect attributes across an inheritance chain
11
+ # class Model
12
+ # extend InheritanceHelper::Methods
13
+ #
14
+ # def self.attributes
15
+ # {}.freeze
16
+ # end
17
+ #
18
+ # def self.attribute(name, type)
19
+ # add_value_to_class_method(:attributes, name => type)
20
+ # end
21
+ # end
22
+ #
23
+ # class Person < Model
24
+ # attribute :name, :string
25
+ # end
26
+ #
27
+ # Person.attributes # => {name: :string}
28
+ # Model.attributes # => {}
5
29
  module Methods
30
+ # Defines (or replaces) the class method `method` on `klass` so that it returns `value`.
31
+ #
32
+ # The new method keeps the visibility of the method it replaces, so a private class method stays private.
33
+ #
34
+ # @param klass [Module] the class or module to define the method on
35
+ # @param method [Symbol, String] name of the class method
36
+ # @param value [Object] the value the method returns. The same object is returned on every call, so
37
+ # freeze it if callers shouldn't change it
38
+ # @return [Module] `klass`
6
39
  def self.redefine_class_method(klass, method, value)
7
- class << klass; self; end.send(:define_method, method) { value }
40
+ singleton = klass.singleton_class
41
+ visibility = method_visibility(singleton, method)
42
+ singleton.send(:define_method, method) { value }
43
+ singleton.send(visibility, method)
8
44
  klass
9
45
  end
10
46
 
47
+ # @api private
48
+ # @param mod [Module] the module to look the method up in
49
+ # @param method [Symbol, String] name of the method
50
+ # @return [Symbol] `:private`, `:protected` or `:public` (also for a method that isn't defined yet)
51
+ def self.method_visibility(mod, method)
52
+ if mod.private_method_defined?(method)
53
+ :private
54
+ elsif mod.protected_method_defined?(method)
55
+ :protected
56
+ else
57
+ :public
58
+ end
59
+ end
60
+ private_class_method :method_visibility
61
+
62
+ # Defines (or replaces) the class method `method` on this class so that it returns `value`.
63
+ #
64
+ # @param method [Symbol, String] name of the class method
65
+ # @param value [Object] the value the method returns
66
+ # @return [Module] this class
67
+ # @see InheritanceHelper::Methods.redefine_class_method
11
68
  def redefine_class_method(method, value)
12
69
  ::InheritanceHelper::Methods.redefine_class_method(self, method, value)
13
70
  end
14
71
 
15
- # useful for adding data to hashes.
16
- # when working with arrays it keeps a flat data set
72
+ # Redefines the class method `method` to return its current value with `value` added.
73
+ #
74
+ # - A Hash is merged with `value`, which must be a Hash.
75
+ # - Anything else (an Array, a Set) is combined with `Array(value)`, so an array of values adds each one
76
+ # and the result stays flat. Use {#append_value_to_class_method} to add an array as a single element.
77
+ #
78
+ # The current value isn't changed. If it is frozen, the new value is frozen too.
79
+ #
80
+ # @param method [Symbol, String] name of a class method that returns a Hash, Array or Set
81
+ # @param value [Object] the value or values to add
82
+ # @return [Module] this class
83
+ # @raise [TypeError] if the class method returns `nil`
84
+ # @example
85
+ # add_value_to_class_method(:attributes, name: :string) # {} => {name: :string}
86
+ # add_value_to_class_method(:fields, [:a, :b]) # [] => [:a, :b]
17
87
  def add_value_to_class_method(method, value)
18
- old_value = send(method)
88
+ old_value = current_class_method_value(method)
19
89
 
20
90
  new_value =
21
91
  case old_value
@@ -28,11 +98,36 @@ module InheritanceHelper
28
98
  redefine_class_method(method, old_value.frozen? ? new_value.freeze : new_value)
29
99
  end
30
100
 
31
- # useful for working with arrays and maintain a list of values
101
+ # Redefines the class method `method` to return a copy of its current value with `value` appended as a
102
+ # single element (using `<<`).
103
+ #
104
+ # The current value isn't changed. If it is frozen, the new value is frozen too.
105
+ #
106
+ # @param method [Symbol, String] name of a class method that returns an Array (or anything that responds
107
+ # to `dup` and `<<`)
108
+ # @param value [Object] the element to append
109
+ # @return [Module] this class
110
+ # @raise [TypeError] if the class method returns `nil`
111
+ # @example
112
+ # append_value_to_class_method(:callbacks, [:save, :log]) # [] => [[:save, :log]]
32
113
  def append_value_to_class_method(method, value)
33
- old_value = send(method)
114
+ old_value = current_class_method_value(method)
34
115
  new_value = old_value.dup << value
35
116
  redefine_class_method(method, old_value.frozen? ? new_value.freeze : new_value)
36
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
37
132
  end
38
133
  end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InheritanceHelper
4
+ # Gem version, bumped by release-please
5
+ VERSION = '0.3.0'
6
+ end
@@ -1,9 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # A set of utility classes for making inheritance work with class level variables
3
+ require_relative 'inheritance-helper/version'
4
+
5
+ # Helpers for class-level values that subclasses can extend without changing their parent classes.
4
6
  module InheritanceHelper
5
7
  autoload :Methods, 'inheritance-helper/methods'
6
8
 
9
+ # Helpers for creating classes at runtime.
7
10
  module ClassBuilder
8
11
  autoload :Utils, 'inheritance-helper/class_builder/utils'
9
12
  end
metadata CHANGED
@@ -1,29 +1,40 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inheritance-helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Doug Youch
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2021-08-01 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
- description: Redefines class methods
14
- email: dougyouch+github@gmail.com
12
+ description: Redefine a class method on a subclass to return a new value, so hashes,
13
+ arrays and sets declared on a parent class can be added to by each subclass while
14
+ the parent keeps its own copy. Built for DSLs that collect attributes, options or
15
+ callbacks at the class level. Also includes a helper for creating named classes
16
+ inside a module.
17
+ email: dougyouch@gmail.com
15
18
  executables: []
16
19
  extensions: []
17
20
  extra_rdoc_files: []
18
21
  files:
22
+ - CHANGELOG.md
23
+ - LICENSE.txt
24
+ - README.md
19
25
  - lib/inheritance-helper.rb
20
26
  - lib/inheritance-helper/class_builder/utils.rb
21
27
  - lib/inheritance-helper/methods.rb
28
+ - lib/inheritance-helper/version.rb
22
29
  homepage: https://github.com/dougyouch/inheritance-helper
23
30
  licenses:
24
31
  - MIT
25
- metadata: {}
26
- post_install_message:
32
+ metadata:
33
+ rubygems_mfa_required: 'true'
34
+ source_code_uri: https://github.com/dougyouch/inheritance-helper
35
+ changelog_uri: https://github.com/dougyouch/inheritance-helper/blob/master/CHANGELOG.md
36
+ bug_tracker_uri: https://github.com/dougyouch/inheritance-helper/issues
37
+ documentation_uri: https://rubydoc.info/gems/inheritance-helper
27
38
  rdoc_options: []
28
39
  require_paths:
29
40
  - lib
@@ -31,15 +42,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
31
42
  requirements:
32
43
  - - ">="
33
44
  - !ruby/object:Gem::Version
34
- version: '0'
45
+ version: '3.3'
35
46
  required_rubygems_version: !ruby/object:Gem::Requirement
36
47
  requirements:
37
48
  - - ">="
38
49
  - !ruby/object:Gem::Version
39
50
  version: '0'
40
51
  requirements: []
41
- rubygems_version: 3.2.3
42
- signing_key:
52
+ rubygems_version: 4.0.20
43
53
  specification_version: 4
44
- summary: Inheritance Helpers
54
+ summary: Class-level settings that subclasses can extend without changing their parents
45
55
  test_files: []