config_mapper 1.1.1 → 1.2.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: 8ef98e7511cb9930fbda99d63064fc49e7634c25
4
- data.tar.gz: b22f51b95e5248c20f91f353fddbd304b0a6ed26
3
+ metadata.gz: 2b50eb5ad224762a6891a4bb75077f7cf24dd19a
4
+ data.tar.gz: ee8a164e3478984a0793df79345af4bbaa67054a
5
5
  SHA512:
6
- metadata.gz: eafa293ee0625f4c8d330f00f59a2618affeff679d5189e24087734cd4601f45bf32c0f7fdfaf380e643c7a9a0762b34581a6efc2f918eae237fc918e35b02e8
7
- data.tar.gz: f59d8a5d5a27502ae8bb457aa083a14be7d2f35be5af3a2550d2347142ab452bfb76b25f17f343e6fd193ea267cdcadb8049853366ebba2b21699aa37c1b1cef
6
+ metadata.gz: 4f16a33006c27cc333e7bed302052b372728755a900103f42781f116639cde0a6af56c598d2335677bba75b031ed49e0c3c70162d00c5bcce0cce0085d80a302
7
+ data.tar.gz: 0ef76dfb3980e16c6e671e5a055e4deb546408c1515f7675da6bccf43d10357d4432b7c43262f8767f7b2017e42765e869ca44823c502480661098b5cde93b52
data/.rubocop.yml CHANGED
@@ -44,6 +44,9 @@ Style/FileName:
44
44
  Style/HashSyntax:
45
45
  EnforcedStyle: hash_rockets
46
46
 
47
+ Style/Lambda:
48
+ Enabled: false
49
+
47
50
  Style/StringLiterals:
48
51
  EnforcedStyle: double_quotes
