Arrayfields-4.1.0

NAME
arrayfields.rb

URIS
http://www.codeforpeople.com/lib/ruby/
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’] #=> 0
a[‘zero’] = 0
#
# 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 insance 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 and 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 if
# the hash iteration. it’s okay for some purposed though
#
a = Arrayfields.new :key => :value, :a => :b
p a.fields #=> [:key, :a]
p a.values #=> [:value, :b]
#
# lists of pairs get flattened - the result simply has to be
evenly numbered
#
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
[email protected]

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

enjoy.

a @ http://drawohara.com/

Hi ara (Ara, a, … which is the best salutation?),

There appears to be an incompatibility between arrayfields and active
record dynamic finders.

I’ve filed a bug report here:

http://rubyforge.org/tracker/index.php?func=detail&aid=14040&group_id=1024&atid=4025

but I’m also posting it here to get a wider audience.

I’m using rails 1.2.3. After loading arrayfields 4.1.0 the active
record dynamic finders “find_by_ …” are broken.

Here’s a simple test showing the dynamic finder working, requiring
arrayfields, and then the dynamic finder stops working.

$ script/console
Loading development environment.

OtmlFile.find_by_path(“…/…/concord/otrunk-examples/BasicExamples/basic_drawing.otml”)
=> #<OtmlFile:0x330ebf4 @attributes={“name”=>“basic_drawing.otml”,
“id”=>“1”,
“path”=>“…/…/concord/otrunk-examples/BasicExamples/basic_drawing.otml”}>
require ‘arrayfields’
=> [“PseudoHash”, “Arrayfields”, “Pseudohash”, “Fieldable”,
“FieldedArray”, “ArrayFields”, “Fieldedarray”]

OtmlFile.find_by_path(“…/…/concord/otrunk-examples/BasicExamples/basic_drawing.otml”)
ArgumentError: not inject-able
from
/usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:28:in
initialize' from /usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:16:in new’
from
/usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:16:in
new' from /usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:286:in fields=’
from
/usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:305:in
dup' from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1426:in replace_bind_variables’
from
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1405:in
sanitize_sql_hash' from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1388:in sanitize_sql’
from
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1163:in
add_conditions!' from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1096:in construct_finder_sql’
from
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:997:in
find_every' from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:991:in find_initial’
from
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1204:in
send' from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1204:in method_missing’
from
/usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/deprecation.rb:44:in
silence' from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1204:in method_missing’
from (irb):3>>

At 11:41 PM +0900 9/18/07, Stephen B. wrote:

There appears to be an incompatibility between arrayfields and active record dynamic finders.

I’ve filed a bug report here:

http://rubyforge.org/tracker/index.php?func=detail&aid=14040&group_id=1024&atid=4025

Here’s a much simpler way to generate the problem without rails.

$ irb
irb(main):001:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):002:0> a.dup
=> [1, 2, 3]
irb(main):003:0> require ‘arrayfields’
=> true
irb(main):004:0> a.dup
ArgumentError: not inject-able
from
/usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:28:in
initialize' from /usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:16:in new’
from
/usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:16:in
new' from /usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:286:in fields=’
from
/usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:305:in
`dup’
from (irb):4

On Sep 18, 2007, at 1:27 PM, Stephen B. wrote:

lib/arrayfields.rb:28:in initialize' from /usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/ lib/arrayfields.rb:16:in new’
from /usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/
lib/arrayfields.rb:16:in new' from /usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/ lib/arrayfields.rb:286:in fields=’
from /usr/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/
lib/arrayfields.rb:305:in `dup’
from (irb):4

yeah thanks. it was a stupid bug on my part. 4.2.0 and 4.3.0 both
address the fix. thanks again.

a @ http://drawohara.com/

On Sep 18, 2007, at 8:41 AM, Stephen B. wrote:

OtmlFile.find_by_path(“…/…/concord/otrunk-examples/
BasicExamples/basic_drawing.otml”)

thanks.

cfp:~ > rails test --database=sqlite3 > /dev/null 2>&1 && cd test

cfp:~/test > ./script/console
Loading development environment.

