lib/configurable/delegate_hash.rb in configurable-0.4.2 vs lib/configurable/delegate_hash.rb in configurable-0.5.0

- old
+ new

@@ -58,14 +58,14 @@ end # Binds self to the specified receiver. Delegate values are removed from # store and sent to their writer on receiver. If the store has no value # for a delegate key, the delegate default value will be used. - def bind(receiver) + def bind(receiver, rebind=false) raise ArgumentError, "receiver cannot be nil" if receiver == nil - if bound? + if bound? && !rebind if @receiver == receiver return(self) else raise ArgumentError, "already bound to: #{@receiver}" end @@ -150,14 +150,22 @@ another.respond_to?(:to_hash) && to_hash == another.to_hash end # Returns self as a hash. Any DelegateHash values are recursively # hashified, to account for nesting. - def to_hash + def to_hash(&block) hash = {} each_pair do |key, value| - hash[key] = value.kind_of?(DelegateHash) ? value.to_hash : value + if value.kind_of?(DelegateHash) + value = value.to_hash(&block) + end + + if block_given? + yield(hash, key, value) + else + hash[key] = value + end end hash end # Overrides default inspect to show the to_hash values. @@ -176,18 +184,33 @@ protected # helper to map delegate values from source to the receiver def map(source) # :nodoc: + source_values = {} + source.each_key do |key| + if delegate = delegates[key] + if source_values.has_key?(delegate) + key = delegates.keys.find {|k| delegates[k] == delegate } + raise "multiple values mapped to #{key.inspect}" + end + + source_values[delegate] = source.delete(key) + end + end + delegates.each_pair do |key, delegate| # map the value; if no value is set in the source then use the # delegate default. if map_default is false, then simply skip... # this ensures each config is initialized to a value when bound # UNLESS map_default is set (indicating manual initialization) value = case - when source.has_key?(key) then source.delete(key) - when delegate[:set_default, true] then delegate.default - else next + when source_values.has_key?(delegate) + source_values[delegate] + when delegate[:set_default, true] + delegate.default + else + next end receiver.send(delegate.writer, value) end end \ No newline at end of file