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: 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