c = ActiveRecord::Base.connection
=> #<ActiveRecord::ConnectionAdapters::SQLite3Adapter:0x345227c
@connection=#<SQLite3::Database:0x3462c44
@statement_factory=SQLite3::Statement, @results_as_hash=true,
@transaction_active=false, @handle=#SWIG::TYPE_p_sqlite3:0x34522a4,
@translator=nil, @driver=#<SQLite3::Driver::Native::Driver:0x345236c
@callback_data={}, @trace={}, @busy_handler={}, @authorizer={}>,
@type_translation=false, @closed=false>, @last_verification=0,
@runtime=0, @logger=#<Logger:0x367331c @logdev=#<Logger::LogDevice:
0x3673164 @filename=“script/…/config/…/config/…/log/
development.log”, @mutex=#<Logger::LogDevice::LogDeviceMutex:
0x3673074 @mon_owner=nil, @mon_waiting_queue=[], @mon_entering_queue=
[], @mon_count=0>, @dev=#<File:script/…/config/…/config/…/log/
development.log>, @shift_size=1048576, @shift_age=0>, @formatter=nil,
@default_formatter=#<Logger::Formatter:0x36731f0
@datetime_format=nil>, @level=0, @progname=nil>>

c.execute ’ create table foos( a text, b text ) ’
=> []

class Foo < ActiveRecord::Base; end
=> nil

Foo.create :a => ‘4’, :b => ‘2’
=> #<Foo:0x344a3c4 @errors=#<ActiveRecord::Errors:0x3447b10 @errors=
{}, @base=#<Foo:0x344a3c4 …>>, @attributes={“a”=>“4”, “b”=>“2”,
“id”=>1}, @new_record=false>

Foo.find_by_a ‘4’
=> #<Foo:0x3443ec0 @attributes={“a”=>“4”, “b”=>“2”}>

Foo.find_by_b ‘2’
=> #<Foo:0x34419a4 @attributes={“a”=>“4”, “b”=>“2”}>

require ‘arrayfields’
=> [“ArrayFields”, “Fieldedarray”, “Arrayfields”, “PseudoHash”,
“Fieldable”, “Pseudohash”, “FieldedArray”]

p Arrayfields.version
“4.2.0”
=> nil

Foo.find_by_a ‘4’
=> #<Foo:0x342bfb4 @attributes={“a”=>“4”, “b”=>“2”}>

Foo.find_by_b ‘2’
=> #<Foo:0x3429a98 @attributes={“a”=>“4”, “b”=>“2”}>

on rubyforge now.

a @ http://drawohara.com/

On Sep 17, 2007, at 4:49 PM, Jeremy H. wrote:

thanks.

cfp:~/src/ruby/arrayfields/arrayfields-4.2.0 > cat a.rb
require ‘rubygems’
require ‘arrayfields’
puts “ruby version : #{RUBY_VERSION}”
puts “gems version : #{Gem::RubyGemsVersion}”
puts “arrayfields version : #{ArrayFields::VERSION}”
require ‘rake’
puts 42

cfp:~/src/ruby/arrayfields/arrayfields-4.2.0 > ruby a.rb
ruby version : 1.8.6
gems version : 0.9.2
arrayfields version : 4.2.0
42

on rubyforge now.

a @ http://drawohara.com/

On Sep 14, 2007, at 8:56 PM, ara.t.howard wrote:

  p a.at('one')                      #=> 1
  p a.values_at('zero', 'two')       #=> [0, 2]
#
# assigmnet is allowed
#
  a['zero'] = 42
  p a['zero']                        #=> 0

Surely, the last line above contains a typo. Shouldn’t it be

  p a['zero']                        #=> 42

Regards, Morton

On Sat, Sep 15, 2007 at 01:24:22PM +0900, ara.t.howard wrote:

therein lies the problem with writing documentation :wink:

if you check most of my new stuff the examples generate the README
for exactly the reason that i have fat fingers :wink:

thx.

Bug for you…

% cat af-bug.rb
require 'rubygems'
require 'arrayfields'
puts "ruby version        : #{RUBY_VERSION}"
puts "gems version        : #{Gem::RubyGemsVersion}"
puts "arrayfields version : #{ArrayFields::VERSION}"
require 'rake'
puts 42


% ruby af-bug.rb
ruby version        : 1.8.6
gems version        : 0.9.2
arrayfields version : 4.1.0
/opt/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:28:in 

initialize': <nil> not inject-able (ArgumentError) from /opt/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:16:innew’
from
/opt/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:16:in
new' from /opt/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:286:infields=’
from
/opt/local/lib/ruby/gems/1.8/gems/arrayfields-4.1.0/lib/arrayfields.rb:305:in
dup' from /opt/local/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1304 from /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:ingem_original_require’
from
/opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in
`require’
from af-bug.rb:6

Order matters, require ‘rake’ before arrayfields and there is no error.

enjoy,

-jeremy

On Sep 14, 2007, at 9:36 PM, Morton G. wrote:

Surely, the last line above contains a typo. Shouldn’t it be

  p a['zero']                        #=> 42

Regards, Morton

therein lies the problem with writing documentation :wink:

if you check most of my new stuff the examples generate the README
for exactly the reason that i have fat fingers :wink:

thx.

a @ http://drawohara.com/