49
52
 
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # ConfigMapper
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/config_mapper.png)](http://badge.fury.io/rb/config_mapper)
4
+ [![Build Status](https://secure.travis-ci.org/mdub/config_mapper.png?branch=master)](http://travis-ci.org/mdub/config_mapper)
5
+
3
6
  ConfigMapper maps configuration data onto Ruby objects.
4
7
 
5
8
  ## Usage
@@ -119,8 +122,8 @@ require "config_mapper/config_struct"
119
122
  class State < ConfigMapper::ConfigStruct
120
123
 
121
124
  component :position do
122
- attribute(:x) { |arg| Integer(arg) }
123
- attribute(:y) { |arg| Integer(arg) }
125
+ attribute :x
126
+ attribute :y
124
127
  end
125
128
 
126
129
  attribute :orientation
@@ -128,35 +131,48 @@ class State < ConfigMapper::ConfigStruct
128
131
  end
129
132
  ```
130
133
 
131
- By default, declared attributes are assumed to be mandatory. The
132
- `ConfigStruct#config_errors` method returns errors for each unset mandatory
133
- attribute.
134
+ `ConfigStruct#config_errors` returns errors for each unset mandatory attribute.
134
135
 
135
136
  ```ruby
136
137
  state = State.new
137
138
  state.position.x = 3
138
139
  state.position.y = 4
139
140
  state.config_errors
140
- #=> { ".orientation" => "no value provided" }
141
+ #=> { ".orientation" => #<ConfigMapper::ConfigStruct::NoValueProvided: no value provided> }
141
142
  ```
142
143
 
143
144
  `#config_errors` can be overridden to provide custom semantic validation.
144
145
 
145
- Attributes can be given default values. Provide an explicit `nil` default to
146
- mark an attribute as optional, e.g.
146
+ Attributes can be given default values. Specify a default value of `nil` to mark an attribute as optional, e.g.
147
147
 
148
148
  ```ruby
149
149
  class Address < ConfigMapper::ConfigStruct
150
-
151
150
  attribute :host
152
151
  attribute :port, :default => 80
153
152
  attribute :path, :default => nil
153
+ end
154
+ ```
155
+
156
+ If a block is provided when an `attribute` is declared, it is used to validate values when they are set, and/or coerce them to a canonical type. The block should raise `ArgumentError` to indicate an invalid value.
157
+
158
+ ```ruby
159
+ class Server < ConfigMapper::ConfigStruct
160
+
161
+ attribute :host do |arg|
162
+ unless arg =~ /^\w+(\.\w+)+$/
163
+ raise ArgumentError, "invalid hostname: #{arg}"
164
+ end
165
+ arg
166
+ end
167
+
168
+ attribute :port do |arg|
169
+ Integer(arg)
170
+ end
154
171
 
155
172
  end
156
173
  ```
157
174
 
158
- `ConfigStruct#configure_with` maps data into the object, and combines mapping errors and
159
- semantic errors (returned by `#config_errors`) into a single Hash:
175
+ `ConfigStruct#configure_with` maps data into the object, and combines mapping errors and semantic errors (returned by `#config_errors`) into a single Hash:
160
176
 
161
177
  ```ruby
162
178
  data = {
@@ -15,6 +15,14 @@ module ConfigMapper
15
15
  @entries[key] ||= @entry_type.call
16
16
  end
17
17
 
18
+ def to_h
19
+ {}.tap do |result|
20
+ @entries.each do |key, value|
21
+ result[key] = value.to_h
22
+ end
23
+ end
24
+ end
25
+
18
26
  extend Forwardable
19
27
 
20
28
  def_delegators :@entries, :each, :empty?, :keys, :map, :size
@@ -21,21 +21,24 @@ module ConfigMapper
21
21
  # @options options [String] :default (nil) default value
22
22
  # @yield type-coercion block
23
23
  #
24
- def attribute(name, options = {}, &coerce_block)
24
+ def attribute(name, options = {})
25
25
  name = name.to_sym
26
+ required = true
27
+ default_value = nil
26
28
  if options.key?(:default)
27
29
  default_value = options.fetch(:default).freeze
28
- attribute_initializers[name] = proc { default_value }
29
- else
30
- required_attributes << name
30
+ required = false if default_value.nil?
31
31
  end
32
+ attribute_initializers[name] = proc { default_value }
33
+ required_attributes << name if required
32
34
  attr_reader(name)
33
- if coerce_block
34
- define_method("#{name}=") do |arg|
35
- instance_variable_set("@#{name}", coerce_block.call(arg))
35
+ define_method("#{name}=") do |value|
36
+ if value.nil?
37
+ raise NoValueProvided if required
38
+ else
39
+ value = yield(value) if block_given?
36
40
  end
37
- else
38
- attr_writer(name)
41
+ instance_variable_set("@#{name}", value)
39
42
  end
40
43
  end
41
44
 
@@ -125,6 +128,22 @@ module ConfigMapper
125
128
  config_errors.merge(errors)
126
129
  end
127
130
 
131
+ # Return the configuration as a Hash.
132
+ #
133
+ # @return [Hash] serializable config data
134
+ #
135
+ def to_h
136
+ {}.tap do |result|
137
+ self.class.attribute_initializers.keys.each do |attr_name|
138
+ value = send(attr_name)
139
+ if value && value.respond_to?(:to_h) && !value.is_a?(Array)
140
+ value = value.to_h
141
+ end
142
+ result[attr_name.to_s] = value
143
+ end
144
+ end
145
+ end
146
+
128
147
  private
129
148
 
130
149
  def components
@@ -140,13 +159,19 @@ module ConfigMapper
140
159
  end
141
160
  end
142
161
 
143
- NOT_SET = "no value provided".freeze
162
+ class NoValueProvided < ArgumentError
163
+
164
+ def initialize
165
+ super("no value provided")
166
+ end
167
+
168
+ end
144
169
 
145
170
  def missing_required_attribute_errors
146
171
  {}.tap do |errors|
147
172
  self.class.required_attributes.each do |name|
148
- unless instance_variable_defined?("@#{name}")
149
- errors[".#{name}"] = NOT_SET
173
+ if instance_variable_get("@#{name}").nil?
174
+ errors[".#{name}"] = NoValueProvided.new
150
175
  end
151
176
  end
152
177
  end
@@ -1,5 +1,5 @@
1
1
  module ConfigMapper
2
2
 
3
- VERSION = "1.1.1"
3
+ VERSION = "1.2.0".freeze
4
4
 
5
5
  end
data/lib/config_mapper.rb CHANGED
@@ -25,7 +25,7 @@ module ConfigMapper
25
25
  mapper_for(target).configure_with(data)
26
26
  end
27
27
 
28
- alias_method :set, :configure_with
28
+ alias set configure_with
29
29
 
30
30
  def mapper_for(target)
31
31
  if target.is_a?(Hash) || target.is_a?(ConfigMapper::ConfigDict)
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: 1.1.1
4
+ version: 1.2.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: 2016-02-29 00:00:00.000000000 Z
11
+ date: 2016-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -96,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
96
  version: '0'
97
97
  requirements: []
98
98
  rubyforge_project:
99
- rubygems_version: 2.5.2
99
+ rubygems_version: 2.5.1
100
100
  signing_key:
101
101
  specification_version: 4
102
102
  summary: Maps config data onto plain old objects