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.
Files changed (29) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +54 -3
  3. data/CODE_OF_CONDUCT.md +132 -0
  4. data/DEVELOPMENT.md +7 -16
  5. data/LICENSE +1 -1
  6. data/README.md +71 -145
  7. data/lib/sleeping_king_studios/tools.rb +12 -6
  8. data/lib/sleeping_king_studios/tools/array_tools.rb +86 -58
  9. data/lib/sleeping_king_studios/tools/base.rb +20 -0
  10. data/lib/sleeping_king_studios/tools/core_tools.rb +78 -19
  11. data/lib/sleeping_king_studios/tools/hash_tools.rb +69 -42
  12. data/lib/sleeping_king_studios/tools/integer_tools.rb +97 -55
  13. data/lib/sleeping_king_studios/tools/object_tools.rb +75 -52
  14. data/lib/sleeping_king_studios/tools/string_tools.rb +69 -96
  15. data/lib/sleeping_king_studios/tools/toolbelt.rb +44 -23
  16. data/lib/sleeping_king_studios/tools/toolbox.rb +2 -2
  17. data/lib/sleeping_king_studios/tools/toolbox/constant_map.rb +75 -74
  18. data/lib/sleeping_king_studios/tools/toolbox/inflector.rb +124 -0
  19. data/lib/sleeping_king_studios/tools/toolbox/inflector/rules.rb +173 -0
  20. data/lib/sleeping_king_studios/tools/toolbox/mixin.rb +11 -11
  21. data/lib/sleeping_king_studios/tools/toolbox/semantic_version.rb +15 -14
  22. data/lib/sleeping_king_studios/tools/version.rb +14 -10
  23. metadata +106 -35
  24. data/lib/sleeping_king_studios/tools/all.rb +0 -5
  25. data/lib/sleeping_king_studios/tools/enumerable_tools.rb +0 -8
  26. data/lib/sleeping_king_studios/tools/semantic_version.rb +0 -15
  27. data/lib/sleeping_king_studios/tools/string_tools/plural_inflector.rb +0 -185
  28. data/lib/sleeping_king_studios/tools/toolbox/configuration.rb +0 -207
  29. 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