config_hash 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 73f82976e9390c9a3415a6eb9184d8b198a4593f
4
+ data.tar.gz: 3802b8e1088be490850e06034d5e8ffa7a8de439
5
+ SHA512:
6
+ metadata.gz: b3012332aeb6d10baf6d1f8183337dce40815a9428cf91b69c0eb25902a0cff794eaac1e9a2e11d01d60cb7bb66c16bca065f74db8b25b0c167e7ed42555a960
7
+ data.tar.gz: 17c079178938569abf148d7292b6a91e1f2d85719e30b7f90a0d68cdcdb70abc28d09dc2b1bfe5b3a4e006d2937dfaf604be0fdff1b8ccda7399b2b2b536cbe3
@@ -0,0 +1,19 @@
1
+ class ConfigHash < Hash
2
+ class Processors
3
+ class << self
4
+ def constantize(v)
5
+ case v
6
+ when Symbol then v.to_s.start_with?(':') ? const_fetch(":#{v}", v) : v
7
+ when String then v.start_with?('::') ? const_fetch(v, v) : v
8
+ else v
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def const_fetch(value, default)
15
+ Object.const_defined?(value) ? Object.const_get(value) : default
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,87 @@
1
+ require 'config_hash/processors'
2
+
3
+ class ConfigHash < Hash
4
+ def initialize(hash, default=nil, **options, &default_block)
5
+ unless hash.kind_of?(Hash)
6
+ raise ArgumentError.new("first argument must be a hash!")
7
+ end
8
+
9
+ @freeze = options.fetch(:freeze, true)
10
+ @processors = options.fetch(:processors, [])
11
+ if !(@processors.is_a?(Array) && @processors.all? { |p| p.is_a?(Proc) || p.is_a?(Method) })
12
+ raise ArgumentError.new("processors must be a list of callables!")
13
+ end
14
+ # allow default processors to be assigned by those method names specially.
15
+ ConfigHash::Processors.methods(false).each do |proc|
16
+ @processors << ConfigHash::Processors.method(proc) if options[proc]
17
+ end
18
+
19
+ super(default, &default_block)
20
+
21
+ # recursively construct this hash from the passed in hash.
22
+ hash.each do |key, value|
23
+ key = key.is_a?(String) ? key.to_sym : key # force strings to symbols
24
+ self[construct(key)] = construct(value)
25
+
26
+ if key.is_a? Symbol # allow '.' notation for symbol keys.
27
+ self.instance_eval("def #{key}; process(self[:#{key}]); end")
28
+ end
29
+ end
30
+
31
+ self.freeze if @freeze
32
+ end
33
+
34
+ def [](key, in_process=false)
35
+ key = key.is_a?(String) ? key.to_sym : key
36
+ return super(key) if in_process
37
+
38
+ process(self.send(:[], key, true)) # make sure to process reutrn values
39
+ end
40
+
41
+ def method_missing(method, *args)
42
+ return super(method, *args) if @freeze
43
+
44
+ # if we're not freezing, we can allow assignment and expect nil results.
45
+ if method =~ /^(.*)=$/ && args.length == 1
46
+ key = method.to_s.tr('=', '').to_sym
47
+ self[key] = args[0]
48
+ self.instance_eval("def #{key}; process(self[:#{key}]); end")
49
+ else
50
+ nil # it's a non-defined value.
51
+ end
52
+ end
53
+
54
+ def delete(key, &blk)
55
+ return super(key, &blk) if @freeze
56
+
57
+ key = key.is_a?(String) ? key.to_sym : key
58
+ instance_eval("undef #{key}") if respond_to?(key)
59
+ super(key, &blk)
60
+ end
61
+
62
+ private
63
+
64
+ def process(value)
65
+ @processors.reduce(value) { |modified, proc| proc.call(modified) }
66
+ end
67
+
68
+ def construct(value)
69
+ case value
70
+ when ConfigHash then value
71
+ when Hash then ConfigHash.new(
72
+ value,
73
+ value.default,
74
+ freeze: @freeze, processors: @processors,
75
+ &value.default_proc
76
+ )
77
+ when Array then dup_if_appropriate(value).map { |sv| construct(sv) }
78
+ else dup_if_appropriate(value)
79
+ end.tap { |calced| calced.freeze if @freeze }
80
+ end
81
+
82
+ def dup_if_appropriate(v)
83
+ # if it is a class, module, or proc, DO NOT DUP
84
+ return v if [Class, Module, Proc].any? { |kls| v.instance_of?(kls) }
85
+ v.dup rescue v # on symbol, integer just return value
86
+ end
87
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: config_hash
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Zach Lome
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-12-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.4'
41
+ description: A safe hash that can process values and use dot notation.
42
+ email:
43
+ - zslome@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/config_hash.rb
49
+ - lib/config_hash/processors.rb
50
+ homepage: https://github.com/kuraiou/config_hash
51
+ licenses:
52
+ - MIT
53
+ metadata: {}
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 2.4.5.1
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: a hash built for configurations.
74
+ test_files: []
75
+ has_rdoc: