lib/configurations/configuration.rb in configurations-1.1.0 vs lib/configurations/configuration.rb in configurations-1.3.0

- old
+ new

@@ -57,25 +57,25 @@ # Method missing gives access for reading and writing to the underlying configuration hash via dot notation # def method_missing(method, *args, &block) property = method.to_s[0..-2].to_sym + value = args.first if _is_writer?(method) && @_writeable && _configurable?(property) - _assert_type!(property, args.first) - @configuration[property] = args.first + _assign!(property, value) elsif !_is_writer?(method) && @_writeable || _configured?(method) @configuration[method] else - super + ::Kernel.send(method, *args, &block) end end # Respond to missing according to the method_missing implementation # def respond_to_missing?(method, include_private = false) - is_setter?(method) || @_writeable || _configured?(method) || super + is_setter?(method) || @_writeable || _configured?(method) || ::Kernel.respond_to_missing?(method, include_private) end # Set the configuration to writeable or read only. Access to writer methods is only allowed within the # configure block, this method is used to invoke writability for subconfigurations. # @param [Boolean] data true if the configuration should be writeable, false otherwise @@ -96,19 +96,26 @@ h end end - private - # @param [Symbol] property The property to test for configurability # @return [Boolean] whether the given property is configurable # def _configurable?(property) _arbitrarily_configurable? or @configurable.has_key?(property) end + + # @return [Boolean] whether this configuration is arbitrarily configurable + # + def _arbitrarily_configurable? + @configurable.nil? or @configurable.empty? + end + + private + # @param [Symbol] property The property to test for # @return [Boolean] whether the given property has been configured # def _configured?(property) @configuration.has_key?(property) @@ -125,45 +132,67 @@ # Evaluates configurable properties and passes eventual hashes down to subconfigurations # def _evaluate_configurable! return if _arbitrarily_configurable? - @configurable.each do |k, type| + @configurable.each do |k, assertion| if k.is_a?(::Hash) k.each do |property, nested| - @configuration[property] = Configuration.new(nil, _to_configurable_hash(nested, type)) + @configuration[property] = Configuration.new(nil, _to_configurable_hash(nested, assertion)) end end end end # @param [Symbol, Hash, Array] value configurable properties, either single or nested # @param [Class] type the type to assert, if any # @return a hash with configurable values pointing to their types # - def _to_configurable_hash(value, type) + def _to_configurable_hash(value, assertion) value = [value] unless value.is_a?(::Array) - ::Hash[value.zip([type].flatten*value.size)] + ::Hash[value.zip([assertion].flatten*value.size)] end + # Assigns a value after running the assertions + # @param [Symbol] property the property to type test + # @param [Any] value the given value + # + def _assign!(property, value) + v = _evaluate_block!(property, value) + value = v unless v.nil? + _assert_type!(property, value) + @configuration[property] = value + end + # Type assertion for configurable properties # @param [Symbol] property the property to type test # @param [Any] value the given value # @raise [ConfigurationError] if the given value has the wrong type # def _assert_type!(property, value) - return if _arbitrarily_configurable? + return unless _evaluable?(property, :type) - expected_type = @configurable[property] - return if expected_type.nil? + assertion = @configurable[property][:type] + ::Kernel.raise ConfigurationError, "Expected #{property} to be configured with #{expected_type}, but got #{value.class.inspect}", caller unless value.is_a?(assertion) + end - ::Kernel.raise ConfigurationError, "Expected #{property} to be configured with #{expected_type}, but got #{value.class.inspect}", caller unless value.is_a?(expected_type) + # Block assertion for configurable properties + # @param [Symbol] property the property to type test + # @param [Any] value the given value + # + def _evaluate_block!(property, value) + return value unless _evaluable?(property, :block) + + evaluation = @configurable[property][:block] + evaluation.call(value) end - # @return [Boolean] whether this configuration is arbitrarily configurable + # @param [Symbol] property The property to test for + # @param [Symbol] assertion_type The evaluation type type to test for + # @return [Boolean] whether the given property is assertable # - def _arbitrarily_configurable? - @configurable.nil? or @configurable.empty? + def _evaluable?(property, evaluation) + @configurable and @configurable.has_key?(property) and @configurable[property].is_a?(::Hash) and @configurable[property].has_key?(evaluation) end # @param [Symbol] method the method to test for # @return [Boolean] whether the given method is a writer #