NAME

arrayfields.rb

URIS

http://rubyforge.org/projects/codeforpeople/

SYNOPSIS

   require 'arrayfields'

   a = Arrayfields.new :k, :v, :a, :b

   p a[:k]        #=> :v
   p a[:a]        #=> :b
   p a.fields     #=> [:k, :a]
   p a.values     #=> [:v, :b]
   p a            #=> [:v, :b]
   p a.to_hash    #=> {:k => :v, :a => :b} 
   p a.pairs      #=> [[:k, :v], [:a, :b]]

   a[:foo] = :bar

   p a[:foo]      #=> :bar
   p a.fields     #=> [:k, :a, :foo]

AND

   require 'arrayfields'  

   fields = 'name', 'age'
   a = [ 'zaphod', 42 ]

   a.fields = fields

   a['name']                #=> 'zaphod'
   a[:name ]                #=> 'zaphod'
   a.indices 'name', 'age'  #=> [ 'zaphod', 42 ]

DESCRIPTION

allow keyword access to array instances.  arrayfields works by adding only a
few methods to arrays, namely #fields= and fields, but the #fields= method is
hooked to extend an array on a per object basis.  in otherwords __only__ those
arrays whose fields are set will have auto-magical keyword access bestowed on
them - all other arrays remain unaffected.  arrays with keyword access require
much less memory when compared to hashes/objects and yet still provide fast
lookup and preserve data order.

LIST OF OVERRIDDEN METHODS

Array#[]
Array#slice
Array#[]=
Array#at
Array#delete_at
Array#fill
Array#values_at
Array#indices
Array#indexes
Array#slice!

LIST OF HASH-LIKE METHODS

Array#each_with_field
Array#each_pair
Array#each_key
Array#each_value
Array#fetch
Array#has_key?
Array#member?
Array#key?
Array#has_value?
Array#value?
Array#keys
Array#store
Array#values
Array#to_hash
Array#to_h
Array#update
Array#replace
Array#invert
Array#pairs

LIST OF ADDED Array METHODS

Array#fields=
Array#fields

LIST OF ADDED Array CLASS METHODS

Array.fields/Array.struct

SAMPLES

<========< sample/a.rb >========>

~ > cat sample/a.rb

  require 'arrayfields'
  #
  # the class Array has only a few added method, one is for setting the fields,
  # when the fields are set for an array THIS INSTANCE ONLY will be modified to
  # allow keyword access.  other arrays will not be affected!
  #
    a = [0,1,2]
    fields = ['zero', 'one', 'two']
    a.fields = fields                # ONLY the Array 'a' is affected!
  #
  # keyword access is now allowed for many methods
  #
    p a['zero']                        #=> 0
    p a['one']                         #=> 1
    p a['two']                         #=> 2
    p a.at('one')                      #=> 1
    p a.values_at('zero', 'two')       #=> [0, 2]
  #
  # assigmnet is allowed
  #
    a['zero'] = 42
    p a['zero']                        #=> 42 
  #
  # assignment to non-fields results in the element being appended and the field
  # being added for future use (also appended)
  #
    p(a.fields.join(','))                 #=> "zero, one, two"
    p a['three']                          #=> nil
    a['three'] = 3
    p(a.fields.join(','))                 #=> "zero, one, two, three"
    p a['three']                          #=> 3 
  #
  # other detructive methods are also keyword enabled
  #
    a.fill 42, 'zero', len = a.size
    p(a.values_at(a.fields))              #=> [42, 42, 42, 42]
    a.replace [0,1,2,3]

    a.slice! 'two', 2 
    p a                                   #=> [0,1] 

~ > ruby sample/a.rb

  0
  1
  2
  1
  [0, 2]
  42
  "zero,one,two"
  nil
  "zero,one,two,three"
  3
  [42, 42, 42, 42]
  [0, 1]

<========< sample/b.rb >========>

~ > cat sample/b.rb

  require 'arrayfields'
  #
  # the struct class factory method can be used in much the same way as ruby's
  # own struct generators and is useful when the fields for a set of arrays is
  # known apriori
  #
    c = Array.struct :a, :b, :c  # class generator 
    a = c.new [42, nil, nil]
    a[:c] = 42
    p a                          #=> [42, nil, 42]
  #
  # of course we can append too
  #
    a[:d] = 42.0
    p a[:d]                      #=> 42.0
    p a                          #=> [42, nil, 42, 42.0]

~ > ruby sample/b.rb

  [42, nil, 42]
  42.0
  [42, nil, 42, 42.0]

<========< sample/c.rb >========>

~ > cat sample/c.rb

  require 'arrayfields'
  #
  # the Array.fields methods generates an instance with those fields
  #
    a = Array.fields :a, :b, :c
    a[:a] = a[:c] = 42
    p a                           #=> [42, nil, 42]
    p a.fields                    #=> [:a, :b, :c]
    p a.values                    #=> [42, nil, 42]

