object_table 0.1.0
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/.gitignore +34 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +322 -0
- data/Rakefile +5 -0
- data/lib/object_table/basic_grid.rb +33 -0
- data/lib/object_table/column.rb +80 -0
- data/lib/object_table/grouped.rb +58 -0
- data/lib/object_table/masked_column.rb +54 -0
- data/lib/object_table/table_methods.rb +146 -0
- data/lib/object_table/temp_grouped.rb +43 -0
- data/lib/object_table/temp_view.rb +63 -0
- data/lib/object_table/version.rb +3 -0
- data/lib/object_table/view.rb +24 -0
- data/lib/object_table/view_methods.rb +22 -0
- data/lib/object_table.rb +86 -0
- data/object_table.gemspec +27 -0
- data/spec/object_table/basic_grid_spec.rb +80 -0
- data/spec/object_table/column_spec.rb +128 -0
- data/spec/object_table/grouped_spec.rb +115 -0
- data/spec/object_table/masked_column_spec.rb +132 -0
- data/spec/object_table/temp_grouped_spec.rb +105 -0
- data/spec/object_table/temp_view_spec.rb +209 -0
- data/spec/object_table/view_spec.rb +140 -0
- data/spec/object_table_spec.rb +232 -0
- data/spec/support/object_table_example.rb +314 -0
- metadata +135 -0
@@ -0,0 +1,232 @@
|
|
1
|
+
require 'object_table'
|
2
|
+
|
3
|
+
require 'support/object_table_example'
|
4
|
+
|
5
|
+
describe ObjectTable do
|
6
|
+
it_behaves_like 'an object table', ObjectTable
|
7
|
+
|
8
|
+
describe '#initialize' do
|
9
|
+
let(:columns){ {col1: [1, 2, 3], col2: NArray[4, 5, 6], col3: 7..9, col4: 10} }
|
10
|
+
subject{ ObjectTable.new columns }
|
11
|
+
|
12
|
+
it 'should convert all columns into ObjectTable::Columns' do
|
13
|
+
subject.columns.values.each do |v|
|
14
|
+
expect(v).to be_a ObjectTable::Column
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should include all the columns' do
|
19
|
+
grid = ObjectTable::BasicGrid[columns]
|
20
|
+
grid._ensure_uniform_columns!
|
21
|
+
|
22
|
+
grid.each do |k, v|
|
23
|
+
expect(subject[k].to_a).to eql v.to_a
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with multi dimensional columns' do
|
28
|
+
let(:columns){ {col1: [1, 2, 3], col2: NArray[[4, 4], [5, 5], [6, 6]]} }
|
29
|
+
|
30
|
+
it 'should convert all columns into ObjectTable::Columns' do
|
31
|
+
subject.columns.values.each do |v|
|
32
|
+
expect(v).to be_a ObjectTable::Column
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should include all the columns' do
|
37
|
+
grid = ObjectTable::BasicGrid[columns]
|
38
|
+
grid._ensure_uniform_columns!
|
39
|
+
|
40
|
+
grid.each do |k, v|
|
41
|
+
expect(subject[k].to_a).to eql v.to_a
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should preserve the dimensions' do
|
46
|
+
expect(subject[:col2].shape).to eql columns[:col2].shape
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
context '#set_column' do
|
53
|
+
let(:value){ [4, 5, 6] }
|
54
|
+
let(:args) { [] }
|
55
|
+
let(:table){ ObjectTable.new(col1: [1, 2, 3], col2: 5) }
|
56
|
+
|
57
|
+
let(:column) { table.colnames[0] }
|
58
|
+
|
59
|
+
subject{ table.set_column(column, value, *args) }
|
60
|
+
|
61
|
+
it 'should allow assigning columns' do
|
62
|
+
subject
|
63
|
+
expect(table.columns[column].to_a).to eql value
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should coerce the value to a column' do
|
67
|
+
subject
|
68
|
+
expect(table.columns[column]).to be_a ObjectTable::Column
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'with the wrong length' do
|
72
|
+
let(:value) { [1, 2] }
|
73
|
+
it 'should fail' do
|
74
|
+
expect{subject}.to raise_error
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'with a scalar' do
|
79
|
+
let(:value){ 10 }
|
80
|
+
it 'should fill the column with that value' do
|
81
|
+
subject
|
82
|
+
expect(table.columns[column].to_a).to eql ([value] * table.nrows)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'with a range' do
|
87
|
+
let(:value){ 0...3 }
|
88
|
+
it 'should assign the range values' do
|
89
|
+
subject
|
90
|
+
expect(table.columns[column].to_a).to eql value.to_a
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'for a new column' do
|
95
|
+
let(:column) { :col3 }
|
96
|
+
|
97
|
+
it 'should create a new column' do
|
98
|
+
subject
|
99
|
+
expect(table.columns).to include column
|
100
|
+
expect(table.columns[column].to_a).to eql value
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'with a range' do
|
104
|
+
let(:value){ 0...3 }
|
105
|
+
it 'should assign the range values' do
|
106
|
+
subject
|
107
|
+
expect(table.columns[column].to_a).to eql value.to_a
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'with an NArray' do
|
112
|
+
let(:value){ NArray.int(3, 4, table.nrows) }
|
113
|
+
|
114
|
+
it 'should use the narray parameters' do
|
115
|
+
subject
|
116
|
+
expect(table.columns[column].to_a).to eql value.to_a
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'when failed to add column' do
|
121
|
+
let(:value){ NArray[1, 2, 3] }
|
122
|
+
|
123
|
+
it 'should not have that column' do
|
124
|
+
expect(table).to receive(:add_column).with(column, value.typecode) do
|
125
|
+
table.columns[column] = 12345
|
126
|
+
end
|
127
|
+
|
128
|
+
# the assignment is going to chuck an error
|
129
|
+
subject rescue nil
|
130
|
+
expect(table.columns).to_not include column
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'with narray args' do
|
136
|
+
let(:args) { ['int', 3, 4] }
|
137
|
+
let(:value){ NArray.float(3, 4, table.nrows) }
|
138
|
+
|
139
|
+
context 'for a new column' do
|
140
|
+
let(:column) { :col3 }
|
141
|
+
|
142
|
+
it 'should create a column with the typecode' do
|
143
|
+
subject
|
144
|
+
expect(table.columns[column].typecode).to eql NArray.new(*args).typecode
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should create a column with the correct size' do
|
148
|
+
subject
|
149
|
+
expect(table.columns[column].shape[-1]).to eql table.nrows
|
150
|
+
expect(table.columns[column].shape[0...-1]).to eql args[1..-1]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
describe '#pop_column' do
|
159
|
+
let(:table) { ObjectTable.new(col1: [1, 2, 3], col2: 5) }
|
160
|
+
let(:name) { :col2 }
|
161
|
+
|
162
|
+
subject{ table.pop_column(name) }
|
163
|
+
|
164
|
+
it 'should remove the column' do
|
165
|
+
subject
|
166
|
+
expect(table.colnames).to_not include name
|
167
|
+
expect(table.columns).to_not include name
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'should return the column' do
|
171
|
+
column = table[name]
|
172
|
+
expect(subject).to be column
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe '.stack' do
|
177
|
+
let(:others) do
|
178
|
+
[
|
179
|
+
ObjectTable.new(col1: [1, 2, 3], col2: 5),
|
180
|
+
ObjectTable.new(col1: 10, col2: 50),
|
181
|
+
ObjectTable.new(col2: [10, 30], col1: 15).where{col2.eq 10},
|
182
|
+
ObjectTable::BasicGrid[col2: [1, 2], col1: [3, 4]],
|
183
|
+
]
|
184
|
+
end
|
185
|
+
|
186
|
+
subject{ ObjectTable.stack *others }
|
187
|
+
|
188
|
+
it 'should join the tables and grids together' do
|
189
|
+
expect(subject).to be_a ObjectTable
|
190
|
+
expect(subject).to eql ObjectTable.new(
|
191
|
+
col1: others.flat_map{|x| x[:col1].to_a},
|
192
|
+
col2: others.flat_map{|x| x[:col2].to_a},
|
193
|
+
)
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'should duplicate the contents' do
|
197
|
+
others.each do |chunk|
|
198
|
+
expect(subject).to_not be chunk
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context 'with non grids/tables' do
|
203
|
+
let(:others){ [ObjectTable.new(col1: 10, col2: 50), 'not a table'] }
|
204
|
+
|
205
|
+
it 'should fail' do
|
206
|
+
expect{subject}.to raise_error
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'with differing column names' do
|
211
|
+
let(:others){ [ObjectTable.new(col1: 10, col2: 50), ObjectTable.new(col1: 10, col3: 50)] }
|
212
|
+
|
213
|
+
it 'should fail' do
|
214
|
+
expect{subject}.to raise_error
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
describe '#sort_by!' do
|
220
|
+
let(:table){ ObjectTable.new(col1: [2, 2, 1, 1], col2: [0, 1, 0, 1], col3: [5, 6, 7, 8]) }
|
221
|
+
subject{ table.sort_by!(table.col1, table.col2) }
|
222
|
+
|
223
|
+
it 'should modify the table' do
|
224
|
+
expect(subject).to be table
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'should sort by the given columns' do
|
228
|
+
expect(subject).to eql table.sort_by(table.col1, table.col2)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
@@ -0,0 +1,314 @@
|
|
1
|
+
require 'object_table'
|
2
|
+
|
3
|
+
RSpec.shared_examples 'an object table' do |cls|
|
4
|
+
before do
|
5
|
+
@cls = cls
|
6
|
+
end
|
7
|
+
|
8
|
+
def _make_relevant_table(table)
|
9
|
+
if @cls == ObjectTable
|
10
|
+
table
|
11
|
+
|
12
|
+
elsif @cls == ObjectTable::TempView
|
13
|
+
table.stack! ObjectTable::BasicGrid[table.columns.map{|k, v| [k, v.max]}]
|
14
|
+
column = table.colnames.first
|
15
|
+
table[column][-1] += 1
|
16
|
+
table.where{table[column] < table[column][-1]}
|
17
|
+
|
18
|
+
elsif @cls == ObjectTable::View
|
19
|
+
table.stack! ObjectTable::BasicGrid[table.columns.map{|k, v| [k, v.max]}]
|
20
|
+
column = table.colnames.first
|
21
|
+
table[column][-1] += 1
|
22
|
+
table.where{table[column] < table[column][-1]}.apply{ self }
|
23
|
+
|
24
|
+
else
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
subject{ _make_relevant_table(table) }
|
30
|
+
|
31
|
+
describe '#inspect' do
|
32
|
+
let(:table){ ObjectTable.new(col1: 1..10, col2: 5) }
|
33
|
+
it 'should succeed' do
|
34
|
+
expect{subject.inspect}.to_not raise_error
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should have a header listing the dimensions' do
|
38
|
+
expect(subject.inspect.lines.to_a.first).to eql "#{subject.class}(#{subject.nrows}, #{subject.ncols})\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should include the column names at the top and bottom' do
|
42
|
+
expect(subject.inspect.lines.to_a[1].split).to eql subject.colnames.map(&:to_s)
|
43
|
+
expect(subject.inspect.lines.to_a[-1].split).to eql subject.colnames.map(&:to_s)
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'with few rows' do
|
47
|
+
let(:table){ ObjectTable.new(col1: 1..10, col2: 5) }
|
48
|
+
|
49
|
+
it 'should include all the rows' do
|
50
|
+
table = subject.inspect.lines.to_a[1..-1].join + "\n"
|
51
|
+
expect(table).to eql <<EOS
|
52
|
+
col1 col2
|
53
|
+
0: 1 5
|
54
|
+
1: 2 5
|
55
|
+
2: 3 5
|
56
|
+
3: 4 5
|
57
|
+
4: 5 5
|
58
|
+
5: 6 5
|
59
|
+
6: 7 5
|
60
|
+
7: 8 5
|
61
|
+
8: 9 5
|
62
|
+
9: 10 5
|
63
|
+
col1 col2
|
64
|
+
EOS
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'with many rows' do
|
69
|
+
let(:table){ ObjectTable.new(col1: 1..100, col2: 5) }
|
70
|
+
|
71
|
+
it 'should only include the top and bottom 5 rows' do
|
72
|
+
table = subject.inspect.lines.to_a[1..-1].join + "\n"
|
73
|
+
expect(table).to eql <<EOS
|
74
|
+
col1 col2
|
75
|
+
0: 1 5
|
76
|
+
1: 2 5
|
77
|
+
2: 3 5
|
78
|
+
3: 4 5
|
79
|
+
4: 5 5
|
80
|
+
------------------
|
81
|
+
95: 96 5
|
82
|
+
96: 97 5
|
83
|
+
97: 98 5
|
84
|
+
98: 99 5
|
85
|
+
99: 100 5
|
86
|
+
col1 col2
|
87
|
+
EOS
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'with matrixy columns' do
|
92
|
+
let(:table){ ObjectTable.new(col1: 1..100, col2: NArray.to_na([[1, 2]] * 100) ) }
|
93
|
+
|
94
|
+
it 'should handle the matrixy columns' do
|
95
|
+
table = subject.inspect.lines.to_a[1..-1].join + "\n"
|
96
|
+
expect(table).to eql <<EOS
|
97
|
+
col1 col2
|
98
|
+
0: 1 [ 1, 2 ]
|
99
|
+
1: 2 [ 1, 2 ]
|
100
|
+
2: 3 [ 1, 2 ]
|
101
|
+
3: 4 [ 1, 2 ]
|
102
|
+
4: 5 [ 1, 2 ]
|
103
|
+
----------------------
|
104
|
+
95: 96 [ 1, 2 ]
|
105
|
+
96: 97 [ 1, 2 ]
|
106
|
+
97: 98 [ 1, 2 ]
|
107
|
+
98: 99 [ 1, 2 ]
|
108
|
+
99: 100 [ 1, 2 ]
|
109
|
+
col1 col2
|
110
|
+
EOS
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'with long rows in the matrix' do
|
114
|
+
let(:table){ ObjectTable.new(col1: 1..100, col2: NArray.to_na([(0...100).to_a] * 100) ) }
|
115
|
+
|
116
|
+
it 'should let NArray truncate them' do
|
117
|
+
table = subject.inspect.lines.to_a[1..-1].join + "\n"
|
118
|
+
expect(table).to eql <<EOS
|
119
|
+
col1 col2
|
120
|
+
0: 1 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ... ]
|
121
|
+
1: 2 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ... ]
|
122
|
+
2: 3 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ... ]
|
123
|
+
3: 4 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ... ]
|
124
|
+
4: 5 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ... ]
|
125
|
+
-------------------------------------------------------------------------------------------
|
126
|
+
95: 96 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ... ]
|
127
|
+
96: 97 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ... ]
|
128
|
+
97: 98 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ... ]
|
129
|
+
98: 99 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ... ]
|
130
|
+
99: 100 [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ... ]
|
131
|
+
col1 col2
|
132
|
+
EOS
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'when raising a no method error' do
|
138
|
+
it 'should propagate it as some other exception' do
|
139
|
+
expect(subject).to receive(:columns){ raise NoMethodError.new('asd') }
|
140
|
+
expect{subject.inspect}.to raise_error do |error|
|
141
|
+
expect(error).to_not be_a NoMethodError
|
142
|
+
expect(error.message).to eql 'asd'
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe '#nrows' do
|
149
|
+
let(:table){ ObjectTable.new(col1: [1, 2, 3], col2: [5, 5, 5]) }
|
150
|
+
|
151
|
+
it 'should return the number of rows' do
|
152
|
+
expect(table.nrows).to eql 3
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'on an empty table' do
|
156
|
+
let(:table){ ObjectTable.new }
|
157
|
+
|
158
|
+
it 'should return 0' do
|
159
|
+
expect(table.nrows).to eql 0
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe 'column methods' do
|
165
|
+
let(:table){ ObjectTable.new(col1: [1, 2, 3], col2: [5, 5, 5]) }
|
166
|
+
|
167
|
+
it 'should respond to the column names as methods' do
|
168
|
+
subject.columns.keys.each do |key|
|
169
|
+
expect(subject).to respond_to key
|
170
|
+
expect(subject.send(key)).to eql subject.columns[key]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe '#[]' do
|
175
|
+
it 'should allow access to columns through []' do
|
176
|
+
subject.columns.keys.each do |key|
|
177
|
+
expect(subject[key]).to eql subject.columns[key]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe '==' do
|
184
|
+
let(:table){ ObjectTable.new(col1: [1, 2, 3], col2: [5, 5, 5]) }
|
185
|
+
|
186
|
+
it 'should fail for non-tables' do
|
187
|
+
expect(subject == 'not a table').to be_falsey
|
188
|
+
end
|
189
|
+
|
190
|
+
context 'against a ObjectTable' do
|
191
|
+
context 'with different contents' do
|
192
|
+
let(:other){ ObjectTable.new(col1: [1, 2, 3], col2: 10000) }
|
193
|
+
|
194
|
+
it 'should fail' do
|
195
|
+
expect(subject == other).to be_falsey
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
context 'with the same contents' do
|
200
|
+
let(:other){ ObjectTable.new(col1: [1, 2, 3], col2: [5, 5, 5]) }
|
201
|
+
|
202
|
+
it 'should succeed' do
|
203
|
+
expect(subject == other).to be_truthy
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context 'against a ObjectTable::View' do
|
209
|
+
let(:view_parent){ ObjectTable.new(col2: [5, 5, 5, 1000], col1: [1, 2, 3, 4]) }
|
210
|
+
|
211
|
+
context 'with different contents' do
|
212
|
+
let(:other){ view_parent.where{ col1 > 1} }
|
213
|
+
|
214
|
+
it 'should fail' do
|
215
|
+
expect(subject == other).to be_falsey
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
context 'with the same contents' do
|
220
|
+
let(:other){ view_parent.where{ col1 < 4} }
|
221
|
+
|
222
|
+
it 'should succeed' do
|
223
|
+
expect(subject == other).to be_truthy
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
describe '#apply' do
|
231
|
+
let(:table){ ObjectTable.new(col1: [1, 2, 3], col2: 5) }
|
232
|
+
|
233
|
+
it 'should evaluate in the context of the table' do
|
234
|
+
expect(subject.apply{ col1 }).to eql subject.col1
|
235
|
+
expect(subject.apply{ col2.sum }).to eql subject.col2.sum
|
236
|
+
end
|
237
|
+
|
238
|
+
context 'with a block returning a grid' do
|
239
|
+
subject{ table.apply{ ObjectTable::BasicGrid[col1: [4, 5, 6]] } }
|
240
|
+
|
241
|
+
it 'should coerce to a table' do
|
242
|
+
expect(subject).to be_a ObjectTable
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'should have access to a BasicGrid shortcut' do
|
247
|
+
result = table.apply{ @R[value: col1 + 5] }
|
248
|
+
expect(result).to be_a ObjectTable
|
249
|
+
expect(result.value).to eql (table.col1 + 5)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
describe '#where' do
|
254
|
+
let(:table){ ObjectTable.new(col1: [1, 2, 3], col2: 5) }
|
255
|
+
let(:block){ Proc.new{col1 > 1} }
|
256
|
+
let(:filtered){ subject.where &block }
|
257
|
+
|
258
|
+
it 'should return a temp view' do
|
259
|
+
expect(filtered).to be_a ObjectTable::TempView
|
260
|
+
expect(filtered.instance_eval('@filter')).to eql block
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
describe '#group' do
|
265
|
+
let(:table){ ObjectTable.new(col1: [1, 2, 3], col2: 5) }
|
266
|
+
let(:block){ Proc.new{col1 > 1} }
|
267
|
+
let(:grouped){ subject.group &block }
|
268
|
+
|
269
|
+
it 'should return groups' do
|
270
|
+
expect(grouped).to be_a ObjectTable::TempGrouped
|
271
|
+
expect(grouped.instance_eval('@grouper')).to eql block
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe '.clone' do
|
276
|
+
let(:table){ ObjectTable.new(col1: [1, 2, 3], col2: 5) }
|
277
|
+
let(:clone){ subject.clone }
|
278
|
+
|
279
|
+
it 'should return a new table' do
|
280
|
+
expect(clone).to be_a ObjectTable
|
281
|
+
expect(clone).to_not be subject
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'should be equivalent to the original table' do
|
285
|
+
expect(clone).to eql subject
|
286
|
+
end
|
287
|
+
|
288
|
+
it 'should have cloned columns' do
|
289
|
+
subject.columns.each do |k, v|
|
290
|
+
expect(clone.columns[k].to_a).to eql v.to_a
|
291
|
+
expect(clone.columns[k]).to_not be v
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
describe '#sort_by' do
|
297
|
+
let(:table){ ObjectTable.new(col1: [2, 2, 1, 1], col2: [0, 1, 0, 1], col3: [5, 6, 7, 8]) }
|
298
|
+
let(:sorted){ subject.sort_by(subject.col1, subject.col2) }
|
299
|
+
|
300
|
+
it 'should return a new table' do
|
301
|
+
expect(sorted).to be_a ObjectTable
|
302
|
+
expect(sorted).to_not be subject
|
303
|
+
end
|
304
|
+
|
305
|
+
it 'should sort by the given columns' do
|
306
|
+
expect(sorted).to eql ObjectTable.new(
|
307
|
+
col1: [1, 1, 2, 2],
|
308
|
+
col2: [0, 1, 0, 1],
|
309
|
+
col3: [7, 8, 5, 6],
|
310
|
+
)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: object_table
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cheney Lin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: narray
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.1'
|
69
|
+
description: Simple data table table implementation in ruby
|
70
|
+
email:
|
71
|
+
- lincheney@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- Gemfile
|
78
|
+
- LICENSE
|
79
|
+
- README.md
|
80
|
+
- Rakefile
|
81
|
+
- lib/object_table.rb
|
82
|
+
- lib/object_table/basic_grid.rb
|
83
|
+
- lib/object_table/column.rb
|
84
|
+
- lib/object_table/grouped.rb
|
85
|
+
- lib/object_table/masked_column.rb
|
86
|
+
- lib/object_table/table_methods.rb
|
87
|
+
- lib/object_table/temp_grouped.rb
|
88
|
+
- lib/object_table/temp_view.rb
|
89
|
+
- lib/object_table/version.rb
|
90
|
+
- lib/object_table/view.rb
|
91
|
+
- lib/object_table/view_methods.rb
|
92
|
+
- object_table.gemspec
|
93
|
+
- spec/object_table/basic_grid_spec.rb
|
94
|
+
- spec/object_table/column_spec.rb
|
95
|
+
- spec/object_table/grouped_spec.rb
|
96
|
+
- spec/object_table/masked_column_spec.rb
|
97
|
+
- spec/object_table/temp_grouped_spec.rb
|
98
|
+
- spec/object_table/temp_view_spec.rb
|
99
|
+
- spec/object_table/view_spec.rb
|
100
|
+
- spec/object_table_spec.rb
|
101
|
+
- spec/support/object_table_example.rb
|
102
|
+
homepage: https://github.com/lincheney/ruby-object-table
|
103
|
+
licenses:
|
104
|
+
- MIT
|
105
|
+
metadata: {}
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubyforge_project:
|
122
|
+
rubygems_version: 2.2.2
|
123
|
+
signing_key:
|
124
|
+
specification_version: 4
|
125
|
+
summary: Simple data table table implementation in ruby
|
126
|
+
test_files:
|
127
|
+
- spec/object_table/basic_grid_spec.rb
|
128
|
+
- spec/object_table/column_spec.rb
|
129
|
+
- spec/object_table/grouped_spec.rb
|
130
|
+
- spec/object_table/masked_column_spec.rb
|
131
|
+
- spec/object_table/temp_grouped_spec.rb
|
132
|
+
- spec/object_table/temp_view_spec.rb
|
133
|
+
- spec/object_table/view_spec.rb
|
134
|
+
- spec/object_table_spec.rb
|
135
|
+
- spec/support/object_table_example.rb
|