sleeping_king_studios-tools 0.7.0.alpha.0 → 0.7.0.beta.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
  SHA1:
3
- metadata.gz: 5f27a979de124657efcdfa2d4b8293b2c8d71458
4
- data.tar.gz: c7a28bce980002ba427a38e491130a29fb29672e
3
+ metadata.gz: c4adaa39941af100f90cca20495186512bb1df63
4
+ data.tar.gz: ebfa9dc2da32771e4e10b5a66d93023995f529ab
5
5
  SHA512:
6
- metadata.gz: 6b229bf6aa673e10662fc71cbeb5b55b0f4c3eaf3d9959dcff67895595b5074e03a61238c35c36f779e545672bb5669d7f08805b46b0360f77d2824741ad5db8
7
- data.tar.gz: 7c0546a0349e2d556976f5356abfc77bb710b6d477f2d4e23d05b422a50d8f6c32fe1a9105bd15e77a98c2895696c0f5dccca6556fe2d0657bdd301a4b0f0664
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', 'lights'
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
@@ -15,7 +15,7 @@ module SleepingKingStudios
15
15
  MAJOR = 0
16
16
  MINOR = 7
17
17
  PATCH = 0
18
- PRERELEASE = :alpha
18
+ PRERELEASE = :beta
19
19
  BUILD = 0
20
20
  end # module
21
21
 
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.alpha.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-03 00:00:00.000000000 Z
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: '10.5'
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: '10.5'
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