config_mapper 0.2.0 → 1.0.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: 7d643ab8607c785459650363209b078699513bd5
4
- data.tar.gz: 1a4ef25c93114686800bc0cf82dc13c7736e448a
3
+ metadata.gz: a927800ba901de2ba648d012936b19b591d24c5e
4
+ data.tar.gz: c93aace56fd8a8a9662f547ef72e5c5f1d0a9396
5
5
  SHA512:
6
- metadata.gz: f323e289fbdc9d7c1f6d8f8c436e7d62bb68b98b35268e210a0f4bc0568a6f69549e7c9fb54c38173ce3b84f797c5dba732a7ab80239b0ccaf4d046bbbca5278
7
- data.tar.gz: 7fcb8808ee09efb2a932ab5b8f4dc74f49405b12438c50428d2506667a7f5862b31b2a771e08964f49ed8f9d8988355748328c407a80eb376f5ff40ec5a19daf
6
+ metadata.gz: 5da46b8fb08d97ccfe985cb2a0da607de151f2d70167c0edd03c66a5771d9e5e24fda1a2183e58552103aa451d9016c8d45991ba87d1c3a47fc0b3e1e7b0e8e1
7
+ data.tar.gz: 3b40a4cc5c9049f681bbeaf17cacad8817dffd48c53b5ec46314a1e49f0410053f335feee942357b8265dbbb660468751f2de1657994af68bca3b4514399faaf
data/README.md CHANGED
@@ -6,74 +6,84 @@ ConfigMapper maps configuration data onto Ruby objects.
6
6
 
7
7
  Imagine you have some Ruby objects:
8
8
 
9
- class Position
9
+ ```ruby
10
+ class Position
10
11
 
11
- attr_reader :x
12
- attr_reader :y
12
+ attr_reader :x
13
+ attr_reader :y
13
14
 
14
- def x=(arg); @x = Integer(arg); end
15
- def y=(arg); @y = Integer(arg); end
15
+ def x=(arg); @x = Integer(arg); end
16
+ def y=(arg); @y = Integer(arg); end
16
17
 
17
- end
18
+ end
18
19
 
19
- class State
20
+ class State
20
21
 
21
- def initialize
22
- @position = Position.new
23
- end
22
+ def initialize
23
+ @position = Position.new
24
+ end
24
25
 
25
- attr_reader :position
26
- attr_accessor :orientation
26
+ attr_reader :position
27
+ attr_accessor :orientation
27
28
 
28
- end
29
+ end
29
30
 
30
- state = State.new
31
+ state = State.new
32
+ ```
31
33
 
32
34
  and wish to populate/modify it, based on plain data:
33
35
 
34
- config_data = {
35
- "orientation" => "North",
36
- "position" => {
37
- "x" => 2,
38
- "y" => 4
39
- }
40
- }
36
+ ```ruby
37
+ config_data = {
38
+ "orientation" => "North",
39
+ "position" => {
40
+ "x" => 2,
41
+ "y" => 4
42
+ }
43
+ }
44
+ ```
41
45
 
42
46
  ConfigMapper will help you out:
43
47
 
44
- require 'config_mapper'
48
+ ```ruby
49
+ require 'config_mapper'
45
50
 
46
- errors = ConfigMapper.set(config_data, state)
47
- state.orientation #=> "North"
48
- state.position.x #=> 2
51
+ errors = ConfigMapper.set(config_data, state)
52
+ state.orientation #=> "North"
53
+ state.position.x #=> 2
54
+ ```
49
55
 
50
56
  It can even populate Hashes of objects, e.g.
51
57
 
52
- positions = Hash.new { |h,k| h[k] = Position.new }
58
+ ```ruby
59
+ positions = Hash.new { |h,k| h[k] = Position.new }
53
60
 
54
- config_data = {
55
- "fred" => { "x" => 2, "y" => 4 },
56
- "mary" => { "x" => 3, "y" => 5 }
57
- }
61
+ config_data = {
62
+ "fred" => { "x" => 2, "y" => 4 },
63
+ "mary" => { "x" => 3, "y" => 5 }
64
+ }
58
65
 
59
- ConfigMapper.set(config_data, positions)
60
- positions["fred"].x #=> 2
61
- positions["mary"].y #=> 5
66
+ ConfigMapper.set(config_data, positions)
67
+ positions["fred"].x #=> 2
68
+ positions["mary"].y #=> 5
69
+ ```
62
70
 
63
71
  ### Errors
64
72
 
65
73
  `ConfigMapper.set` returns a Hash of errors encountered while mapping data
66
74
  onto objects. The errors are Exceptions (typically ArgumentError or NoMethodError),
67
- keyed by a dot-delimited path to the offending data. e.g.
68
-
69
- config_data = {
70
- "position" => {
71
- "bogus" => "flibble"
72
- }
73
- }
74
-
75
- errors = ConfigMapper.set(config_data, state)
76
- errors #=> { "position.bogus" => #<NoMethodError> }
75
+ keyed by a Array representing the path to the offending data. e.g.
76
+
77
+ ```ruby
78
+ config_data = {
79
+ "position" => {
80
+ "bogus" => "flibble"
81
+ }
82
+ }
83
+
84
+ errors = ConfigMapper.set(config_data, state)
85
+ errors #=> { ["position", "bogus"] => #<NoMethodError> }
86
+ ```
77
87
 
78
88
  ## License
79
89
 
@@ -1,7 +1,9 @@
1
+ require "config_mapper/attribute_sink"
2
+
1
3
  # Supports marshalling of plain-old data (e.g. loaded from
2
4
  # YAML files) onto strongly-typed objects.
3
5
  #
