require 'ostruct' module ZTK # Config Error Class # # @author Zachary Patten class ConfigError < Error; end # Configuration Module # # Extend an existing class with this module to turn it into a singleton # configuration class. # # Given we have some code like: # # class C # extend(ZTK::Config) # end # # We can then do things like: # # C.thing = "something" # # or we can reference keys this way: # # C[:thing] = "something" # # Accessing the value is just as simple: # # puts C.thing # # We can also load configurations from disk. Assuming we have a file (i.e. config.rb) like: # # message "Hello World" # thing (1+1) # # We can load it like so: # # C.from_file("config.rb") # # Then we can reference the configuration defined in the file as easily as: # # puts C.message # # @author Zachary Patten module Config # Extend base class with this module. # # This will add the *configuration* attribute to the base class and create # a new *OpenStruct* object assigning it to the *configuration* attribute. # def self.extended(base) class << base attr_accessor :configuration end base.configuration = OpenStruct.new end # Loads a configuration from a file. # def from_file(filename) self.instance_eval(IO.read(filename), filename) end # Yields the configuration OpenStruct object to a block. # # @yield [configuration] Pass the configuration OpenStruct object to the # specified block. # def config(&block) block and block.call(self.configuration) end # Get the value of a configuration key. # # @param [Symbol, String] key A symbol or string of the configuration # key to return. # # @return The value currently assigned to the configuration key. # def [](key) _get(key) end # Set the value of a configuration key. # # @param [Symbol, String] key A symbol or string of the configuration # key to set. # @param value The value which you want to assign to the configuration # key. # # @return The value assigned to the configuration key. # def []=(key, value) _set(key, value) end # @see Hash#keys # def keys self.configuration.send(:table).keys end # @see Hash#has_key? # def has_key?(key) self.configuration.send(:table).has_key?(key) end # @see Hash#merge # def merge(hash) self.configuration.send(:table).merge(hash) end # @see Hash#merge! # def merge!(hash) self.configuration.send(:table).merge!(hash) end # Handles method calls for our configuration keys. # def method_missing(method_symbol, *method_args) if method_args.length > 0 _set(method_symbol, method_args.first) end _get(method_symbol) end private def _set(key, value) key = key.to_s (key =~ /=/) or key += '=' self.configuration.send(key.to_sym, value) end def _get(key) key = key.to_s (key !~ /=/) or key = key[0..-2] self.configuration.send(key.to_sym) end end end