README.md in config_mapper-1.0.0 vs README.md in config_mapper-1.1.0
- old
+ new
@@ -18,11 +18,11 @@
end
class State
def initialize
- @position = Position.new
+ @position = Position.new
end
attr_reader :position
attr_accessor :orientation
@@ -35,22 +35,22 @@
```ruby
config_data = {
"orientation" => "North",
"position" => {
- "x" => 2,
- "y" => 4
+ "x" => 2,
+ "y" => 4
}
}
```
ConfigMapper will help you out:
```ruby
require 'config_mapper'
-errors = ConfigMapper.set(config_data, state)
+errors = ConfigMapper.configure_with(config_data, state)
state.orientation #=> "North"
state.position.x #=> 2
```
It can even populate Hashes of objects, e.g.
@@ -61,34 +61,125 @@
config_data = {
"fred" => { "x" => 2, "y" => 4 },
"mary" => { "x" => 3, "y" => 5 }
}
-ConfigMapper.set(config_data, positions)
+ConfigMapper.configure_with(config_data, positions)
positions["fred"].x #=> 2
positions["mary"].y #=> 5
```
+### Target object
+
+Given
+
+```ruby
+ConfigMapper.configure_with(config_data, target)
+```
+
+the `target` object is expected provide accessor-methods corresponding
+to the attributes that you want to make configurable. For example, with:
+
+```ruby
+config_data = {
+ "orientation" => "North",
+ "position" => { "x" => 2, "y" => 4 }
+}
+```
+
+it should have a `orientiation=` method, and a `position` method that
+returns a `Position` object, which should in turn have `x=` and `y=`
+methods.
+
+ConfigMapper cannot and will not _create_ objects for you.
+
### Errors
-`ConfigMapper.set` returns a Hash of errors encountered while mapping data
-onto objects. The errors are Exceptions (typically ArgumentError or NoMethodError),
-keyed by a Array representing the path to the offending data. e.g.
+`ConfigMapper.configure_with` returns a Hash of errors encountered while mapping data onto objects. The errors are Exceptions (typically ArgumentError or NoMethodError), keyed by the path to the offending data. e.g.
```ruby
config_data = {
"position" => {
"bogus" => "flibble"
}
}
-errors = ConfigMapper.set(config_data, state)
-errors #=> { ["position", "bogus"] => #<NoMethodError> }
+errors = ConfigMapper.configure_with(config_data, state)
+errors #=> { ".position.bogus" => #<NoMethodError> }
```
+## ConfigStruct
+
+ConfigMapper works pretty well with plain old Ruby objects, but we
+provide a base-class, `ConfigMapper::ConfigStruct`, with a DSL that
+makes it even easier to declare configuration data-structures.
+
+```ruby
+require "config_mapper/config_struct"
+
+class State < ConfigMapper::ConfigStruct
+
+ component :position do
+ attribute(:x) { |arg| Integer(arg) }
+ attribute(:y) { |arg| Integer(arg) }
+ end
+
+ attribute :orientation
+
+end
+```
+
+By default, declared attributes are assumed to be mandatory. The
+`ConfigStruct#config_errors` method returns errors for each unset mandatory
+attribute.
+
+```ruby
+state = State.new
+state.position.x = 3
+state.position.y = 4
+state.config_errors
+#=> { ".orientation" => "no value provided" }
+```
+
+`#config_errors` can be overridden to provide custom semantic validation.
+
+Attributes can be given default values. Provide an explicit `nil` default to
+mark an attribute as optional, e.g.
+
+```ruby
+class Address < ConfigMapper::ConfigStruct
+
+ attribute :host
+ attribute :port, :default => 80
+ attribute :path, :default => nil
+
+end
+```
+
+`ConfigStruct#configure_with` maps data into the object, and combines mapping errors and
+semantic errors (returned by `#config_errors`) into a single Hash:
+
+```ruby
+data = {
+ "position" => { "x" => 3, "y" => "fore" },
+ "bogus" => "foobar"
+}
+state.configure_with(data)
+#=> {
+#=> ".orientation" => "no value provided",
+#=> ".position.y" => #<ArgumentError: invalid value for Integer(): "fore">,
+#=> ".bogus" => #<NoMethodError: undefined method `bogus=' for #<State:0x007fc8e9b12a60>>
+#=> }
+```
+
## License
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
## Contributing
It's on GitHub; you know the drill.
+
+## See also
+
+* [ConfigHound](https://github.com/mdub/config_hound) is a great way to
+ load raw config-data, before throwing it to ConfigMapper.