# Defines a collection for application settings # # This implements a hierarchical interface to application settings. Containers # can define an optional parent container that will be used for default options # if those options aren't set on the given container. class R10K::Settings::Container # @!attribute [r] valid_keys # @return [Set] All valid keys defined on the container or parent container. attr_accessor :valid_keys # @param parent [R10K::Settings::Container] An optional parent container def initialize(parent = nil) @parent = parent @valid_keys = Set.new @settings = {} end # Look up a value in the container. The lookup checks the current container, # and then falls back to the parent container if it's given. # # @param key [Symbol] The lookup key # # @return [Object, nil] The retrieved value if present. # # @raise [R10K::Settings::Container::InvalidKey] If the looked up key isn't # a valid key. def [](key) validate_key! key if @settings[key] @settings[key] elsif @parent && (pkey = @parent[key]) begin @settings[key] = pkey.dup rescue TypeError @settings[key] = pkey end @settings[key] end end # Set a value on the container # # @param key [Symbol] The lookup key # @param value [Object] The value to store in the container # # @raise [R10K::Settings::Container::InvalidKey] If the looked up key isn't # a valid key. def []=(key, value) validate_key! key @settings[key] = value end # Define a valid container key # # @note This should only be used by {#R10K::Settings::ClassSettings} # # @param key [Symbol] # @return [void] def add_valid_key(key) @valid_keys.add(key) end # Determine if a key is a valid setting. # # @param key [Symbol] # # @return [true, false] def valid_key?(key) if @valid_keys.include?(key) true elsif @parent and @parent.valid_key?(key) @valid_keys.add(key) true end end # Clear all existing settings in this container. Valid settings are left alone. # @return [void] def reset! @settings = {} end private def validate_key!(key) unless valid_key?(key) raise InvalidKey, _("Key %{key} is not a valid key") % {key: key} end end # @api private class InvalidKey < StandardError; end end