class Mongrel2::Table

The Mongrel2 Table class. Instances of this class provide a case-insensitive hash-like object that can store multiple values per key.

headers = Mongrel2::Table.new
headers['User-Agent'] = 'PornBrowser 1.1.5'
headers['user-agent']  # => 'PornBrowser 1.1.5'
headers[:user_agent]   # => 'PornBrowser 1.1.5'
headers.user_agent     # => 'PornBrowser 1.1.5'

Author/s

Constants

KEYED_METHODS

Methods that understand case-insensitive keys

NON_DELEGATED_METHODS

Method to not delegate to the inner hash

Public Class Methods

def_normalized_delegators( delegate, *syms ) click to toggle source

Auto-generate methods which call the given delegate after normalizing their first argument via normalize_key

# File lib/mongrel2/table.rb, line 39
def self::def_normalized_delegators( delegate, *syms )
        syms.each do |methodname|
                define_method( methodname ) do |key, *args|
                        nkey = normalize_key( key )
                        instance_variable_get( delegate ).
                                __send__( methodname, nkey, *args )
                end
        end
end
new( initial_values={} ) click to toggle source

Create a new Mongrel2::Table using the given hash for initial values.

# File lib/mongrel2/table.rb, line 56
def initialize( initial_values={} )
        @hash = {}
        initial_values.each {|k,v| self.append(k => v) }
end

Public Instance Methods

append( hash ) click to toggle source

Append the keys and values in the given hash to the table, transforming each value into an array if there was an existing value for the same key.

# File lib/mongrel2/table.rb, line 86
def append( hash )
        self.merge!( hash ) do |key,origval,newval|
                [ origval, newval ].flatten
        end
end
each_header( &block ) click to toggle source

Enumerator for iterating over the table contents, yielding each as an RFC822 header.

# File lib/mongrel2/table.rb, line 107
def each_header( &block )
        enum = Enumerator.new do |yielder|
                @hash.each do |header, value|
                        Array( value ).each do |val|
                                yielder.yield( normalize_header(header), val.to_s )
                        end
                end
        end

        if block
                return enum.each( &block )
        else
                return enum
        end
end
freeze() click to toggle source

Overridden to freeze the inner hash as well.

Calls superclass method
# File lib/mongrel2/table.rb, line 169
def freeze
        super
        @hash.freeze
end
inspect() click to toggle source

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

# File lib/mongrel2/table.rb, line 159
def inspect
        return "#<%p:%#x %p>" % [
                self.class,
                self.object_id * 2,
                @hash
        ]
end
merge( other_table ) { |key, original_value, new_value| ... } click to toggle source

Return a new table which is the result of merging the receiver with other_table in the same fashion as Hash#merge. If the optional merge_callback block is provided, it is called whenever there is a key collision between the two.

# File lib/mongrel2/table.rb, line 143
def merge( other_table, &merge_callback ) # :yields: key, original_value, new_value
        other = self.dup
        other.merge!( other_table, &merge_callback )
        return other
end
Also aliased as: update
merge!( other_table, &merge_callback ) click to toggle source

Merge other_table into the receiver.

# File lib/mongrel2/table.rb, line 132
def merge!( other_table, &merge_callback )
        nhash = normalize_hash( other_table.to_hash )
        @hash.merge!( nhash, &merge_callback )
end
Also aliased as: update!
to_h() click to toggle source

Return the Table as a hash.

# File lib/mongrel2/table.rb, line 125
def to_h
        @hash.dup
end
Also aliased as: to_hash
to_hash()
Alias for: to_h
to_s() click to toggle source

Return the Table as RFC822 headers in a String

# File lib/mongrel2/table.rb, line 94
def to_s
        @hash.collect do |header,value|
                Array( value ).collect {|val|
                        "%s: %s" % [
                                normalize_header( header ),
                                val
                        ]
                }
        end.flatten.sort.join( "\r\n" ) + "\r\n"
end
update( other_table )
Alias for: merge
update!( other_table, &merge_callback )
Alias for: merge!
values_at( *keys ) click to toggle source

Return an array containing the values associated with the given keys.

# File lib/mongrel2/table.rb, line 153
def values_at( *keys )
        @hash.values_at( *(keys.collect {|k| normalize_key(k)}) )
end

Protected Instance Methods

make_getter( key ) click to toggle source

Create a Proc that will act as a getter for the given key

# File lib/mongrel2/table.rb, line 207
def make_getter( key )
        return Proc.new { self[key] }
end
make_setter( key ) click to toggle source

Create a Proc that will act as a setter for the given key

# File lib/mongrel2/table.rb, line 201
def make_setter( key )
        return Proc.new {|new_value| self[ key ] = new_value }
end
method_missing( sym, *args ) click to toggle source

Proxy method: handle getting/setting headers via methods instead of the index operator.

Calls superclass method
# File lib/mongrel2/table.rb, line 181
def method_missing( sym, *args )
        # work magic
        return super unless sym.to_s =~ /^([a-z]\w+)(=)?$/

        # If it's an assignment, the (=)? will have matched
        key, assignment = $1, $2

        method_body = nil
        if assignment
                method_body = self.make_setter( key )
        else
                method_body = self.make_getter( key )
        end

        self.class.send( :define_method, sym, &method_body )
        return self.method( sym ).call( *args )
end

Private Instance Methods

deep_copy( obj ) click to toggle source

Recursively copying the specified obj and return the result.

# File lib/mongrel2/table.rb, line 241
def deep_copy( obj )
        # Handle mocks during testing
        return obj if obj.class.name == 'RSpec::Mocks::Mock'

        return case obj
                        when NilClass, Numeric, TrueClass, FalseClass, Symbol
                                        obj

                        when Array
                                        obj.map {|o| deep_copy(o) }

                        when Hash
                                        newhash = {}
                                        obj.each do |k,v|
                                                        newhash[ deep_copy(k) ] = deep_copy( v )
                                        end
                                        newhash

                        else
                                        obj.clone
                        end
end
normalize_hash( hash ) click to toggle source

Return a copy of hash with all of its keys normalized by normalize_key.

# File lib/mongrel2/table.rb, line 217
def normalize_hash( hash )
        hash = hash.dup
        hash.keys.each do |key|
                nkey = normalize_key( key )
                hash[ nkey ] = hash.delete( key ) if key != nkey
        end

        return hash
end
normalize_header( key ) click to toggle source

Return the given key as an RFC822-style header label

# File lib/mongrel2/table.rb, line 235
def normalize_header( key )
        key.to_s.split( '_' ).collect {|part| part.capitalize }.join( '-' )
end
normalize_key( key ) click to toggle source

Normalize the given key to equivalence

# File lib/mongrel2/table.rb, line 229
def normalize_key( key )
        key.to_s.downcase.gsub('-', '_').to_sym
end