sleeping_king_studios-tools 0.7.0 → 1.0.2
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 +5 -5
- data/CHANGELOG.md +54 -3
- data/CODE_OF_CONDUCT.md +132 -0
- data/DEVELOPMENT.md +7 -16
- data/LICENSE +1 -1
- data/README.md +71 -145
- data/lib/sleeping_king_studios/tools.rb +12 -6
- data/lib/sleeping_king_studios/tools/array_tools.rb +86 -58
- data/lib/sleeping_king_studios/tools/base.rb +20 -0
- data/lib/sleeping_king_studios/tools/core_tools.rb +78 -19
- data/lib/sleeping_king_studios/tools/hash_tools.rb +69 -42
- data/lib/sleeping_king_studios/tools/integer_tools.rb +97 -55
- data/lib/sleeping_king_studios/tools/object_tools.rb +75 -52
- data/lib/sleeping_king_studios/tools/string_tools.rb +69 -96
- data/lib/sleeping_king_studios/tools/toolbelt.rb +44 -23
- data/lib/sleeping_king_studios/tools/toolbox.rb +2 -2
- data/lib/sleeping_king_studios/tools/toolbox/constant_map.rb +75 -74
- data/lib/sleeping_king_studios/tools/toolbox/inflector.rb +124 -0
- data/lib/sleeping_king_studios/tools/toolbox/inflector/rules.rb +173 -0
- data/lib/sleeping_king_studios/tools/toolbox/mixin.rb +11 -11
- data/lib/sleeping_king_studios/tools/toolbox/semantic_version.rb +15 -14
- data/lib/sleeping_king_studios/tools/version.rb +14 -10
- metadata +106 -35
- data/lib/sleeping_king_studios/tools/all.rb +0 -5
- data/lib/sleeping_king_studios/tools/enumerable_tools.rb +0 -8
- data/lib/sleeping_king_studios/tools/semantic_version.rb +0 -15
- data/lib/sleeping_king_studios/tools/string_tools/plural_inflector.rb +0 -185
- data/lib/sleeping_king_studios/tools/toolbox/configuration.rb +0 -207
- data/lib/sleeping_king_studios/tools/toolbox/delegator.rb +0 -175
@@ -1,207 +0,0 @@
|
|
1
|
-
# lib/sleeping_king_studios/tools/toolbox/configuration.rb
|
2
|
-
|
3
|
-
require 'sleeping_king_studios/tools/toolbox'
|
4
|
-
|
5
|
-
module SleepingKingStudios::Tools::Toolbox
|
6
|
-
class Configuration
|
7
|
-
module ClassMethods
|
8
|
-
DEFAULT_OPTION = Object.new.freeze
|
9
|
-
|
10
|
-
# Defines a nested namespace for the configuration object.
|
11
|
-
def namespace namespace_name, &block
|
12
|
-
namespace =
|
13
|
-
(@namespaces ||= {}).fetch(namespace_name) do
|
14
|
-
@namespaces[namespace_name] = define_namespace namespace_name
|
15
|
-
end # fetch
|
16
|
-
|
17
|
-
namespace.instance_exec namespace, &block if block_given?
|
18
|
-
|
19
|
-
namespace
|
20
|
-
end # method namespace
|
21
|
-
|
22
|
-
# Defines an option for the configuration object.
|
23
|
-
def option option_name, allow_nil: false, default: DEFAULT_OPTION, enum: nil
|
24
|
-
options = {
|
25
|
-
:allow_nil => allow_nil,
|
26
|
-
:default => default,
|
27
|
-
:enum => enum
|
28
|
-
} # end hash
|
29
|
-
|
30
|
-
define_accessor option_name, options
|
31
|
-
define_mutator option_name, options
|
32
|
-
end # class method option
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def define_accessor option_name, options
|
37
|
-
define_method option_name do
|
38
|
-
__get_value__(option_name, options)
|
39
|
-
end # method option_name
|
40
|
-
end # method define_accessor
|
41
|
-
|
42
|
-
def define_mutator option_name, options
|
43
|
-
writer_name = :"#{option_name}="
|
44
|
-
|
45
|
-
define_method writer_name do |value|
|
46
|
-
__set_value__(option_name, value, options)
|
47
|
-
end # method option_name=
|
48
|
-
end # method define_mutator
|
49
|
-
|
50
|
-
def define_namespace namespace_name
|
51
|
-
namespace =
|
52
|
-
Class.new(SleepingKingStudios::Tools::Toolbox::Configuration)
|
53
|
-
|
54
|
-
define_method namespace_name do |&block|
|
55
|
-
if instance_variable_defined?(:"@#{namespace_name}")
|
56
|
-
config = instance_variable_get(:"@#{namespace_name}")
|
57
|
-
else
|
58
|
-
data = __get_value__(namespace_name, :default => Object.new)
|
59
|
-
config = namespace.new(data)
|
60
|
-
|
61
|
-
config.__root_namespace__ = __root_namespace__ || self
|
62
|
-
|
63
|
-
instance_variable_set(:"@#{namespace_name}", config)
|
64
|
-
end # if
|
65
|
-
|
66
|
-
block.call(config) if block
|
67
|
-
|
68
|
-
config
|
69
|
-
end # method namespace_name
|
70
|
-
|
71
|
-
namespace
|
72
|
-
end # method define_namespace
|
73
|
-
end # module
|
74
|
-
extend ClassMethods
|
75
|
-
|
76
|
-
DEFAULT_OPTION = ClassMethods::DEFAULT_OPTION
|
77
|
-
|
78
|
-
# @param data [Hash, Object] The data source used to populate configuration
|
79
|
-
# values. Can be a Hash or a data object. If the data source is nil, or no
|
80
|
-
# data source is given, values will be set to their respective defaults.
|
81
|
-
def initialize data = nil
|
82
|
-
@__data__ = __objectify_data__(data)
|
83
|
-
@__root_namespace__ = self
|
84
|
-
|
85
|
-
yield(singleton_class) if block_given?
|
86
|
-
end # constructor
|
87
|
-
|
88
|
-
def [] key
|
89
|
-
send(key) if respond_to?(key)
|
90
|
-
end # method []
|
91
|
-
|
92
|
-
def []= key, value
|
93
|
-
send(:"#{key}=", value)
|
94
|
-
end # method []=
|
95
|
-
|
96
|
-
def dig *keys
|
97
|
-
keys.reduce(self) do |hsh, key|
|
98
|
-
value = hsh[key]
|
99
|
-
|
100
|
-
return value if value.nil?
|
101
|
-
|
102
|
-
value
|
103
|
-
end # reduce
|
104
|
-
end # method dig
|
105
|
-
|
106
|
-
def fetch key, default = DEFAULT_OPTION
|
107
|
-
return send(key) if respond_to?(key)
|
108
|
-
|
109
|
-
return default unless default == DEFAULT_OPTION
|
110
|
-
|
111
|
-
return yield if block_given?
|
112
|
-
|
113
|
-
raise KeyError, 'key not found'
|
114
|
-
end # method fetch
|
115
|
-
|
116
|
-
protected
|
117
|
-
|
118
|
-
attr_accessor :__root_namespace__
|
119
|
-
|
120
|
-
private
|
121
|
-
|
122
|
-
attr_reader :__data__
|
123
|
-
|
124
|
-
def __blank_value__ value
|
125
|
-
value.nil? || (value.respond_to?(:empty?) && value.empty?)
|
126
|
-
end # method __blank_value__
|
127
|
-
|
128
|
-
def __evaluate_default__ default
|
129
|
-
default.is_a?(Proc) ? __root_namespace__.instance_exec(&default) : default
|
130
|
-
end # method __evaluate_default__
|
131
|
-
|
132
|
-
def __get_value__ name, options
|
133
|
-
default_given = options[:default] != DEFAULT_OPTION
|
134
|
-
|
135
|
-
if __data__.respond_to?(name)
|
136
|
-
value = __data__.send name
|
137
|
-
|
138
|
-
if value.nil? && default_given
|
139
|
-
value = __evaluate_default__(options[:default])
|
140
|
-
end # if
|
141
|
-
|
142
|
-
__validate_value__ value, options
|
143
|
-
|
144
|
-
value
|
145
|
-
elsif instance_variable_defined?(:"@#{name}")
|
146
|
-
# Recall values locally if data source is immutable.
|
147
|
-
return instance_variable_get(:"@#{name}")
|
148
|
-
elsif default_given
|
149
|
-
value = __evaluate_default__(options[:default])
|
150
|
-
|
151
|
-
__validate_value__ value, options
|
152
|
-
|
153
|
-
value
|
154
|
-
else
|
155
|
-
__validate_value__ nil, options
|
156
|
-
|
157
|
-
nil
|
158
|
-
end # if-else
|
159
|
-
end # method __get_value__
|
160
|
-
|
161
|
-
def __objectify_data__ data
|
162
|
-
return data unless data.is_a?(Hash)
|
163
|
-
|
164
|
-
return Object.new if data.empty?
|
165
|
-
|
166
|
-
obj = Struct.new(*data.keys).new
|
167
|
-
|
168
|
-
data.each do |key, value|
|
169
|
-
val = value.is_a?(Hash) ? __objectify_data__(value) : value
|
170
|
-
|
171
|
-
obj.send :"#{key}=", val
|
172
|
-
end # each
|
173
|
-
|
174
|
-
obj
|
175
|
-
end # method __objectify_data__
|
176
|
-
|
177
|
-
def __set_value__ name, value, options
|
178
|
-
writer_name = :"#{name}="
|
179
|
-
|
180
|
-
__validate_value__ value, options
|
181
|
-
|
182
|
-
if __data__.respond_to?(writer_name)
|
183
|
-
__data__.send(writer_name, value)
|
184
|
-
else
|
185
|
-
# Store values locally if data source is immutable.
|
186
|
-
instance_variable_set(:"@#{name}", value)
|
187
|
-
end # if-else
|
188
|
-
end # method __set_value__
|
189
|
-
|
190
|
-
def __validate_value__ value, options
|
191
|
-
return if __blank_value__(value) && options[:allow_nil]
|
192
|
-
|
193
|
-
if options[:enum] && !options[:enum].include?(value)
|
194
|
-
array_tools = ::SleepingKingStudios::Tools::ArrayTools
|
195
|
-
valid_options =
|
196
|
-
array_tools.
|
197
|
-
humanize_list(
|
198
|
-
options[:enum].map(&:inspect),
|
199
|
-
:last_separator => ' or '
|
200
|
-
) # end humanize_list
|
201
|
-
|
202
|
-
raise RuntimeError,
|
203
|
-
"expected option to be #{valid_options}, but was #{value.inspect}"
|
204
|
-
end # if
|
205
|
-
end # method __validate_value__
|
206
|
-
end # class
|
207
|
-
end # module
|
@@ -1,175 +0,0 @@
|
|
1
|
-
# lib/sleeping_king_studios/tools/toolbox/delegator.rb
|
2
|
-
|
3
|
-
require 'sleeping_king_studios/tools/toolbox'
|
4
|
-
|
5
|
-
module SleepingKingStudios::Tools::Toolbox
|
6
|
-
# Module for extending classes with basic delegation. Supports passing
|
7
|
-
# arguments, keywords, and blocks to the delegated method.
|
8
|
-
#
|
9
|
-
# @example
|
10
|
-
# class MyClass
|
11
|
-
# extend SleepingKingStudios::Tools::Delegator
|
12
|
-
#
|
13
|
-
# delegate :my_method, :to => MyService
|
14
|
-
# end # class
|
15
|
-
module Delegator
|
16
|
-
# Defines a wrapper method to delegate implementation of the specified
|
17
|
-
# method or methods to an object, to the object at another specified method,
|
18
|
-
# or to the object at a specified instance variable.
|
19
|
-
#
|
20
|
-
# @example Delegate to an object
|
21
|
-
# class MyModule
|
22
|
-
# extend SleepingKingStudios::Tools::Toolbox::Delegator
|
23
|
-
#
|
24
|
-
# delegate :my_method, :to => MyService
|
25
|
-
# end # class
|
26
|
-
#
|
27
|
-
# @example Delegate to a method
|
28
|
-
# class MyModule
|
29
|
-
# extend SleepingKingStudios::Tools::Toolbox::Delegator
|
30
|
-
#
|
31
|
-
# def my_service
|
32
|
-
# MyService.new
|
33
|
-
# end # method my_service
|
34
|
-
#
|
35
|
-
# delegate :my_method, :to => :my_service
|
36
|
-
# end # class
|
37
|
-
#
|
38
|
-
# @example Delegate to an instance variable
|
39
|
-
# class MyModule
|
40
|
-
# extend SleepingKingStudios::Tools::Toolbox::Delegator
|
41
|
-
#
|
42
|
-
# def initialize
|
43
|
-
# @my_service = MyService.new
|
44
|
-
# end # constructor
|
45
|
-
#
|
46
|
-
# delegate :my_method, :to => :@my_service
|
47
|
-
# end # class
|
48
|
-
#
|
49
|
-
# @param method_names [Array<String, Symbol>] The names of the methods to
|
50
|
-
# delegate.
|
51
|
-
# @param to [Object, String, Symbol] The object, method, or instance
|
52
|
-
# variable to delegate to. If the object is not a string or symbol, the
|
53
|
-
# generated method will call `method_name` on the object. If the object is
|
54
|
-
# a string or symbol, but does not start with an `@`, the generated method
|
55
|
-
# will call the method of that name on the instance, and then call
|
56
|
-
# `method_name` on the result. If the object is a string or symbol and
|
57
|
-
# does start with an `@`, the generated method will get the instance
|
58
|
-
# variable of that name and call `method_name` on the result.
|
59
|
-
#
|
60
|
-
# @raise ArgumentError if no delegate is specified.
|
61
|
-
def delegate *method_names, to: nil, allow_nil: false
|
62
|
-
raise ArgumentError.new('must specify a delegate') if to.nil? && !allow_nil
|
63
|
-
|
64
|
-
method_names.each do |method_name|
|
65
|
-
delegate_method method_name, to, { :allow_nil => !!allow_nil }
|
66
|
-
end # each
|
67
|
-
end # method delegate
|
68
|
-
|
69
|
-
# Wraps a delegate object by automatically delegating each method that is
|
70
|
-
# defined on the delegate class from the instance to the delegate. The
|
71
|
-
# delegate can be specified with an object literal or with the name of an
|
72
|
-
# instance method or instance variable.
|
73
|
-
#
|
74
|
-
# Only methods that are defined at the time #wrap_delegate is called will be
|
75
|
-
# delegated, so make sure to call #wrap_delegate after loading any gems or
|
76
|
-
# libraries that extend your delegate class, such as ActiveSupport.
|
77
|
-
#
|
78
|
-
# @example Create a class that wraps a Hash
|
79
|
-
# class Errors
|
80
|
-
# extend SleepingKingStudios::Tools::Delegator
|
81
|
-
#
|
82
|
-
# wrap_delegate Hash.new { |hsh, key| hsh[key] = Errors.new }, :klass => Hash
|
83
|
-
#
|
84
|
-
# def messages
|
85
|
-
# @messages ||= []
|
86
|
-
# end # method messages
|
87
|
-
# end # class
|
88
|
-
#
|
89
|
-
# errors = Errors.new
|
90
|
-
# errors[:post].messages << "title can't be blank"
|
91
|
-
#
|
92
|
-
# @param target [Object, String, Symbol] The object, method, or instance
|
93
|
-
# variable to delegate to. If the object is not a string or symbol, the
|
94
|
-
# generated method will call each method on the object. If the object is
|
95
|
-
# a string or symbol, but does not start with an `@`, the generated method
|
96
|
-
# will call the method of that name on the instance, and then call
|
97
|
-
# each method on the result. If the object is a string or symbol and
|
98
|
-
# does start with an `@`, the generated method will get the instance
|
99
|
-
# variable of that name and call each method on the result.
|
100
|
-
# @param klass [Module] The class or module whose methods are delegated to
|
101
|
-
# the target. If target is the name of an instance variable or an instance
|
102
|
-
# method, the klass must be specified. If target is an object literal, the
|
103
|
-
# klass is optional, in which case all methods from the target will be
|
104
|
-
# delegated to the target.
|
105
|
-
# @param except [Array<String, Symbol>] An optional list of method names.
|
106
|
-
# Any names on the list will not be delegated, even if the method is
|
107
|
-
# defined by the klass or defined on the target literal.
|
108
|
-
# @param only [Array<String, Symbol>] An optional list of method names.
|
109
|
-
# Only names on the list will be delegated, and only if the method is
|
110
|
-
# defined by the klass or defined on the target literal.
|
111
|
-
#
|
112
|
-
# @raise ArgumentError if no delegate is specified.
|
113
|
-
# @raise ArgumentError if the target is the name of an instance method or an
|
114
|
-
# instance variable and no klass is specified.
|
115
|
-
# @raise ArgumentError if the target is an object literal that does not
|
116
|
-
# belong to the specified klass.
|
117
|
-
#
|
118
|
-
# @see #delegate
|
119
|
-
def wrap_delegate target, klass: nil, except: [], only: []
|
120
|
-
if klass.is_a?(Module)
|
121
|
-
unless target.is_a?(String) || target.is_a?(Symbol) || target.is_a?(klass)
|
122
|
-
raise ArgumentError.new "expected delegate to be a #{klass.name}"
|
123
|
-
end # unless
|
124
|
-
|
125
|
-
method_names = klass.instance_methods - Object.instance_methods
|
126
|
-
elsif target.is_a?(String) || target.is_a?(Symbol)
|
127
|
-
raise ArgumentError.new 'must specify a delegate class'
|
128
|
-
else
|
129
|
-
method_names = target.methods - Object.new.methods
|
130
|
-
end # if-elsif-else
|
131
|
-
|
132
|
-
if except.is_a?(Array) && !except.empty?
|
133
|
-
method_names = method_names - except.map(&:intern)
|
134
|
-
end # if
|
135
|
-
|
136
|
-
if only.is_a?(Array) && !only.empty?
|
137
|
-
method_names = method_names & only.map(&:intern)
|
138
|
-
end # if
|
139
|
-
|
140
|
-
delegate *method_names, :to => target
|
141
|
-
end # method wrap_delegate
|
142
|
-
|
143
|
-
private
|
144
|
-
|
145
|
-
def delegate_method method_name, target, options = {}
|
146
|
-
if target.is_a?(String) || target.is_a?(Symbol)
|
147
|
-
target = target.intern
|
148
|
-
|
149
|
-
if target.to_s =~ /\A@/
|
150
|
-
define_method method_name do |*args, &block|
|
151
|
-
receiver = instance_variable_get(target)
|
152
|
-
|
153
|
-
return nil if receiver.nil? && options[:allow_nil]
|
154
|
-
|
155
|
-
receiver.send(method_name, *args, &block)
|
156
|
-
end # define_method
|
157
|
-
else
|
158
|
-
define_method method_name do |*args, &block|
|
159
|
-
receiver = send(target)
|
160
|
-
|
161
|
-
return nil if receiver.nil? && options[:allow_nil]
|
162
|
-
|
163
|
-
receiver.send(method_name, *args, &block)
|
164
|
-
end # define_method
|
165
|
-
end # if-else
|
166
|
-
else
|
167
|
-
define_method method_name do |*args, &block|
|
168
|
-
return nil if target.nil? && options[:allow_nil]
|
169
|
-
|
170
|
-
target.send(method_name, *args, &block)
|
171
|
-
end # define_method
|
172
|
-
end # if
|
173
|
-
end # method delegate_method
|
174
|
-
end # module
|
175
|
-
end # module
|