tmatilai/vagrant-proxyconf

View on GitHub
lib/vagrant-proxyconf/config/key_mixin.rb

Summary

Maintainability
A
0 mins
Test Coverage
require_relative 'key'

module VagrantPlugins
  module ProxyConf
    module Config
      # Helper module for Config classes.
      #
      # Handles mapping to environment variables, setting default values,
      # and constructing the configuration file stanza.
      module KeyMixin

        # Methods for the including class to specify and access the configuration keys.
        module ClassMethods
          # @!attribute [r] keys
          # @return [Array<Key>] the configuration keys for the class
          def keys
            @keys ||= []
          end

          # Defines a configuration key for the class.
          # Creates `attr_accessor` for the key name and adds a {Key} to {#keys}.
          # @param (see Key#initialize)
          # @option (see Key#initialize)
          # @!macro [attach] key
          #   @!attribute
          def key(name, opts = {})
            self.class_eval { attr_accessor name }
            keys << Key.new(name, opts)
          end
        end

        # Extends the including class with {ClassMethods}
        def self.included(base)
          base.extend ClassMethods
        end

        # Initializes all keys to `UNSET_VALUE`
        def initialize
          super
          keys.each do |key|
            set(key, self.class::UNSET_VALUE)
          end
        end

        # Overrides values from specified environment variables, and sets them
        # to default values if no configuration was found
        def finalize!
          super
          keys.each { |key| set(key, resolve_value(key)) }
        end

        # @return [Boolean] true if any of the configuration keys has a non-nil value
        def enabled?
          keys.any? { |key| set?(key) }
        end

        # Returns the full configuration stanza
        # Calls {#config_for} for each key.
        #
        # @return [String]
        def to_s
          keys.map { |key| config_for(key, get(key)).to_s }.join
        end

        # Returns a configuration line/stanza for the specified key and value.
        # The returned line should include linefeed `\\n` if not empty.
        # The default implementations returns "<key>=<value>\\n".
        #
        # @param key [Key] the configuration key
        # @param value [String, nil] the configuration value
        # @return [#to_s] the configuration line(s)
        def config_for(key, value)
          "#{key}=#{value && value}\n"
        end

        # Returns a new instance of this class where all nil keys are
        # replaced from the specified default config
        #
        # @param defaults [KeyMixin] the default configuration
        # @return [KeyMixin]
        def merge_defaults(defaults)
          result = dup
          keys.each do |key|
            if !set?(key) && defaults.key?(key)
              result.set(key, defaults.get(key))
            end
          end
          result
        end

        protected

        def keys
          self.class.keys
        end

        def key?(key)
          keys.any? { |k| k.name == key.name }
        end

        def get(key)
          public_send(key.name)
        end

        def set?(key)
          !get(key).nil?
        end

        def set(key, value)
          public_send(:"#{key.name}=", value)
        end

        private

        def resolve_value(key)
          ret = key.value_from_env_var do |default|
            value = get(key)
            value == self.class::UNSET_VALUE ? default : value
          end
          ret == '' ? false : ret
        end
      end
    end
  end
end