4
- class ConfigMapper
6
+ module ConfigMapper
5
7
 
6
8
  # Attempt to set attributes on a target object.
7
9
  #
@@ -13,85 +15,9 @@ class ConfigMapper
13
15
  # @return [Hash] exceptions encountered
14
16
  #
15
17
  def self.set(data, target)
16
- mapper = new(target)
18
+ mapper = AttributeSink.new(target)
17
19
  mapper.set_attributes(data)
18
20
  mapper.errors
19
21
  end
20
22
 
21
- def initialize(target, errors = {})
22
- @target = ObjectAsHash[target]
23
- @errors = errors
24
- end
25
-
26
- attr_reader :target
27
- attr_reader :errors
28
-
29
- # Set multiple attributes from a Hash.
30
- #
31
- def set_attributes(data)
32
- data.each do |key, value|
33
- set_attribute(key, value)
34
- end
35
- end
36
-
37
- private
38
-
39
- # Set a single attribute.
40
- #
41
- def set_attribute(key, value)
42
- if value.is_a?(Hash) && !target[key].nil?
43
- nested_errors = ErrorProxy.new(errors, "#{key}.")
44
- nested_mapper = self.class.new(target[key], nested_errors)
45
- nested_mapper.set_attributes(value)
46
- else
47
- target[key] = value
48
- end
49
- rescue NoMethodError, ArgumentError => e
50
- errors[key] = e
51
- end
52
-
53
- class ObjectAsHash
54
-
55
- def self.[](target)
56
- if target.is_a?(Hash)
57
- target
58
- else
59
- ObjectAsHash.new(target)
60
- end
61
- end
62
-
63
- def initialize(target)
64
- @target = target
65
- end
66
-
67
- def [](key)
68
- @target.public_send(key)
69
- end
70
-
71
- def []=(key, value)
72
- @target.public_send("#{key}=", value)
73
- end
74
-
75
- end
76
-
77
- # Wraps a Hash of errors, injecting prefixes
78
- #
79
- class ErrorProxy
80
-
81
- def initialize(errors, prefix)
82
- @errors = errors
83
- @prefix = prefix
84
- end
85
-
86
- def []=(key, value)
87
- errors[prefix + key] = value
88
- end
89
-
90
- private
91
-
92
- attr_reader :errors
93
- attr_reader :prefix
94
-
95
- end
96
-
97
23
  end
@@ -0,0 +1,42 @@
1
+ require "config_mapper/error_proxy"
2
+ require "config_mapper/object_as_hash"
3
+
4
+ module ConfigMapper
5
+
6
+ # Sets attributes on an object, collecting errors
7
+ #
8
+ class AttributeSink
9
+
10
+ def initialize(target, errors = {})
11
+ @target = ObjectAsHash[target]
12
+ @errors = errors
13
+ end
14
+
15
+ attr_reader :target
16
+ attr_reader :errors
17
+
18
+ # Set multiple attributes from a Hash.
19
+ #
20
+ def set_attributes(data)
21
+ data.each do |key, value|
22
+ set_attribute(key, value)
23
+ end
24
+ end
25
+
26
+ # Set a single attribute.
27
+ #
28
+ def set_attribute(key, value)
29
+ if value.is_a?(Hash) && !target[key].nil?
30
+ nested_errors = ErrorProxy.new(errors, [key])
31
+ nested_mapper = self.class.new(target[key], nested_errors)
32
+ nested_mapper.set_attributes(value)
33
+ else
34
+ target[key] = value
35
+ end
36
+ rescue NoMethodError, ArgumentError => e
37
+ errors[[key]] = e
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,23 @@
1
+ module ConfigMapper
2
+
3
+ # Wraps a Hash of errors, injecting prefixes
4
+ #
5
+ class ErrorProxy
6
+
7
+ def initialize(errors, prefix)
8
+ @errors = errors
9
+ @prefix = prefix
10
+ end
11
+
12
+ def []=(key, value)
13
+ errors[prefix + key] = value
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :errors
19
+ attr_reader :prefix
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,29 @@
1
+ module ConfigMapper
2
+
3
+ # Wrap an object to make it look more like a Hash.
4
+ #
5
+ class ObjectAsHash
6
+
7
+ def self.[](target)
8
+ if target.is_a?(Hash)
9
+ target
10
+ else
11
+ ObjectAsHash.new(target)
12
+ end
13
+ end
14
+
15
+ def initialize(target)
16
+ @target = target
17
+ end
18
+
19
+ def [](key)
20
+ @target.public_send(key)
21
+ end
22
+
23
+ def []=(key, value)
24
+ @target.public_send("#{key}=", value)
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -1,5 +1,5 @@
1
- class ConfigMapper
1
+ module ConfigMapper
2
2
 
3
- VERSION = "0.2.0"
3
+ VERSION = "1.0.0"
4
4
 
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: config_mapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-04 00:00:00.000000000 Z
11
+ date: 2015-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -69,6 +69,9 @@ files:
69
69
  - Rakefile
70
70
  - config_mapper.gemspec
71
71
  - lib/config_mapper.rb
72
+ - lib/config_mapper/attribute_sink.rb
73
+ - lib/config_mapper/error_proxy.rb
74
+ - lib/config_mapper/object_as_hash.rb
72
75
  - lib/config_mapper/version.rb
73
76
  homepage: https://github.com/mdub/config_mapper
74
77
  licenses:
@@ -90,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
93
  version: '0'
91
94
  requirements: []
92
95
  rubyforge_project:
93
- rubygems_version: 2.4.5
96
+ rubygems_version: 2.4.8
94
97
  signing_key:
95
98
  specification_version: 4
96
99
  summary: Maps config data onto plain old objects