lib/aladdin/config.rb in aladdin-0.0.5 vs lib/aladdin/config.rb in aladdin-0.0.6

- old
+ new

@@ -1,14 +1,15 @@ # ~*~ encoding: utf-8 ~*~ - module Aladdin # Raised when there is a configuration error. class ConfigError < StandardError; end - # Configuration options for Aladdin. - class Config + # Configuration options for Aladdin. Gets all of its values from {FILE}. + # Values in this file should not be trusted because they are given by the + # user. + class Config < Hash # Name of configuration file. FILE = 'manifest.json' # Default configuration options. @@ -17,35 +18,65 @@ 'bin' => 'make', 'arg_prefix' => '' }, 'title' => 'Lesson X', 'description' => 'This is a placeholder description. You should provide your own', - 'categories' => [] + 'categories' => [], + 'static_paths' => %w(images) } # Creates a new configuration from the file at the given path. Merges the # configuration hash parsed from the file with {DEFAULTS}. Raises # {ConfigError} if the file could not be read or parsed. # @param [String] root path to lesson root def initialize(root) - path = File.expand_path FILE, root - case - when (not File.exist? path) - ConfigError.new("We couldn't find a manifest file at #{path}") - when (not File.readable? path) - ConfigError.new("We found a manifest file at #{path}, but couldn't " + - "read it. Please ensure that the permissions are set correctly.") - else - config = ::JSON.parse(File.read path) - @config = DEFAULTS.deep_merge config - end + @path = File.expand_path FILE, root + ensure_readable + super nil + merge! DEFAULTS.deep_merge ::JSON.parse File.read @path + ensure_valid rescue ::JSON::JSONError => e raise ConfigError.new e.message end - # @return [Hash] a hash copy of the configuration options - def to_hash - @config.clone + private + + # Raises {ConfigError} unless the configuration file exists and is + # readable. + def ensure_readable + missing unless File.exist? @path + not_readable unless File.readable? @path + end + + # Raises {ConfigError} unless the all of the values in the supplied + # configuration have the same type as those in {DEFAULTS}. + def ensure_valid(defaults=DEFAULTS, supplied=self) + supplied.each do |key, value| + bad_type(key, defaults[key], value) unless value.is_a? defaults[key].class + ensure_valid(defaults[key], value) if Hash === value + end + end + + def missing + raise ConfigError.new <<-eos.squish + We expected a manifest file at #{@path}, but couldn't find it. Please + ensure that you have a file named #{Aladdin::Config::File} at the root + of your lesson directory. + eos + end + + def not_readable + raise ConfigError.new <<-eos.squish + We found a manifest file at #{@path}, but couldn't open it for reading. + Please ensure that you have the permissions to read the file. + eos + end + + def bad_type(key, expected, actual) + raise ConfigError.new <<-eos.squish + The #{key} option in the manifest file should be a #{expected.class.name} + instead of a #{actual.class.name}. + eos end end end