sigterm_extensions 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +17 -0
- data/Gemfile +6 -0
- data/LICENSE.md +0 -0
- data/README.md +0 -0
- data/bin/ctxirb +156 -0
- data/lib/git.rb +166 -0
- data/lib/git/LICENSE +21 -0
- data/lib/git/author.rb +14 -0
- data/lib/git/base.rb +551 -0
- data/lib/git/base/factory.rb +75 -0
- data/lib/git/branch.rb +126 -0
- data/lib/git/branches.rb +71 -0
- data/lib/git/config.rb +22 -0
- data/lib/git/diff.rb +159 -0
- data/lib/git/index.rb +5 -0
- data/lib/git/lib.rb +1041 -0
- data/lib/git/log.rb +128 -0
- data/lib/git/object.rb +312 -0
- data/lib/git/path.rb +31 -0
- data/lib/git/remote.rb +36 -0
- data/lib/git/repository.rb +6 -0
- data/lib/git/stash.rb +27 -0
- data/lib/git/stashes.rb +55 -0
- data/lib/git/status.rb +199 -0
- data/lib/git/version.rb +5 -0
- data/lib/git/working_directory.rb +4 -0
- data/lib/sigterm_extensions.rb +75 -0
- data/lib/sigterm_extensions/all.rb +12 -0
- data/lib/sigterm_extensions/backtrace_cleaner.rb +129 -0
- data/lib/sigterm_extensions/callbacks.rb +847 -0
- data/lib/sigterm_extensions/concern.rb +169 -0
- data/lib/sigterm_extensions/configurable.rb +38 -0
- data/lib/sigterm_extensions/core_ext.rb +4 -0
- data/lib/sigterm_extensions/core_ext/array.rb +3 -0
- data/lib/sigterm_extensions/core_ext/array/extract.rb +19 -0
- data/lib/sigterm_extensions/core_ext/array/extract_options.rb +29 -0
- data/lib/sigterm_extensions/core_ext/class.rb +3 -0
- data/lib/sigterm_extensions/core_ext/class/attribute.rb +139 -0
- data/lib/sigterm_extensions/core_ext/class/attribute_accessors.rb +4 -0
- data/lib/sigterm_extensions/core_ext/class/subclasses.rb +52 -0
- data/lib/sigterm_extensions/core_ext/custom.rb +12 -0
- data/lib/sigterm_extensions/core_ext/digest.rb +3 -0
- data/lib/sigterm_extensions/core_ext/digest/uuid.rb +51 -0
- data/lib/sigterm_extensions/core_ext/enumerable.rb +232 -0
- data/lib/sigterm_extensions/core_ext/file.rb +3 -0
- data/lib/sigterm_extensions/core_ext/file/atomic.rb +68 -0
- data/lib/sigterm_extensions/core_ext/hash.rb +3 -0
- data/lib/sigterm_extensions/core_ext/hash/deep_merge.rb +41 -0
- data/lib/sigterm_extensions/core_ext/hash/deep_transform_values.rb +44 -0
- data/lib/sigterm_extensions/core_ext/hash/except.rb +22 -0
- data/lib/sigterm_extensions/core_ext/hash/keys.rb +141 -0
- data/lib/sigterm_extensions/core_ext/hash/reverse_merge.rb +23 -0
- data/lib/sigterm_extensions/core_ext/hash/slice.rb +24 -0
- data/lib/sigterm_extensions/core_ext/kernel.rb +3 -0
- data/lib/sigterm_extensions/core_ext/kernel/concern.rb +12 -0
- data/lib/sigterm_extensions/core_ext/kernel/reporting.rb +43 -0
- data/lib/sigterm_extensions/core_ext/kernel/singleton_class.rb +6 -0
- data/lib/sigterm_extensions/core_ext/load_error.rb +7 -0
- data/lib/sigterm_extensions/core_ext/module.rb +3 -0
- data/lib/sigterm_extensions/core_ext/module/aliasing.rb +29 -0
- data/lib/sigterm_extensions/core_ext/module/anonymous.rb +28 -0
- data/lib/sigterm_extensions/core_ext/module/attr_internal.rb +36 -0
- data/lib/sigterm_extensions/core_ext/module/attribute_accessors.rb +208 -0
- data/lib/sigterm_extensions/core_ext/module/attribute_accessors_per_thread.rb +146 -0
- data/lib/sigterm_extensions/core_ext/module/concerning.rb +132 -0
- data/lib/sigterm_extensions/core_ext/module/delegation.rb +319 -0
- data/lib/sigterm_extensions/core_ext/module/redefine_method.rb +38 -0
- data/lib/sigterm_extensions/core_ext/module/remove_method.rb +15 -0
- data/lib/sigterm_extensions/core_ext/name_error.rb +36 -0
- data/lib/sigterm_extensions/core_ext/object.rb +3 -0
- data/lib/sigterm_extensions/core_ext/object/blank.rb +153 -0
- data/lib/sigterm_extensions/core_ext/object/colors.rb +39 -0
- data/lib/sigterm_extensions/core_ext/object/duplicable.rb +47 -0
- data/lib/sigterm_extensions/core_ext/object/inclusion.rb +27 -0
- data/lib/sigterm_extensions/core_ext/object/instance_variables.rb +28 -0
- data/lib/sigterm_extensions/core_ext/object/methods.rb +61 -0
- data/lib/sigterm_extensions/core_ext/object/with_options.rb +80 -0
- data/lib/sigterm_extensions/core_ext/range.rb +3 -0
- data/lib/sigterm_extensions/core_ext/range/compare_range.rb +74 -0
- data/lib/sigterm_extensions/core_ext/range/conversions.rb +39 -0
- data/lib/sigterm_extensions/core_ext/range/overlaps.rb +8 -0
- data/lib/sigterm_extensions/core_ext/securerandom.rb +43 -0
- data/lib/sigterm_extensions/core_ext/string.rb +3 -0
- data/lib/sigterm_extensions/core_ext/string/access.rb +93 -0
- data/lib/sigterm_extensions/core_ext/string/filters.rb +143 -0
- data/lib/sigterm_extensions/core_ext/string/starts_ends_with.rb +4 -0
- data/lib/sigterm_extensions/core_ext/string/strip.rb +25 -0
- data/lib/sigterm_extensions/core_ext/tryable.rb +132 -0
- data/lib/sigterm_extensions/descendants_tracker.rb +108 -0
- data/lib/sigterm_extensions/gem_methods.rb +47 -0
- data/lib/sigterm_extensions/hash_binding.rb +16 -0
- data/lib/sigterm_extensions/inflector.rb +339 -0
- data/lib/sigterm_extensions/inflector/acronyms.rb +42 -0
- data/lib/sigterm_extensions/inflector/inflections.rb +249 -0
- data/lib/sigterm_extensions/inflector/inflections/defaults.rb +117 -0
- data/lib/sigterm_extensions/inflector/rules.rb +37 -0
- data/lib/sigterm_extensions/inflector/version.rb +8 -0
- data/lib/sigterm_extensions/interactive_editor.rb +120 -0
- data/lib/sigterm_extensions/lazy.rb +34 -0
- data/lib/sigterm_extensions/lazy_load_hooks.rb +79 -0
- data/lib/sigterm_extensions/option_merger.rb +32 -0
- data/lib/sigterm_extensions/ordered_hash.rb +48 -0
- data/lib/sigterm_extensions/ordered_options.rb +83 -0
- data/lib/sigterm_extensions/paths.rb +235 -0
- data/lib/sigterm_extensions/per_thread_registry.rb +58 -0
- data/lib/sigterm_extensions/proxy_object.rb +14 -0
- data/lib/sigterm_extensions/staging/boot.rb +31 -0
- data/lib/sigterm_extensions/staging/boot/bundler_patch.rb +24 -0
- data/lib/sigterm_extensions/staging/boot/command.rb +26 -0
- data/lib/sigterm_extensions/staging/boot/gemfile_next_auto_sync.rb +79 -0
- data/lib/sigterm_extensions/version.rb +4 -0
- data/lib/sigterm_extensions/wrappable.rb +16 -0
- data/sigterm_extensions.gemspec +42 -0
- data/templates/dotpryrc.rb.erb +124 -0
- metadata +315 -0
@@ -0,0 +1,169 @@
|
|
1
|
+
module SigtermExtensions
|
2
|
+
# A typical module looks like this:
|
3
|
+
#
|
4
|
+
# module M
|
5
|
+
# def self.included(base)
|
6
|
+
# base.extend ClassMethods
|
7
|
+
# base.class_eval do
|
8
|
+
# scope :disabled, -> { where(disabled: true) }
|
9
|
+
# end
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# module ClassMethods
|
13
|
+
# ...
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# By using <tt>SigtermExtensions::Concern</tt> the above module could instead be
|
18
|
+
# written as:
|
19
|
+
#
|
20
|
+
# require 'sigterm_extensions/concern'
|
21
|
+
#
|
22
|
+
# module M
|
23
|
+
# extend SigtermExtensions::Concern
|
24
|
+
#
|
25
|
+
# included do
|
26
|
+
# scope :disabled, -> { where(disabled: true) }
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# class_methods do
|
30
|
+
# ...
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# Moreover, it gracefully handles module dependencies. Given a +Foo+ module
|
35
|
+
# and a +Bar+ module which depends on the former, we would typically write the
|
36
|
+
# following:
|
37
|
+
#
|
38
|
+
# module Foo
|
39
|
+
# def self.included(base)
|
40
|
+
# base.class_eval do
|
41
|
+
# def self.method_injected_by_foo
|
42
|
+
# ...
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# module Bar
|
49
|
+
# def self.included(base)
|
50
|
+
# base.method_injected_by_foo
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# class Host
|
55
|
+
# include Foo # We need to include this dependency for Bar
|
56
|
+
# include Bar # Bar is the module that Host really needs
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We
|
60
|
+
# could try to hide these from +Host+ directly including +Foo+ in +Bar+:
|
61
|
+
#
|
62
|
+
# module Bar
|
63
|
+
# include Foo
|
64
|
+
# def self.included(base)
|
65
|
+
# base.method_injected_by_foo
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# class Host
|
70
|
+
# include Bar
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
|
74
|
+
# is the +Bar+ module, not the +Host+ class. With <tt>SigtermExtensions::Concern</tt>,
|
75
|
+
# module dependencies are properly resolved:
|
76
|
+
#
|
77
|
+
# require 'sigterm_extensions/concern'
|
78
|
+
#
|
79
|
+
# module Foo
|
80
|
+
# extend SigtermExtensions::Concern
|
81
|
+
# included do
|
82
|
+
# def self.method_injected_by_foo
|
83
|
+
# ...
|
84
|
+
# end
|
85
|
+
# end
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# module Bar
|
89
|
+
# extend SigtermExtensions::Concern
|
90
|
+
# include Foo
|
91
|
+
#
|
92
|
+
# included do
|
93
|
+
# self.method_injected_by_foo
|
94
|
+
# end
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# class Host
|
98
|
+
# include Bar # It works, now Bar takes care of its dependencies
|
99
|
+
# end
|
100
|
+
module Concern
|
101
|
+
class MultipleIncludedBlocks < StandardError #:nodoc:
|
102
|
+
def initialize
|
103
|
+
super "Cannot define multiple 'included' blocks for a Concern"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.extended(base) #:nodoc:
|
108
|
+
base.instance_variable_set(:@_dependencies, [])
|
109
|
+
end
|
110
|
+
|
111
|
+
def append_features(base) #:nodoc:
|
112
|
+
if base.instance_variable_defined?(:@_dependencies)
|
113
|
+
base.instance_variable_get(:@_dependencies) << self
|
114
|
+
false
|
115
|
+
else
|
116
|
+
return false if base < self
|
117
|
+
@_dependencies.each { |dep| base.include(dep) }
|
118
|
+
super
|
119
|
+
base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)
|
120
|
+
base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Evaluate given block in context of base class,
|
125
|
+
# so that you can write class macros here.
|
126
|
+
# When you define more than one +included+ block, it raises an exception.
|
127
|
+
def included(base = nil, &block)
|
128
|
+
if base.nil?
|
129
|
+
if instance_variable_defined?(:@_included_block)
|
130
|
+
if @_included_block.source_location != block.source_location
|
131
|
+
raise MultipleIncludedBlocks
|
132
|
+
end
|
133
|
+
else
|
134
|
+
@_included_block = block
|
135
|
+
end
|
136
|
+
else
|
137
|
+
super
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Define class methods from given block.
|
142
|
+
# You can define private class methods as well.
|
143
|
+
#
|
144
|
+
# module Example
|
145
|
+
# extend ActiveSupport::Concern
|
146
|
+
#
|
147
|
+
# class_methods do
|
148
|
+
# def foo; puts 'foo'; end
|
149
|
+
#
|
150
|
+
# private
|
151
|
+
# def bar; puts 'bar'; end
|
152
|
+
# end
|
153
|
+
# end
|
154
|
+
#
|
155
|
+
# class Buzz
|
156
|
+
# include Example
|
157
|
+
# end
|
158
|
+
#
|
159
|
+
# Buzz.foo # => "foo"
|
160
|
+
# Buzz.bar # => private method 'bar' called for Buzz:Class(NoMethodError)
|
161
|
+
def class_methods(&class_methods_module_definition)
|
162
|
+
mod = const_defined?(:ClassMethods, false) ?
|
163
|
+
const_get(:ClassMethods) :
|
164
|
+
const_set(:ClassMethods, Module.new)
|
165
|
+
|
166
|
+
mod.module_eval(&class_methods_module_definition)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module SigtermExtensions
|
2
|
+
module Configurable
|
3
|
+
def self.with(*attrs)
|
4
|
+
not_provided = Object.new
|
5
|
+
|
6
|
+
config_class = Class.new do
|
7
|
+
attrs.each do |attr|
|
8
|
+
define_method attr do |value = not_provided, &block|
|
9
|
+
if value === not_provided && block.nil?
|
10
|
+
result = instance_variable_get("@#{attr}")
|
11
|
+
result.is_a?(Proc) ? instance_eval(&result) : result
|
12
|
+
else
|
13
|
+
instance_variable_set("@#{attr}", block || value)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_writer *attrs
|
19
|
+
end
|
20
|
+
|
21
|
+
class_methods = Module.new do
|
22
|
+
define_method :config do
|
23
|
+
@config ||= config_class.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def configure(&block)
|
27
|
+
config.instance_eval(&block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Module.new do
|
32
|
+
singleton_class.send :define_method, :included do |host_class|
|
33
|
+
host_class.extend class_methods
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Array
|
2
|
+
# Removes and returns the elements for which the block returns a true value.
|
3
|
+
# If no block is given, an Enumerator is returned instead.
|
4
|
+
#
|
5
|
+
# numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
6
|
+
# odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
|
7
|
+
# numbers # => [0, 2, 4, 6, 8]
|
8
|
+
def extract!
|
9
|
+
return to_enum(:extract!) { size } unless block_given?
|
10
|
+
|
11
|
+
extracted_elements = []
|
12
|
+
|
13
|
+
reject! do |element|
|
14
|
+
extracted_elements << element if yield(element)
|
15
|
+
end
|
16
|
+
|
17
|
+
extracted_elements
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Hash
|
2
|
+
# By default, only instances of Hash itself are extractable.
|
3
|
+
# Subclasses of Hash may implement this method and return
|
4
|
+
# true to declare themselves as extractable. If a Hash
|
5
|
+
# is extractable, Array#extract_options! pops it from
|
6
|
+
# the Array when it is the last element of the Array.
|
7
|
+
def extractable_options?
|
8
|
+
instance_of?(Hash)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Array
|
13
|
+
# Extracts options from a set of arguments. Removes and returns the last
|
14
|
+
# element in the array if it's a hash, otherwise returns a blank hash.
|
15
|
+
#
|
16
|
+
# def options(*args)
|
17
|
+
# args.extract_options!
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# options(1, 2) # => {}
|
21
|
+
# options(1, 2, a: :b) # => {:a=>:b}
|
22
|
+
def extract_options!
|
23
|
+
if last.is_a?(Hash) && last.extractable_options?
|
24
|
+
pop
|
25
|
+
else
|
26
|
+
{}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require "sigterm_extensions/core_ext/kernel/singleton_class"
|
2
|
+
require "sigterm_extensions/core_ext/module/redefine_method"
|
3
|
+
require "sigterm_extensions/core_ext/array/extract_options"
|
4
|
+
|
5
|
+
class Class
|
6
|
+
# Declare a class-level attribute whose value is inheritable by subclasses.
|
7
|
+
# Subclasses can change their own value and it will not impact parent class.
|
8
|
+
#
|
9
|
+
# ==== Options
|
10
|
+
#
|
11
|
+
# * <tt>:instance_reader</tt> - Sets the instance reader method (defaults to true).
|
12
|
+
# * <tt>:instance_writer</tt> - Sets the instance writer method (defaults to true).
|
13
|
+
# * <tt>:instance_accessor</tt> - Sets both instance methods (defaults to true).
|
14
|
+
# * <tt>:instance_predicate</tt> - Sets a predicate method (defaults to true).
|
15
|
+
# * <tt>:default</tt> - Sets a default value for the attribute (defaults to nil).
|
16
|
+
#
|
17
|
+
# ==== Examples
|
18
|
+
#
|
19
|
+
# class Base
|
20
|
+
# class_attribute :setting
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# class Subclass < Base
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# Base.setting = true
|
27
|
+
# Subclass.setting # => true
|
28
|
+
# Subclass.setting = false
|
29
|
+
# Subclass.setting # => false
|
30
|
+
# Base.setting # => true
|
31
|
+
#
|
32
|
+
# In the above case as long as Subclass does not assign a value to setting
|
33
|
+
# by performing <tt>Subclass.setting = _something_</tt>, <tt>Subclass.setting</tt>
|
34
|
+
# would read value assigned to parent class. Once Subclass assigns a value then
|
35
|
+
# the value assigned by Subclass would be returned.
|
36
|
+
#
|
37
|
+
# This matches normal Ruby method inheritance: think of writing an attribute
|
38
|
+
# on a subclass as overriding the reader method. However, you need to be aware
|
39
|
+
# when using +class_attribute+ with mutable structures as +Array+ or +Hash+.
|
40
|
+
# In such cases, you don't want to do changes in place. Instead use setters:
|
41
|
+
#
|
42
|
+
# Base.setting = []
|
43
|
+
# Base.setting # => []
|
44
|
+
# Subclass.setting # => []
|
45
|
+
#
|
46
|
+
# # Appending in child changes both parent and child because it is the same object:
|
47
|
+
# Subclass.setting << :foo
|
48
|
+
# Base.setting # => [:foo]
|
49
|
+
# Subclass.setting # => [:foo]
|
50
|
+
#
|
51
|
+
# # Use setters to not propagate changes:
|
52
|
+
# Base.setting = []
|
53
|
+
# Subclass.setting += [:foo]
|
54
|
+
# Base.setting # => []
|
55
|
+
# Subclass.setting # => [:foo]
|
56
|
+
#
|
57
|
+
# For convenience, an instance predicate method is defined as well.
|
58
|
+
# To skip it, pass <tt>instance_predicate: false</tt>.
|
59
|
+
#
|
60
|
+
# Subclass.setting? # => false
|
61
|
+
#
|
62
|
+
# Instances may overwrite the class value in the same way:
|
63
|
+
#
|
64
|
+
# Base.setting = true
|
65
|
+
# object = Base.new
|
66
|
+
# object.setting # => true
|
67
|
+
# object.setting = false
|
68
|
+
# object.setting # => false
|
69
|
+
# Base.setting # => true
|
70
|
+
#
|
71
|
+
# To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
|
72
|
+
#
|
73
|
+
# object.setting # => NoMethodError
|
74
|
+
# object.setting? # => NoMethodError
|
75
|
+
#
|
76
|
+
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
|
77
|
+
#
|
78
|
+
# object.setting = false # => NoMethodError
|
79
|
+
#
|
80
|
+
# To opt out of both instance methods, pass <tt>instance_accessor: false</tt>.
|
81
|
+
#
|
82
|
+
# To set a default value for the attribute, pass <tt>default:</tt>, like so:
|
83
|
+
#
|
84
|
+
# class_attribute :settings, default: {}
|
85
|
+
def class_attribute(
|
86
|
+
*attrs,
|
87
|
+
instance_accessor: true,
|
88
|
+
instance_reader: instance_accessor,
|
89
|
+
instance_writer: instance_accessor,
|
90
|
+
instance_predicate: true,
|
91
|
+
default: nil
|
92
|
+
)
|
93
|
+
attrs.each do |name|
|
94
|
+
singleton_class.silence_redefinition_of_method(name)
|
95
|
+
define_singleton_method(name) { default }
|
96
|
+
|
97
|
+
singleton_class.silence_redefinition_of_method("#{name}?")
|
98
|
+
define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
|
99
|
+
|
100
|
+
ivar = "@#{name}".to_sym
|
101
|
+
|
102
|
+
singleton_class.silence_redefinition_of_method("#{name}=")
|
103
|
+
define_singleton_method("#{name}=") do |val|
|
104
|
+
redefine_singleton_method(name) { val }
|
105
|
+
|
106
|
+
if singleton_class?
|
107
|
+
class_eval do
|
108
|
+
redefine_method(name) do
|
109
|
+
if instance_variable_defined? ivar
|
110
|
+
instance_variable_get ivar
|
111
|
+
else
|
112
|
+
singleton_class.send name
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
val
|
118
|
+
end
|
119
|
+
|
120
|
+
if instance_reader
|
121
|
+
redefine_method(name) do
|
122
|
+
if instance_variable_defined?(ivar)
|
123
|
+
instance_variable_get ivar
|
124
|
+
else
|
125
|
+
self.class.public_send name
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
redefine_method("#{name}?") { !!public_send(name) } if instance_predicate
|
130
|
+
end
|
131
|
+
|
132
|
+
if instance_writer
|
133
|
+
redefine_method("#{name}=") do |val|
|
134
|
+
instance_variable_set ivar, val
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class Class
|
2
|
+
begin
|
3
|
+
# Test if this Ruby supports each_object against singleton_class
|
4
|
+
ObjectSpace.each_object(Numeric.singleton_class) { }
|
5
|
+
|
6
|
+
# Returns an array with all classes that are < than its receiver.
|
7
|
+
#
|
8
|
+
# class C; end
|
9
|
+
# C.descendants # => []
|
10
|
+
#
|
11
|
+
# class B < C; end
|
12
|
+
# C.descendants # => [B]
|
13
|
+
#
|
14
|
+
# class A < B; end
|
15
|
+
# C.descendants # => [B, A]
|
16
|
+
#
|
17
|
+
# class D < C; end
|
18
|
+
# C.descendants # => [B, A, D]
|
19
|
+
def descendants
|
20
|
+
descendants = []
|
21
|
+
ObjectSpace.each_object(singleton_class) do |k|
|
22
|
+
next if k.singleton_class?
|
23
|
+
descendants.unshift k unless k == self
|
24
|
+
end
|
25
|
+
descendants
|
26
|
+
end
|
27
|
+
rescue StandardError # JRuby 9.0.4.0 and earlier
|
28
|
+
def descendants
|
29
|
+
descendants = []
|
30
|
+
ObjectSpace.each_object(Class) do |k|
|
31
|
+
descendants.unshift k if k < self
|
32
|
+
end
|
33
|
+
descendants.uniq!
|
34
|
+
descendants
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns an array with the direct children of +self+.
|
39
|
+
#
|
40
|
+
# class Foo; end
|
41
|
+
# class Bar < Foo; end
|
42
|
+
# class Baz < Bar; end
|
43
|
+
#
|
44
|
+
# Foo.subclasses # => [Bar]
|
45
|
+
def subclasses
|
46
|
+
subclasses, chain = [], descendants
|
47
|
+
chain.each do |k|
|
48
|
+
subclasses << k unless chain.any? { |c| c > k }
|
49
|
+
end
|
50
|
+
subclasses
|
51
|
+
end
|
52
|
+
end
|