Skip to content

Commit

Permalink
Initial implementation of an array collection class
Browse files Browse the repository at this point in the history
Basically like a regular Ruby array, except it has :build support
and :inject does key/value pairs per iteration instead of just values,
to be compatible with hash-like :inject.
  • Loading branch information
Ethan Rowe committed May 18, 2010
1 parent 4386f25 commit f46b2ec
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 3 deletions.
26 changes: 23 additions & 3 deletions lib/simple_mapper/collection.rb
@@ -1,15 +1,35 @@
require 'delegate'
module SimpleMapper
module Collection
class Hash < DelegateClass(::Hash)
module CommonMethods
attr_accessor :attribute

def build(*args)
attribute.mapper.new(*args)
end
end

class Hash < DelegateClass(::Hash)
include CommonMethods

def initialize(hash = {})
super(hash)
end
end

def build(*args)
attribute.mapper.new(*args)
class Array < DelegateClass(::Array)
include CommonMethods

def initialize(array=[])
super(array)
end

def keys
(0..size - 1).to_a
end

def inject(*args)
(0..size - 1).inject(*args) {|accum, key| yield(accum, [key, self[key]])}
end
end
end
Expand Down
67 changes: 67 additions & 0 deletions test/unit/collection_array_test.rb
@@ -0,0 +1,67 @@
require 'test_helper'
class CollectionArrayTest < Test::Unit::TestCase
context 'A SimpleMapper::Collection::Array' do
setup do
@class = SimpleMapper::Collection::Array
end

should 'be equivalent to a standard Array' do
array = [:a, :b, :c]
instance = @class.new(array)
assert_equal array, instance
assert_equal @class, instance.class
end

should 'allow array-style assignments, lookups, size checks, etc' do
instance = @class.new
assert_equal 0, instance.size
instance << :a
assert_equal 1, instance.size
assert_equal :a, instance[0]
instance[4] = :b
assert_equal 5, instance.size
assert_equal [:a, nil, nil, nil, :b], instance
end

should 'disallow non-integer indexes' do
instance = @class.new
assert_raise(TypeError) { instance[:a] = 'a' }
end

should 'provide list of indexes via :keys' do
assert_equal (0..3).to_a, @class.new([:a, :b, :c, :d]).keys
end

should 'yield key/value pairs instead of just value for :inject' do
source = [:a, :b, :c, :d, :e]
expected = (0..(source.size - 1)).to_a.collect {|key| [key, source[key]]}
result = @class.new(source).inject([]) {|a, pair| a << pair; a}
assert_equal expected, result
end

should 'have an :attribute attribute' do
instance = @class.new
assert_equal nil, instance.attribute
attrib = stub('attribute')
assert_equal attrib, instance.attribute = attrib
assert_equal attrib, instance.attribute
end

should 'allow creation of new mapper instances through :build' do
mapper = stub('mapper')
attrib = stub('attrib', :mapper => mapper)
seq = sequence('build invocations')
mapper.expects(:new).with.in_sequence(seq).returns(:one)
mapper.expects(:new).with(:a => 'A').in_sequence(seq).returns(:two)
mapper.expects(:new).with(:a, :b, :c).in_sequence(seq).returns(:three)
instance = @class.new
instance.attribute = attrib
result = []
result << instance.build
result << instance.build(:a => 'A')
result << instance.build(:a, :b, :c)
assert_equal [:one, :two, :three], result
end

end
end

0 comments on commit f46b2ec

Please sign in to comment.