module CyberCoach
  #
  # Mixin for an object that be initialized with a hash.
  #
  module HashInitializable
    #
    # Installs class and instance methods in the class it is included in.
    #
    def self.included(base)
      base.extend ClassMethods
      base.send :include, InstanceMethods
    end

    #
    # The class methods to install.
    #
    module ClassMethods
    end

    #
    # The instance methods to install.
    #
    module InstanceMethods
      #
      # :category: Initialization
      #
      # Returns a list of instance variables it can be initialized with.
      #
      def initializable_with
        fail SubclassResponsibilityError
      end

      #
      # :category: Initialization
      #
      # Initializes the instance variables with a name in the specified names to
      # the values mapped in the specified hash.
      # hash:: A hash of values to set on instance variables.
      # names:: The names of the instance variables to set.
      #
      def initialize_with(hash)
        initializable_with.each do |name|
          if hash.key? name
            instance_variable_set(:"@#{name}", hash[name])
          end
        end
      end
    end
  end
end
