restruct 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +22 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +40 -0
- data/Rakefile +17 -0
- data/lib/restruct.rb +30 -0
- data/lib/restruct/array.rb +188 -0
- data/lib/restruct/hash.rb +124 -0
- data/lib/restruct/id.rb +20 -0
- data/lib/restruct/marshal_array.rb +5 -0
- data/lib/restruct/marshal_hash.rb +5 -0
- data/lib/restruct/marshal_set.rb +5 -0
- data/lib/restruct/marshalizable.rb +13 -0
- data/lib/restruct/nested_hash.rb +108 -0
- data/lib/restruct/set.rb +119 -0
- data/lib/restruct/structure.rb +32 -0
- data/lib/restruct/version.rb +3 -0
- data/restruct.gemspec +30 -0
- data/spec/array_spec.rb +338 -0
- data/spec/coverage_helper.rb +8 -0
- data/spec/hash_spec.rb +242 -0
- data/spec/id_spec.rb +48 -0
- data/spec/minitest_helper.rb +21 -0
- data/spec/nested_hash_spec.rb +205 -0
- data/spec/set_spec.rb +257 -0
- metadata +192 -0
data/lib/restruct/id.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Restruct
|
2
|
+
class Id < String
|
3
|
+
|
4
|
+
attr_reader :separator
|
5
|
+
|
6
|
+
def initialize(id, separator=nil)
|
7
|
+
@separator = separator || Restruct.id_separator
|
8
|
+
super id.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](id)
|
12
|
+
Id.new "#{to_s}#{separator}#{id}", separator
|
13
|
+
end
|
14
|
+
|
15
|
+
def sections
|
16
|
+
split(separator).map { |s| Id.new s, separator }
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Restruct
|
2
|
+
class NestedHash
|
3
|
+
|
4
|
+
def self.new(type)
|
5
|
+
Class.new Structure do
|
6
|
+
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
const_set :TYPE, type
|
10
|
+
|
11
|
+
def [](key)
|
12
|
+
self.class::TYPE.new id: id[key], redis: redis, parent: self
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch(key)
|
16
|
+
raise KeyError, "key not found: #{key}" unless key? key
|
17
|
+
self[key]
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete(key)
|
21
|
+
self[key].tap(&:destroy)
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete_if
|
25
|
+
each { |k,v| delete k if yield k, v }
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def keep_if
|
30
|
+
each { |k,v| delete k unless yield k, v }
|
31
|
+
self
|
32
|
+
end
|
33
|
+
alias_method :select!, :keep_if
|
34
|
+
|
35
|
+
def clear
|
36
|
+
destroy
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def keys
|
41
|
+
sections = id.sections.count + 1
|
42
|
+
redis.call('KEYS', id['*']).map do |k|
|
43
|
+
Id.new(k).sections.take(sections).last
|
44
|
+
end.uniq.sort
|
45
|
+
end
|
46
|
+
|
47
|
+
def values
|
48
|
+
keys.map { |key| self[key] }
|
49
|
+
end
|
50
|
+
|
51
|
+
def values_at(*keys)
|
52
|
+
keys.map { |key| self[key] }
|
53
|
+
end
|
54
|
+
|
55
|
+
def key?(key)
|
56
|
+
keys.include? key.to_s
|
57
|
+
end
|
58
|
+
alias_method :has_key?, :key?
|
59
|
+
|
60
|
+
def size
|
61
|
+
keys.count
|
62
|
+
end
|
63
|
+
alias_method :count, :size
|
64
|
+
alias_method :length, :size
|
65
|
+
|
66
|
+
def empty?
|
67
|
+
size == 0
|
68
|
+
end
|
69
|
+
|
70
|
+
def each
|
71
|
+
keys.each { |key| yield key, self[key] }
|
72
|
+
end
|
73
|
+
alias_method :each_pair, :each
|
74
|
+
|
75
|
+
def each_key
|
76
|
+
each { |k,v| yield k }
|
77
|
+
end
|
78
|
+
|
79
|
+
def each_value
|
80
|
+
each { |k,v| yield v }
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_h
|
84
|
+
each_with_object({}) do |(key, value), hash|
|
85
|
+
hash[key] = value.respond_to?(:to_primitive) ? value.to_primitive : value
|
86
|
+
end
|
87
|
+
end
|
88
|
+
alias_method :to_primitive, :to_h
|
89
|
+
|
90
|
+
def dump
|
91
|
+
each_with_object({}) do |(key, value), hash|
|
92
|
+
hash[key] = value.dump
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def restore(dump)
|
97
|
+
dump.each { |f,d| self[f].restore d }
|
98
|
+
end
|
99
|
+
|
100
|
+
def destroy
|
101
|
+
values.each(&:destroy)
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
data/lib/restruct/set.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
module Restruct
|
2
|
+
class Set < Structure
|
3
|
+
|
4
|
+
include Enumerable
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def_delegators :to_set, :union, :|, :+,
|
8
|
+
:intersection, :&,
|
9
|
+
:difference, :-,
|
10
|
+
:proper_subset?, :subset?,
|
11
|
+
:proper_superset?, :superset?,
|
12
|
+
:^
|
13
|
+
|
14
|
+
def add(member)
|
15
|
+
_add member
|
16
|
+
self
|
17
|
+
end
|
18
|
+
alias_method :<<, :add
|
19
|
+
|
20
|
+
def add?(member)
|
21
|
+
_add(member) == 0 ? nil : self
|
22
|
+
end
|
23
|
+
|
24
|
+
def merge(members)
|
25
|
+
_add *members
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete(member)
|
30
|
+
_delete member
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete?(member)
|
35
|
+
_delete(member) == 0 ? nil : self
|
36
|
+
end
|
37
|
+
|
38
|
+
def subtract(members)
|
39
|
+
_delete *members
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete_if
|
44
|
+
each { |e| delete e if yield e }
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def keep_if
|
49
|
+
each { |e| delete e unless yield e }
|
50
|
+
self
|
51
|
+
end
|
52
|
+
alias_method :select!, :keep_if
|
53
|
+
|
54
|
+
def clear
|
55
|
+
destroy
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
def size
|
60
|
+
redis.call 'SCARD', id
|
61
|
+
end
|
62
|
+
alias_method :count, :size
|
63
|
+
alias_method :length, :size
|
64
|
+
|
65
|
+
def empty?
|
66
|
+
size == 0
|
67
|
+
end
|
68
|
+
|
69
|
+
def include?(member)
|
70
|
+
redis.call('SISMEMBER', id, serialize(member)) == 1
|
71
|
+
end
|
72
|
+
|
73
|
+
def each(&block)
|
74
|
+
to_a.each(&block)
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_a
|
78
|
+
redis.call('SMEMBERS', id).map { |e| deserialize e }
|
79
|
+
end
|
80
|
+
|
81
|
+
def to_set
|
82
|
+
to_a.to_set
|
83
|
+
end
|
84
|
+
alias_method :to_primitive, :to_set
|
85
|
+
|
86
|
+
alias_method :<, :proper_subset?
|
87
|
+
alias_method :<=, :subset?
|
88
|
+
alias_method :>, :proper_superset?
|
89
|
+
alias_method :>=, :superset?
|
90
|
+
|
91
|
+
def intersect?(set)
|
92
|
+
!disjoint? set
|
93
|
+
end
|
94
|
+
|
95
|
+
def disjoint?(set)
|
96
|
+
(to_a & set.to_a).empty?
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def _add(*members)
|
102
|
+
redis.call 'SADD', id, *members.map { |m| serialize m }
|
103
|
+
end
|
104
|
+
|
105
|
+
def _delete(*members)
|
106
|
+
redis.call 'SREM', id, *members.map { |m| serialize m }
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
def serialize(string)
|
111
|
+
string
|
112
|
+
end
|
113
|
+
|
114
|
+
def deserialize(string)
|
115
|
+
string
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Restruct
|
2
|
+
class Structure
|
3
|
+
|
4
|
+
attr_reader :redis, :id
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
@redis = options[:redis] || Restruct.redis
|
8
|
+
@id = Id.new options[:id] || Restruct.generate_id
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(object)
|
12
|
+
object.class == self.class &&
|
13
|
+
object.id == id &&
|
14
|
+
object.redis == redis
|
15
|
+
end
|
16
|
+
alias_method :eql?, :==
|
17
|
+
|
18
|
+
def dump
|
19
|
+
redis.call 'DUMP', id
|
20
|
+
end
|
21
|
+
|
22
|
+
def restore(dump)
|
23
|
+
destroy
|
24
|
+
redis.call 'RESTORE', id, 0, dump
|
25
|
+
end
|
26
|
+
|
27
|
+
def destroy
|
28
|
+
redis.call 'DEL', id
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/restruct.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'restruct/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'restruct'
|
8
|
+
spec.version = Restruct::VERSION
|
9
|
+
spec.authors = ['Gabriel Naiman']
|
10
|
+
spec.email = ['gabynaiman@gmail.com']
|
11
|
+
spec.summary = 'Redis structures'
|
12
|
+
spec.description = 'Redis structures'
|
13
|
+
spec.homepage = 'https://github.com/gabynaiman/restruct'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'redic', '~> 1.1.1'
|
22
|
+
spec.add_dependency 'class_config', '~> 0.0.1'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'minitest', '~> 4.7'
|
27
|
+
spec.add_development_dependency 'turn', '~> 0.9'
|
28
|
+
spec.add_development_dependency 'simplecov'
|
29
|
+
spec.add_development_dependency 'pry-nav'
|
30
|
+
end
|
data/spec/array_spec.rb
ADDED
@@ -0,0 +1,338 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
[Restruct::Array, Restruct::MarshalArray].each do |klass|
|
4
|
+
|
5
|
+
describe klass do
|
6
|
+
|
7
|
+
let(:array) { klass.new }
|
8
|
+
|
9
|
+
def fill(elements)
|
10
|
+
redis.call 'RPUSH', array.id, *(elements.map { |e| array.send(:serialize, e) })
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'Getters' do
|
14
|
+
|
15
|
+
it '[]' do
|
16
|
+
fill %w(a b c d e)
|
17
|
+
|
18
|
+
array[0].must_equal 'a'
|
19
|
+
array[1].must_equal 'b'
|
20
|
+
array[2].must_equal 'c'
|
21
|
+
array[6].must_be_nil
|
22
|
+
|
23
|
+
array[0..-1].must_equal %w(a b c d e)
|
24
|
+
array[1..3].must_equal %w(b c d)
|
25
|
+
array[4..7].must_equal ['e']
|
26
|
+
array[5..10].must_equal []
|
27
|
+
array[6..10].must_be_nil
|
28
|
+
|
29
|
+
array[-3,3].must_equal %w(c d e)
|
30
|
+
array[1,2].must_equal %w(b c)
|
31
|
+
array[5,1].must_equal []
|
32
|
+
array[6,1].must_be_nil
|
33
|
+
|
34
|
+
error = proc { array[1,2,3,4] }.must_raise ArgumentError
|
35
|
+
error.message.must_equal 'wrong number of arguments (4 for 1..2)'
|
36
|
+
|
37
|
+
error = proc { array['x'] }.must_raise TypeError
|
38
|
+
error.message.must_equal 'no implicit conversion from string to integer'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'at' do
|
42
|
+
fill %w(a b c d)
|
43
|
+
|
44
|
+
array.at(0).must_equal 'a'
|
45
|
+
array.at(1).must_equal 'b'
|
46
|
+
array.at(-1).must_equal 'd'
|
47
|
+
array.at(10).must_be_nil
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'values_at' do
|
51
|
+
fill %w(a b c d e f)
|
52
|
+
|
53
|
+
array.values_at(1, 3, 5).must_equal %w(b d f)
|
54
|
+
array.values_at(1, 3, 5, 7).must_equal ['b', 'd', 'f', nil]
|
55
|
+
array.values_at(-1, -2, -2, -7).must_equal ['f', 'e', 'e', nil]
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'fetch' do
|
59
|
+
fill %w(a b c)
|
60
|
+
|
61
|
+
array.fetch(-1).must_equal 'c'
|
62
|
+
array.fetch(0).must_equal 'a'
|
63
|
+
array.fetch(4, 'x').must_equal 'x'
|
64
|
+
array.fetch(4) { |i| (i + 1).to_s }.must_equal '5'
|
65
|
+
|
66
|
+
error = proc { array.fetch(4) }.must_raise IndexError
|
67
|
+
error.message.must_equal 'index 4 outside of array bounds: -3...3'
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'first' do
|
71
|
+
fill %w(a b c)
|
72
|
+
array.first.must_equal 'a'
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'last' do
|
76
|
+
fill %w(a b c)
|
77
|
+
array.last.must_equal 'c'
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'Setters' do
|
83
|
+
|
84
|
+
it '[]=' do
|
85
|
+
fill %w(a b c d)
|
86
|
+
|
87
|
+
(array[0] = 'x').must_equal 'x'
|
88
|
+
array.to_a.must_equal %w(x b c d)
|
89
|
+
|
90
|
+
(array[-1] = 'z').must_equal 'z'
|
91
|
+
array.to_a.must_equal %w(x b c z)
|
92
|
+
|
93
|
+
error = proc { array[10] = '.' }.must_raise IndexError
|
94
|
+
error.message.must_equal 'index 10 outside of array bounds: -4...4'
|
95
|
+
|
96
|
+
error = proc { array['k'] = '.' }.must_raise TypeError
|
97
|
+
error.message.must_equal 'no implicit conversion from string to integer'
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'push' do
|
101
|
+
fill %w(a b c)
|
102
|
+
|
103
|
+
array.push('d').must_equal array
|
104
|
+
array.to_a.must_equal %w(a b c d)
|
105
|
+
|
106
|
+
array.push('x', 'y', 'z').must_equal array
|
107
|
+
array.to_a.must_equal %w(a b c d x y z)
|
108
|
+
end
|
109
|
+
|
110
|
+
it '<<' do
|
111
|
+
fill %w(a b c)
|
112
|
+
|
113
|
+
(array << 'd').must_equal array
|
114
|
+
array.to_a.must_equal %w(a b c d)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'pop' do
|
118
|
+
fill %w(a b c d e f)
|
119
|
+
|
120
|
+
(array.pop).must_equal 'f'
|
121
|
+
array.to_a.must_equal %w(a b c d e)
|
122
|
+
|
123
|
+
(array.pop(2)).must_equal %w(d e)
|
124
|
+
array.to_a.must_equal %w(a b c)
|
125
|
+
|
126
|
+
(array.pop(5)).must_equal %w(a b c)
|
127
|
+
array.to_a.must_equal []
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'shift' do
|
131
|
+
fill %w(a b c d e f)
|
132
|
+
|
133
|
+
(array.shift).must_equal 'a'
|
134
|
+
array.to_a.must_equal %w(b c d e f)
|
135
|
+
|
136
|
+
(array.shift(2)).must_equal %w(b c)
|
137
|
+
array.to_a.must_equal %w(d e f)
|
138
|
+
|
139
|
+
(array.shift(5)).must_equal %w(d e f)
|
140
|
+
array.to_a.must_equal []
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'insert' do
|
144
|
+
fill %w(a b c d)
|
145
|
+
|
146
|
+
array.insert(0, 'A').must_equal array
|
147
|
+
array.to_a.must_equal %w(A a b c d)
|
148
|
+
|
149
|
+
array.insert(2, 'B', 'B').must_equal array
|
150
|
+
array.to_a.must_equal %w(A a B B b c d)
|
151
|
+
|
152
|
+
array.insert(-2, 'x', 'y', 'z').must_equal array
|
153
|
+
array.to_a.must_equal %w(A a B B b c x y z d)
|
154
|
+
|
155
|
+
array.insert(-5, 'w').must_equal array
|
156
|
+
array.to_a.must_equal %w(A a B B b c w x y z d)
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'concat' do
|
160
|
+
fill %w(a b c)
|
161
|
+
|
162
|
+
array.concat(%w(x y z)).must_equal array
|
163
|
+
array.to_a.must_equal %w(a b c x y z)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'delete' do
|
167
|
+
fill %w(a b a b a b)
|
168
|
+
|
169
|
+
array.delete('b').must_equal 'b'
|
170
|
+
array.to_a.must_equal %w(a a a)
|
171
|
+
|
172
|
+
array.delete('c').must_be_nil
|
173
|
+
array.to_a.must_equal %w(a a a)
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'delete_at' do
|
177
|
+
fill %w(a b c a b c a b c)
|
178
|
+
|
179
|
+
array.delete_at(3).must_equal 'a'
|
180
|
+
array.to_a.must_equal %w(a b c b c a b c)
|
181
|
+
|
182
|
+
array.delete_at(-4).must_equal 'c'
|
183
|
+
array.to_a.must_equal %w(a b c b a b c)
|
184
|
+
|
185
|
+
array.delete_at(10).must_be_nil
|
186
|
+
array.to_a.must_equal %w(a b c b a b c)
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'delete_if' do
|
190
|
+
fill %w(a b c a b c a b c)
|
191
|
+
|
192
|
+
array.delete_if { |e| e == 'a' }.must_equal array
|
193
|
+
array.to_a.must_equal %w(b c b c b c)
|
194
|
+
end
|
195
|
+
|
196
|
+
%w(keep_if select!).each do |method|
|
197
|
+
it method do
|
198
|
+
fill %w(a b c a b c a b c)
|
199
|
+
|
200
|
+
array.send(method) { |e| e == 'a' }.must_equal array
|
201
|
+
array.to_a.must_equal %w(a a a)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'clear' do
|
206
|
+
fill %w(a b c d)
|
207
|
+
|
208
|
+
array.clear.must_equal array
|
209
|
+
array.must_be_empty
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
describe 'Info' do
|
215
|
+
|
216
|
+
%w(size count length).each do |method|
|
217
|
+
it method do
|
218
|
+
fill %w(a b c)
|
219
|
+
array.send(method).must_equal 3
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'empty?' do
|
224
|
+
array.must_be :empty?
|
225
|
+
fill %w(a b c)
|
226
|
+
array.wont_be :empty?
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'include?' do
|
230
|
+
fill %w(a b c)
|
231
|
+
|
232
|
+
assert array.include? 'a'
|
233
|
+
refute array.include? 'z'
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
describe 'Transformations' do
|
239
|
+
|
240
|
+
%w(to_a to_ary to_primitive).each do |method|
|
241
|
+
it method do
|
242
|
+
fill %w(a b c)
|
243
|
+
array.send(method).must_equal %w(a b c)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'join' do
|
248
|
+
fill %w(a b c)
|
249
|
+
|
250
|
+
array.join.must_equal 'abc'
|
251
|
+
array.join('-').must_equal 'a-b-c'
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'uniq' do
|
255
|
+
fill %w(a1 a1 a2 a2 b1 b1 b2 b2)
|
256
|
+
|
257
|
+
array.uniq.must_equal %w(a1 a2 b1 b2)
|
258
|
+
array.uniq { |e| e[1] }.must_equal %w(a1 a2)
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'reverse' do
|
262
|
+
fill %w(a b c)
|
263
|
+
array.reverse.must_equal %w(c b a)
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
describe 'Enumerable' do
|
269
|
+
|
270
|
+
it 'included module' do
|
271
|
+
assert klass.included_modules.include? Enumerable
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'each' do
|
275
|
+
fill %w(a b c)
|
276
|
+
|
277
|
+
list = []
|
278
|
+
array.each { |e| list << e }
|
279
|
+
|
280
|
+
list.must_equal array.to_a
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'each_index' do
|
284
|
+
fill %w(a b c)
|
285
|
+
|
286
|
+
list = []
|
287
|
+
array.each_index { |i| list << i }
|
288
|
+
|
289
|
+
list.must_equal [0,1,2]
|
290
|
+
end
|
291
|
+
|
292
|
+
end
|
293
|
+
|
294
|
+
describe 'Sets' do
|
295
|
+
|
296
|
+
it '+' do
|
297
|
+
fill %w(a b c)
|
298
|
+
(array + %w(x y z)).must_equal %w(a b c x y z)
|
299
|
+
end
|
300
|
+
|
301
|
+
it '-' do
|
302
|
+
fill %w(a b c)
|
303
|
+
(array - %w(a z)).must_equal %w(b c)
|
304
|
+
end
|
305
|
+
|
306
|
+
it '&' do
|
307
|
+
fill %w(a b c)
|
308
|
+
(array & %w(b a z)).must_equal %w(a b)
|
309
|
+
end
|
310
|
+
|
311
|
+
it '|' do
|
312
|
+
fill %w(a b c)
|
313
|
+
(array | %w(b c d)).must_equal %w(a b c d)
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'Equality' do
|
319
|
+
copy = klass.new id: array.id
|
320
|
+
assert array == copy
|
321
|
+
assert array.eql? copy
|
322
|
+
refute array.equal? copy
|
323
|
+
end
|
324
|
+
|
325
|
+
it 'Dump/Restore' do
|
326
|
+
fill %w(a b c)
|
327
|
+
|
328
|
+
dump = array.dump
|
329
|
+
other = klass.new
|
330
|
+
other.restore dump
|
331
|
+
|
332
|
+
other.id.wont_equal array.id
|
333
|
+
other.to_primitive.must_equal array.to_primitive
|
334
|
+
end
|
335
|
+
|
336
|
+
end
|
337
|
+
|
338
|
+
end
|