------art_6998_25250935.1132751532399
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

I sent Ron the following two files to Ron a couple of days ago, and
received a nice reply.

This quick-and-dirty implementation only uses an Array to store
objects. Ron pointed out that it will be much more interesting if the
objects were stored in files, perhaps mapping objects to things like
fixed-length records.

Jim
--
Jim Menard, jim.menard / gmail.com, jimm / io.com
http://www.io.com/~jimm
"Any sufficiently complicated C or Fortran program contains an ad hoc
informally-specified bug-ridden slow implementation of half of Common Lisp."
    -- Greenspun's Tenth Rule of Programming

------art_6998_25250935.1132751532399
Content-Type: application/octet-stream; name=record_set.rb
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="record_set.rb"

# http://www.xprogramming.com/xpmag/xstSomeThoughts.htm

require 'delegate'

class Object

  # Return true if self's instance variables match
  def xst_match(restrict_query_obj)
    restrict_query_obj.instance_variables.each { | name |
      restrict_value  estrict_query_obj.instance_variable_get(name)
      return false if restrict_value ! il &&
        !(restrict_value  self.instance_variable_get(name))
    }
    return true
  end
end

class RecordSet < DelegateClass(Array)

  def initialize(array)
    super(array)
  end

  def restrict(*restrictions)
    return select { | item |
      restrictions.detect { | restriction | item.xst_match(restriction) }
    }
  end

end
  



------art_6998_25250935.1132751532399
Content-Type: application/octet-stream; name=test.rb
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="test.rb"

#!/usr/bin/env ruby

require 'test/unit'
require 'test/unit/ui/console/testrunner' # Only required on Windows
require 'record_set'

# For testing: a class with a few attributes.
class Something
  attr_accessor :name, :email, :age # Not required for XST to work
  def initialize(namel, emaill, agel)
    @name, @email, @age  ame, email, age
  end
  def to_s
    "name  @name, age  @age, email  @email"
  end
end

class RecordSetTest < Test::Unit::TestCase

  def setup
    @rs  ecordSet.new
    @rs << (@jimmy  omething.new('Jimmy Neutron', 'jimmy / example.com', 12))
    @rs << Something.new('Spongebob Squarepants')
    @rs << Something.new(nil, 'foo / example.com', 22)
  end

  def test_match_self
    @rs.each { | obj | assert obj.xst_match(obj) }
  end

  def test_match_nil
    assert nil.xst_match(nil)
    assert @jimmy.xst_match(nil)
  end

  def test_not_match_nil
    assert !nil.xst_match(@jimmy)
  end

  def test_match
    assert_equal 'Jimmy Neutron', @jimmy.name
    assert @jimmy.xst_match(Something.new) # All nil values
    assert @jimmy.xst_match(Something.new('Jimmy Neutron'))
    assert @jimmy.xst_match(Something.new(nil, 'jimmy / example.com'))
    assert @jimmy.xst_match(Something.new(nil, nil, 12))
    assert @jimmy.xst_match(Something.new('Jimmy Neutron',
                                          'jimmy / example.com'))
    assert @jimmy.xst_match(Something.new('Jimmy Neutron',
                                          'jimmy / example.com', 12))
    assert @jimmy.xst_match(Something.new(nil, 'jimmy / example.com', 12))
    assert @jimmy.xst_match(Something.new('Jimmy Neutron', nil, 12))
  end

  def test_not_match
    assert !@jimmy.xst_match(Something.new('Jimmy Neutron', nil, 99))
    assert !@jimmy.xst_match(Something.new('Jimmy Neutron',
                                           'jimmy / example.com', 99))
    assert !@jimmy.xst_match(Something.new(/N..tron/, nil, 99))
  end

  def test_regex_match
    assert @jimmy.xst_match(Something.new(/N..tron/))
  end

  def test_simple_restrict
    found  rs.restrict(Something.new('Jimmy Neutron'))
    assert_not_nil found
    assert_equal 1, found.length
    assert_equal 'Jimmy Neutron', found[0].name
  end

  def test_restrict_array
    found  rs.restrict(Something.new('Jimmy Neutron'),
                         Something.new(nil, 'foo / example.com'))
    assert_not_nil found
    assert_equal 2, found.length
    # These tests rely upon the ordering of the records in the record set
    assert_equal 'Jimmy Neutron', found[0].name
    assert_equal 'foo / example.com', found[1].email
  end

  def test_regex_restrict
    found  rs.restrict(Something.new(/Ne..ron/))
    assert_not_nil found
    assert_equal 1, found.length
    assert_equal 'Jimmy Neutron', found[0].name
  end

  def test_regex_array_restrict
    found  rs.restrict(Something.new(/Ne..ron/),
                         Something.new(nil, 'foo / example.com'))
    assert_not_nil found
    assert_equal 2, found.length
    # These tests rely upon the ordering of the records in the record set
    assert_equal 'Jimmy Neutron', found[0].name
    assert_equal 'foo / example.com', found[1].email
  end

  def test_length
    assert_equal 3, @rs.length
  end

end

# This is required on Windows; not on *nix
if __FILE__ $0
  Test::Unit::UI::Console::TestRunner.run(RecordSetTest)
end



------art_6998_25250935.1132751532399--