sleeping_king_studios-tools 0.7.0.alpha.0 → 0.7.0.beta.0
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4adaa39941af100f90cca20495186512bb1df63
|
4
|
+
data.tar.gz: ebfa9dc2da32771e4e10b5a66d93023995f529ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15139f777ccb83a82fab9bfd0bd3611741862d1b391a1dc6f70d6b754d7a6629d05462e1b1086bec1d904dbc5fa441d0a1a9628c3d5ca6e4d539c9c763b2af0d
|
7
|
+
data.tar.gz: 34dc1e6707ff1ab069287f7ce2c83d1f31d9f0f834c5508b9461ad76ac704aed07a013cdab890bb576141cf1d6c4ba7f27b5e3bbbce22c310500d22031a91fdf
|
data/CHANGELOG.md
CHANGED
@@ -11,8 +11,13 @@
|
|
11
11
|
- Implement StringTools#indent.
|
12
12
|
- Implement StringTools#map_lines.
|
13
13
|
|
14
|
+
#### Toolbox
|
15
|
+
|
16
|
+
- Implement Toolbox::Configuration.
|
17
|
+
|
14
18
|
#### Misc.
|
15
19
|
|
20
|
+
- IntegerTools#pluralize now accepts 2..3 arguments, and will automatically generate the plural string using StringTools#pluralize if an explicit plural is not given.
|
16
21
|
- SleepingKingStudios::Tools::Toolbelt is now autoloaded from SleepingKingStudios::Tools.
|
17
22
|
|
18
23
|
## Current Release
|
data/DEVELOPMENT.md
CHANGED
@@ -2,10 +2,6 @@
|
|
2
2
|
|
3
3
|
## 0.7.0
|
4
4
|
|
5
|
-
- IntegerTools#pluralize - have third (plural string) parameter be optional and defer to StringTools#pluralize.
|
6
|
-
|
7
|
-
- Toolbelt should be autoloaded via Tools.
|
8
|
-
|
9
5
|
## Future Tasks
|
10
6
|
|
11
7
|
- Remove 'extend self' from Tools modules.
|
@@ -25,10 +21,6 @@
|
|
25
21
|
- Identity Methods
|
26
22
|
- RegexpTools#regexp? - true if object is regular expression, otherwise false.
|
27
23
|
|
28
|
-
#### Toolkit
|
29
|
-
|
30
|
-
- Configuration
|
31
|
-
|
32
24
|
### Maintenance
|
33
25
|
|
34
26
|
- Remove deprecated StringTools#pluralize(int, str, str) implementation.
|
data/README.md
CHANGED
@@ -353,11 +353,14 @@ Returns true if the object is an Integer.
|
|
353
353
|
|
354
354
|
#### `#pluralize`
|
355
355
|
|
356
|
-
Returns the singular or the plural value, depending on the provided item count.
|
356
|
+
Returns the singular or the plural value, depending on the provided item count. Can be given an explicit plural argument, or will delegate to StringTools#pluralize.
|
357
357
|
|
358
|
-
IntegerTools.pluralize 4, 'light'
|
358
|
+
IntegerTools.pluralize 4, 'light'
|
359
359
|
#=> 'lights'
|
360
360
|
|
361
|
+
IntegerTools.pluralize 3, 'cow', 'kine'
|
362
|
+
#=> 'kine'
|
363
|
+
|
361
364
|
#### `#romanize`
|
362
365
|
|
363
366
|
Represents an integer between 1 and 4999 (inclusive) as a Roman numeral.
|
@@ -664,6 +667,73 @@ Converts a mixed-case string expression to a lowercase, underscore separated str
|
|
664
667
|
|
665
668
|
Common objects or patterns that are useful across projects but are larger than or do not fit the functional paradigm of the tools.* pattern.
|
666
669
|
|
670
|
+
### Configuration
|
671
|
+
|
672
|
+
require 'sleeping_king_studios/tools/toolbox/configuration'
|
673
|
+
|
674
|
+
Provides a simple DSL for defining configuration objects, which can be populated via hashes or data objects (such as a Rails configuration object).
|
675
|
+
|
676
|
+
class MyGemConfig < SleepingKingStudios::Tools::Toolbox::Configuration
|
677
|
+
option :template_dir
|
678
|
+
|
679
|
+
namespace :serialization do
|
680
|
+
option :format, :default => :json, :enum => [:json, :xml, :yaml]
|
681
|
+
end # namespace
|
682
|
+
end # class
|
683
|
+
|
684
|
+
# Initialize with a hash.
|
685
|
+
hsh = YAML.load(File.read 'path/to/config.yml')
|
686
|
+
config = MyGemConfig.new(hsh)
|
687
|
+
|
688
|
+
# Initialize with a data object.
|
689
|
+
klass = Struct.new(:template_dir)
|
690
|
+
data = klass.new('path/to/templates')
|
691
|
+
config = MyGemConfig.new(data)
|
692
|
+
|
693
|
+
# Retrieve data by calling methods or using hash syntax. All of the
|
694
|
+
# following will return the configured value:
|
695
|
+
config.serialization.format
|
696
|
+
config[:serialization][:format]
|
697
|
+
config['serialization']['format']
|
698
|
+
config.dig(:serialization, :format)
|
699
|
+
config.fetch(:serialization', {}).fetch(:format, :json)
|
700
|
+
|
701
|
+
#### `::namespace`
|
702
|
+
|
703
|
+
Defines an inner namespace for the configuration, which will itself be an instance of Configuration. Can be nested to any depth:
|
704
|
+
|
705
|
+
class MyGemConfig < SleepingKingStudios::Tools::Toolbox::Configuration
|
706
|
+
namespace :weapons do
|
707
|
+
namespace :swords do
|
708
|
+
namespace :upgrades do
|
709
|
+
option :hilts
|
710
|
+
|
711
|
+
option :tangs
|
712
|
+
end # namespace
|
713
|
+
end # namespace
|
714
|
+
end # namespace
|
715
|
+
end # class
|
716
|
+
|
717
|
+
config.weapons.swords.upgrades
|
718
|
+
#=> a Configuration instance, with options #hilts and #tangs.
|
719
|
+
|
720
|
+
#### `::option`
|
721
|
+
|
722
|
+
Defines an option, which creates an accessor and mutator method for the property. Can configure a :default (can be a value, a Proc, or the name of a
|
723
|
+
method) and/or allowable values via the :enum option.
|
724
|
+
|
725
|
+
class MyGemConfig < SleepingKingStudios::Tools::Toolbox::Configuration
|
726
|
+
option :max_level, :default => 20
|
727
|
+
|
728
|
+
option :class, :enum => %(warrior ranger elementalist monk)
|
729
|
+
end # class
|
730
|
+
|
731
|
+
config.max_level
|
732
|
+
# Returns 20 if no configured value is set.
|
733
|
+
|
734
|
+
config.class = 'necromancer'
|
735
|
+
# Raises an error.
|
736
|
+
|
667
737
|
### ConstantMap
|
668
738
|
|
669
739
|
require 'sleeping_king_studios/tools/toolbox/constant_map'
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# lib/sleeping_king_studios/tools/integer_tools.rb
|
2
2
|
|
3
3
|
require 'sleeping_king_studios/tools'
|
4
|
+
require 'sleeping_king_studios/tools/string_tools'
|
4
5
|
|
5
6
|
module SleepingKingStudios::Tools
|
6
7
|
# Tools for working with integers.
|
@@ -88,7 +89,9 @@ module SleepingKingStudios::Tools
|
|
88
89
|
#
|
89
90
|
# @return [String] The single form if count == 1; otherwise the plural
|
90
91
|
# form.
|
91
|
-
def pluralize count, single, plural
|
92
|
+
def pluralize count, single, plural = nil
|
93
|
+
plural ||= StringTools.pluralize(single)
|
94
|
+
|
92
95
|
1 == count ? single : plural
|
93
96
|
end # method pluralize
|
94
97
|
|
@@ -0,0 +1,194 @@
|
|
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
|
+
define_namespace namespace_name, &block
|
13
|
+
end # method namespace
|
14
|
+
|
15
|
+
# Defines an option for the configuration object.
|
16
|
+
def option option_name, allow_nil: false, default: DEFAULT_OPTION, enum: nil
|
17
|
+
options = {
|
18
|
+
:allow_nil => allow_nil,
|
19
|
+
:default => default,
|
20
|
+
:enum => enum
|
21
|
+
} # end hash
|
22
|
+
|
23
|
+
define_accessor option_name, options
|
24
|
+
define_mutator option_name, options
|
25
|
+
end # class method option
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def define_accessor option_name, options
|
30
|
+
define_method option_name do
|
31
|
+
__get_value__(option_name, options)
|
32
|
+
end # method option_name
|
33
|
+
end # method define_accessor
|
34
|
+
|
35
|
+
def define_mutator option_name, options
|
36
|
+
writer_name = :"#{option_name}="
|
37
|
+
|
38
|
+
define_method writer_name do |value|
|
39
|
+
__set_value__(option_name, value, options)
|
40
|
+
end # method option_name=
|
41
|
+
end # method define_mutator
|
42
|
+
|
43
|
+
def define_namespace namespace_name, &block
|
44
|
+
define_method namespace_name do
|
45
|
+
if instance_variable_defined?(:"@#{namespace_name}")
|
46
|
+
return instance_variable_get(:"@#{namespace_name}")
|
47
|
+
end # if
|
48
|
+
|
49
|
+
data = __get_value__(namespace_name, :default => Object.new)
|
50
|
+
config =
|
51
|
+
SleepingKingStudios::Tools::Toolbox::Configuration.new(data, &block)
|
52
|
+
|
53
|
+
config.__root_namespace__ = __root_namespace__ || self
|
54
|
+
|
55
|
+
instance_variable_set(:"@#{namespace_name}", config)
|
56
|
+
|
57
|
+
config
|
58
|
+
end # method namespace_name
|
59
|
+
end # method define_namespace
|
60
|
+
end # module
|
61
|
+
extend ClassMethods
|
62
|
+
|
63
|
+
DEFAULT_OPTION = ClassMethods::DEFAULT_OPTION
|
64
|
+
|
65
|
+
# @param data [Hash, Object] The data source used to populate configuration
|
66
|
+
# values. Can be a Hash or a data object. If the data source is nil, or no
|
67
|
+
# data source is given, values will be set to their respective defaults.
|
68
|
+
def initialize data = nil
|
69
|
+
@__data__ = __objectify_data__(data)
|
70
|
+
@__root_namespace__ = self
|
71
|
+
|
72
|
+
yield(singleton_class) if block_given?
|
73
|
+
end # constructor
|
74
|
+
|
75
|
+
def [] key
|
76
|
+
send(key) if respond_to?(key)
|
77
|
+
end # method []
|
78
|
+
|
79
|
+
def []= key, value
|
80
|
+
send(:"#{key}=", value)
|
81
|
+
end # method []=
|
82
|
+
|
83
|
+
def dig *keys
|
84
|
+
keys.reduce(self) do |hsh, key|
|
85
|
+
value = hsh[key]
|
86
|
+
|
87
|
+
return value if value.nil?
|
88
|
+
|
89
|
+
value
|
90
|
+
end # reduce
|
91
|
+
end # method dig
|
92
|
+
|
93
|
+
def fetch key, default = DEFAULT_OPTION
|
94
|
+
return send(key) if respond_to?(key)
|
95
|
+
|
96
|
+
return default unless default == DEFAULT_OPTION
|
97
|
+
|
98
|
+
return yield if block_given?
|
99
|
+
|
100
|
+
raise KeyError, 'key not found'
|
101
|
+
end # method fetch
|
102
|
+
|
103
|
+
protected
|
104
|
+
|
105
|
+
attr_accessor :__root_namespace__
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
attr_reader :__data__
|
110
|
+
|
111
|
+
def __blank_value__ value
|
112
|
+
value.nil? || (value.respond_to?(:empty?) && value.empty?)
|
113
|
+
end # method __blank_value__
|
114
|
+
|
115
|
+
def __evaluate_default__ default
|
116
|
+
default.is_a?(Proc) ? __root_namespace__.instance_exec(&default) : default
|
117
|
+
end # method __evaluate_default__
|
118
|
+
|
119
|
+
def __get_value__ name, options
|
120
|
+
default_given = options[:default] != DEFAULT_OPTION
|
121
|
+
|
122
|
+
if __data__.respond_to?(name)
|
123
|
+
value = __data__.send name
|
124
|
+
|
125
|
+
if value.nil? && default_given
|
126
|
+
value = __evaluate_default__(options[:default])
|
127
|
+
end # if
|
128
|
+
|
129
|
+
__validate_value__ value, options
|
130
|
+
|
131
|
+
value
|
132
|
+
elsif instance_variable_defined?(:"@#{name}")
|
133
|
+
# Recall values locally if data source is immutable.
|
134
|
+
return instance_variable_get(:"@#{name}")
|
135
|
+
elsif default_given
|
136
|
+
value = __evaluate_default__(options[:default])
|
137
|
+
|
138
|
+
__validate_value__ value, options
|
139
|
+
|
140
|
+
value
|
141
|
+
else
|
142
|
+
__validate_value__ nil, options
|
143
|
+
|
144
|
+
nil
|
145
|
+
end # if-else
|
146
|
+
end # method __get_value__
|
147
|
+
|
148
|
+
def __objectify_data__ data
|
149
|
+
return data unless data.is_a?(Hash)
|
150
|
+
|
151
|
+
return Object.new if data.empty?
|
152
|
+
|
153
|
+
obj = Struct.new(*data.keys).new
|
154
|
+
|
155
|
+
data.each do |key, value|
|
156
|
+
val = value.is_a?(Hash) ? __objectify_data__(value) : value
|
157
|
+
|
158
|
+
obj.send :"#{key}=", val
|
159
|
+
end # each
|
160
|
+
|
161
|
+
obj
|
162
|
+
end # method __objectify_data__
|
163
|
+
|
164
|
+
def __set_value__ name, value, options
|
165
|
+
writer_name = :"#{name}="
|
166
|
+
|
167
|
+
__validate_value__ value, options
|
168
|
+
|
169
|
+
if __data__.respond_to?(writer_name)
|
170
|
+
__data__.send(writer_name, value)
|
171
|
+
else
|
172
|
+
# Store values locally if data source is immutable.
|
173
|
+
instance_variable_set(:"@#{name}", value)
|
174
|
+
end # if-else
|
175
|
+
end # method __set_value__
|
176
|
+
|
177
|
+
def __validate_value__ value, options
|
178
|
+
return if __blank_value__(value) && options[:allow_nil]
|
179
|
+
|
180
|
+
if options[:enum] && !options[:enum].include?(value)
|
181
|
+
array_tools = ::SleepingKingStudios::Tools::ArrayTools
|
182
|
+
valid_options =
|
183
|
+
array_tools.
|
184
|
+
humanize_list(
|
185
|
+
options[:enum].map(&:inspect),
|
186
|
+
:last_separator => ' or '
|
187
|
+
) # end humanize_list
|
188
|
+
|
189
|
+
raise RuntimeError,
|
190
|
+
"expected option to be #{valid_options}, but was #{value.inspect}"
|
191
|
+
end # if
|
192
|
+
end # method __validate_value__
|
193
|
+
end # class
|
194
|
+
end # module
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sleeping_king_studios-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.0.
|
4
|
+
version: 0.7.0.beta.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob "Merlin" Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
11
|
+
date: 2017-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '12.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '12.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- lib/sleeping_king_studios/tools/string_tools/plural_inflector.rb
|
105
105
|
- lib/sleeping_king_studios/tools/toolbelt.rb
|
106
106
|
- lib/sleeping_king_studios/tools/toolbox.rb
|
107
|
+
- lib/sleeping_king_studios/tools/toolbox/configuration.rb
|
107
108
|
- lib/sleeping_king_studios/tools/toolbox/constant_map.rb
|
108
109
|
- lib/sleeping_king_studios/tools/toolbox/delegator.rb
|
109
110
|
- lib/sleeping_king_studios/tools/toolbox/mixin.rb
|