Configurability::Config::

Struct

class
Superclass
Object
Extended With
Forwardable

Hash-wrapper that allows struct-like accessor calls on nested hashes.

Public Class Methods

anchor
new( hash=nil )

Create a new ConfigStruct using the values from the given hash if specified.

# File lib/configurability/config.rb, line 381
def initialize( hash=nil )
        hash ||= {}
        @hash = symbolify_keys( hash )
        @dirty = false
end

Public Instance Methods

anchor
[]( key )

Return the value associated with the specified key, or another Configurability::Config::ConfigStruct if key is a section name.

# File lib/configurability/config.rb, line 402
def []( key )
        key = key.untaint.to_sym if key.respond_to?( :to_sym )

        # Convert Hashes to Struct on the fly for subsections
        @hash[ key ] = self.class.new( @hash[key] ) if @hash[ key ].is_a?( Hash )

        return @hash[ key ]
end
anchor
[]=( key, value )

Set the value associated with the specified key to value.

# File lib/configurability/config.rb, line 413
def []=( key, value )
        key = key.untaint.to_sym
        self.mark_dirty if @hash[ key ] != value
        @hash[ key ] = value
end
anchor
dirty?()

Returns true if the ConfigStruct or any of its sub-structs have changed since it was created.

# File lib/configurability/config.rb, line 428
def dirty?
        return true if @dirty
        return true if @hash.values.find do |obj|
                obj.respond_to?( :dirty? ) && obj.dirty?
        end
end
anchor
has_member?( name )
Alias for: member?
anchor
inspect()

Return a human-readable representation of the Struct suitable for debugging.

# File lib/configurability/config.rb, line 519
def inspect
        return "#<%s:%0x16 %p>" % [
                self.class.name,
                self.object_id * 2,
                @hash,
        ]
end
anchor
mark_dirty()

Mark the struct has having been modified since its creation.

# File lib/configurability/config.rb, line 421
def mark_dirty
        @dirty = true
end
anchor
member?( name )

Returns true if the given name is the name of a member of the receiver.

# File lib/configurability/config.rb, line 475
def member?( name )
        name = name.to_sym if name.respond_to?( :to_sym )
        return @hash.key?( name )
end
Also aliased as: has_member?
anchor
members()

Returns an Array of Symbols, one for each of the struct's members.

# File lib/configurability/config.rb, line 468
def members
        return @hash.keys
end
anchor
merge( other )

Return a new Configurability::Config::Struct which is the result of merging the receiver with the given other object (a Hash or another Configurability::Config::Struct).

# File lib/configurability/config.rb, line 513
def merge( other )
        self.dup.merge!( other )
end
anchor
merge!( other )

Merge the specified other object with this config struct. The other object can be either a Hash, another Configurability::Config::Struct, or an Configurability::Config.

# File lib/configurability/config.rb, line 485
def merge!( other )
        mergefunc = Configurability::Config.method( :merge_complex_hashes )

        case other
        when Hash
                @hash = self.to_h.merge( other, &mergefunc )

        when Configurability::Config::Struct
                @hash = self.to_h.merge( other.to_h, &mergefunc )

        when Configurability::Config
                @hash = self.to_h.merge( other.struct.to_h, &mergefunc )

        else
                raise TypeError,
                        "Don't know how to merge with a %p" % other.class
        end

        # :TODO: Actually check to see if anything has changed?
        @dirty = true

        return self
end
anchor
respond_to?( sym, priv=false )

Return true if the receiver responds to the given method. Overridden to grok autoloaded methods.

# File lib/configurability/config.rb, line 460
def respond_to?( sym, priv=false )
        key = sym.to_s.sub( /(=|\?)$/, '' ).to_sym
        return true if @hash.key?( key )
        super
end
anchor
to_h()
Alias for: to_hash
anchor
to_hash()

Return the receiver's values as a (possibly multi-dimensional) Hash with String keys.

# File lib/configurability/config.rb, line 438
def to_hash
        rhash = {}
        @hash.each {|k,v|
                case v
                when Configurability::Config::Struct
                        rhash[k] = v.to_h
                when NilClass, FalseClass, TrueClass, Numeric
                        # No-op (can't dup)
                        rhash[k] = v
                when Symbol
                        rhash[k] = v.to_s
                else
                        rhash[k] = v.dup
                end
        }
        return rhash
end
Also aliased as: to_h

Protected Instance Methods

anchor
create_member_predicate( key )

Create a predicate method for the specified key and return it.

# File lib/configurability/config.rb, line 559
def create_member_predicate( key )
        return lambda { self.member?( key ) && self[key] ? true : false }
end
anchor
create_member_reader( key )

Create a reader method for the specified key and return it.

# File lib/configurability/config.rb, line 553
def create_member_reader( key )
        return lambda { self[key] }
end
anchor
create_member_writer( key )

Create a writer method for the specified key and return it.

# File lib/configurability/config.rb, line 565
def create_member_writer( key )
        return lambda {|val| self[key] = val }
end
anchor
method_missing( sym, *args )

Handle calls to key-methods

# File lib/configurability/config.rb, line 533
def method_missing( sym, *args )
        key = sym.to_s.sub( /(=|\?)$/, '' ).to_sym

        # Create new methods for this key
        reader    = self.create_member_reader( key )
        writer    = self.create_member_writer( key )
        predicate = self.create_member_predicate( key )

        # ...and install them
        self.class.send( :define_method, key, &reader )
        self.class.send( :define_method, "#{key}=", &writer )
        self.class.send( :define_method, "#{key}?", &predicate )

        # Now jump to the requested method in a way that won't come back through
        # the proxy method if something didn't get defined
        self.method( sym ).call( *args )
end