~ > ruby sample/c.rb

  [42, nil, 42]
  [:a, :b, :c]
  [42, nil, 42]

<========< sample/d.rb >========>

~ > cat sample/d.rb

  require 'arrayfields'
  #
  # the Arrayfields.new method is a contruct that takes evenly numbered pairs of
  # arbitrary objects and builds up a fielded array
  #
    a = Arrayfields.new :key, :value, :a, :b
    p a.fields                                     #=> [:key, :a]
    p a.values                                     #=> [:value, :b]
  #
  # you can use a hash - but of course the ordering gets lost in the initial
  # hash creation.  aka the order of fields get horked by the unorderedness of
  # ruby's hash iteration.  it's okay for some purposes though
  #
    a = Arrayfields.new :key => :value, :a => :b
    p a.fields                                     #=> [:key, :a]
    p a.values                                     #=> [:value, :b]
  #
  # lists of pairs get flattened - the argument simply has to be evenly numbered
  # afterwards.
  #
    a = Arrayfields.new [[:key, :value], [:a, :b]]
    p a.fields                                     #=> [:key, :a]
    p a.values                                     #=> [:value, :b]
    p a.pairs                                      #=> [[:key, :value], [:a, :b]]

~ > ruby sample/d.rb

  [:key, :a]
  [:value, :b]
  [:key, :a]
  [:value, :b]
  [:key, :a]
  [:value, :b]
  [[:key, :value], [:a, :b]]

<========< sample/e.rb >========>

~ > cat sample/e.rb

  require 'arrayfields'

  Entry = Array.struct :path, :stat

  entry = Entry[ File.basename(__FILE__), File.stat(__FILE__) ]
  p entry[:path]   #=> "e.rb"
  p entry.path     #=> "e.rb"

  entry.path = 'foo'
  p entry[:path]   #=> "foo"
  p entry.path     #=> "foo"

  entry.path 'bar' # getter acts as setter without args
  p entry['path']  #=> "bar"
  p entry.path     #=> "bar"

~ > ruby sample/e.rb

  "e.rb"
  "e.rb"
  "foo"
  "foo"
  "bar"
  "bar"

AUTHOR

ara.t.howard@gmail.com

HISTORY

4.7.4
  - fixes for clone/dup methods

4.6.0
  - Array#fields getter acts as setter if arg given, eg

      a = []

      a.fields %w( a b c )
      a['c'] = 42

4.4.0:
  - working dup method worked in, also deepcopy and clone

4.3.0:
  - a dup like method, named 'copy' and based on clone, is added to Arrayfields objects

4.2.0:
  - a dup impl apparently caused some confusion with both rake and rails, so
    this release undoes that impl and should be considered a critical bugfix
    release

4.1.0:
  - improved Array.struct method, see sample/e.rb

4.0.0:
  - added Arrayfields.new(*arbitrary_evenly_numbered_list_of_objects)
  - added #to_pairs and #pairs
  - tried but failed to recall what happend for version 3.8
  - changed Array.fields to == Arrayfields.new (used to alias Array.struct)
  - added impl of Fieldable#dup that sets fields in dupped object

3.7.0:
  - multiton pattern clean up, thanks gavin kistner!
  - mods for ruby 1.8.6 (alias bug in 1.8.6 i think)
  - added PseudoHash class
  - added Array.struct/fields class generator

3.6.0:
  - made string/symbol keys interchangeable

      list = [0, 1, 2]
      list.fields = %w( a b c )
      p list['a'] #=> 0
      p list[:a] #=> 0

3.5.0:
  - added more hash-like methods
    - update
    - replace
    - invert

3.4.0:
  - added FieldedArray[] ctor
  - added methods to make Arrays with fields set behave more closely to Hashes
    - each_pair 
    - each_key
    - each_value
    - fetch
    - has_key?
    - member?
    - key?
    - has_value?
    - value?
    - keys?
    - store
    - values

3.3.0:
  - added gemspec file - thnx Assaph Mehr
  - added FieldedArray proxy class which minimizes modifications to class
    Array and allow ArrayFields to work (potientially) other arraylike object.
    thnks Sean O'Dell
  - added ArrayFields#to_hash method - this seems like an obvious one to add!
  - remedied bug where using append feature of assigning with unknow field
    appedended but did not append to acutal fields
  - added samples
  - created rubyforge accnt @ http://rubyforge.org/projects/arrayfields/ 

3.2.0:
  - precedence fix in many methods - thnx. nobu
  - test for #slice! were not being run - corrected
  - added test for appeding via "a['new_field'] = 42"

3.1.0:
  - added FieldSet class to reduce ram - thnx. Kirk Haines for profiliing
    memory and prompting this change

  - interface changed every so slightly so

      a.fields = 'a', 'b', 'c'

    is not allowed.  use

      a.fields = %w(a b c) 

    or

      a.fields = ['a', 'b', 'c']

3.0.0:
  - added unit tests