object_table 0.3.0 → 0.3.2

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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZTUwZmM3Nzk5N2I3NmE4ZGYwZmE0M2IzMjBkZDEyZTk0NTcxNzliNQ==
5
- data.tar.gz: !binary |-
6
- ODg5Zjc3Nzk5ZGIyMjk1OWNjYjFlYzhjMzhlMGNlNzdjMGI3ZWE0OQ==
2
+ SHA1:
3
+ metadata.gz: 8b283bc238922ed7b80fc82225cbb758c6a0bf44
4
+ data.tar.gz: 144b36aec60ae08d7ef391351dc6ec5e14d4c33c
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- OWFlMzcwN2U2MTQ4Y2ZkNWQyY2I2Y2I1YWFkM2ZjMDIzNTgzYTAxOTNhZDVl
10
- NmIxMDRkY2I0NjQ3NTAwZGYxYzU3MjRiZGFkMjU5ODg2ODdjNzBmMjEwNGNh
11
- ZTRmODBiOWRiM2Y2Zjc5ZjY3OWYwZTk4YzgxY2UzZDdkY2YyMDI=
12
- data.tar.gz: !binary |-
13
- NjkwZWRiM2FlYmVhNjgyNzRhYmZmN2I1YzVhYzJjYTVlYzVlMDFmZTFiNGM0
14
- NjcyMzdlYTIwMDM2MjljN2VkNmM2OTM1MzBjOWZiOWJiMTlhYmE5MWQxMTI2
15
- YmQxMmYxNzQ2MjhjMTc4ZTk3ODhhYTcyZTM2OGE4ZjMwOTNkNDY=
6
+ metadata.gz: 4ae62ff61696c06ab3c4edd2974dc68cd4508de97388a0194d347865c2f617a3cd1694f87f6afdaa6cafd4fadca011e131cebf2f09925e6ea46de959b5eab2ea
7
+ data.tar.gz: 38110c1fc518f9d8bc5d0ab4b964eab0a266fb94641ee71c636510bcd1ab710901f9af64c61a677800e4617ac993e74610e69e3eff704079e503d38e499e72ad
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/README.md CHANGED
@@ -1,6 +1,21 @@
1
1
  ruby-object-table
2
2
  =================
3
3
 
4
+ [![Gem Version][GV img]][Gem Version]
5
+ [![Build Status][BS img]][Build Status]
6
+ [![Code Climate][CC img]][Code Climate]
7
+ [![Coverage Status][CS img]][Coverage Status]
8
+
9
+ [Gem Version]: https://rubygems.org/gems/object_table
10
+ [Build Status]: https://travis-ci.org/lincheney/ruby-object-table
11
+ [Code Climate]: https://codeclimate.com/github/lincheney/ruby-object-table
12
+ [Coverage Status]: https://coveralls.io/r/lincheney/ruby-object-table
13
+
14
+ [GV img]: https://badge.fury.io/rb/object_table.png
15
+ [BS img]: https://travis-ci.org/lincheney/ruby-object-table.png
16
+ [CC img]: https://codeclimate.com/github/lincheney/ruby-object-table.png
17
+ [CS img]: https://coveralls.io/repos/lincheney/ruby-object-table/badge.png?branch=master
18
+
4
19
  Simple data table/frame implementation in ruby
5
20
  Probably slow and extremely inefficient, but it works and that's all that matters.
6
21
  Uses NArrays (https://github.com/masa16/narray) for storing data.
@@ -8,14 +8,7 @@ class ObjectTable::BasicGrid < Hash
8
8
 
9
9
  def _get_number_rows!
10
10
  each{|k, v| self[k] = v.to_a if v.is_a?(Range)}
11
- rows = map do |k, v|
12
- case v
13
- when Array
14
- v.length
15
- when NArray
16
- v.shape.last or 0
17
- end
18
- end.compact.uniq
11
+ rows = map{|k, v| ObjectTable::Column.length_of(v) rescue nil}.compact.uniq
19
12
  end
20
13
 
21
14
  def _ensure_uniform_columns!(rows = nil)
@@ -29,7 +22,7 @@ class ObjectTable::BasicGrid < Hash
29
22
  self[k] = [v] * rows unless (v.is_a?(Array) || v.is_a?(NArray))
30
23
  end
31
24
 
32
- self
25
+ rows
33
26
  end
34
27
 
35
28
  end
@@ -2,7 +2,19 @@ require 'narray'
2
2
 
3
3
  module ObjectTable::Column
4
4
 
5
+ def self.length_of(array)
6
+ case array
7
+ when Array
8
+ array.length
9
+ when NArray
10
+ array.shape.last or 0
11
+ else
12
+ raise "Expected Array or NArray, got #{array}"
13
+ end
14
+ end
15
+
5
16
  def self.stack(*columns)
17
+ columns = columns.reject(&:empty?)
6
18
  return NArray[] if columns.empty?
7
19
  return columns[0].clone if columns.length == 1
8
20
 
@@ -10,12 +22,10 @@ module ObjectTable::Column
10
22
  first_col = columns.first
11
23
  new_col = NArray.new(first_col.typecode, *first_col.shape[0...-1], new_rows)
12
24
 
13
- padding = [nil] * (first_col.rank - 1)
14
-
15
- row = 0
16
- columns.each do |col|
17
- new_col[*padding, row ... (row + col.shape[-1])] = col
18
- row += col.shape[-1]
25
+ columns.reduce(0) do |row, col|
26
+ end_row = row + col.shape[-1]
27
+ new_col[false, row ... end_row] = col
28
+ end_row
19
29
  end
20
30
 
21
31
  new_col
@@ -37,15 +37,7 @@ class ObjectTable::Grouped
37
37
 
38
38
  def each(&block)
39
39
  names, groups = _groups()
40
-
41
- enumerator = Enumerator.new do |y|
42
- groups.each do |k, v|
43
- keys = names.zip(k)
44
- y.yield __group_cls__.new(@parent, Hash[keys], v)
45
- end
46
- @parent
47
- end
48
-
40
+ enumerator = _make_groups(names, groups)
49
41
  return enumerator unless block
50
42
  enumerator.each{|grp| grp._apply_block(&block)}
51
43
  end
@@ -53,37 +45,41 @@ class ObjectTable::Grouped
53
45
  def apply(&block)
54
46
  names, groups = _groups()
55
47
  value_key = self.class._generate_name(DEFAULT_VALUE_PREFIX, names).to_sym
48
+ nrows = []
56
49
 
57
- data = groups.map do |k, v|
58
- keys = names.zip(k)
59
- value = __group_cls__.new(@parent, Hash[keys], v)._apply_block &block
50
+ data = _make_groups(names, groups).map do |group|
51
+ value = group._apply_block(&block)
60
52
 
61
53
  case value
62
54
  when ObjectTable::TableMethods
63
- nrows = value.nrows
55
+ nrows.push(value.nrows)
64
56
  value = value.columns
65
57
  when ObjectTable::BasicGrid
66
- value._ensure_uniform_columns!
67
- nrows = NArray.to_na(value.values.first).shape[-1]
68
- when Array
69
- nrows = value.length
70
- when NArray
71
- nrows = value.shape.last
58
+ nrows.push(value._ensure_uniform_columns!)
72
59
  else
73
- nrows = 1
60
+ nrows.push( (ObjectTable::Column.length_of(value) rescue 1) )
74
61
  end
75
62
 
76
- keys = names.zip(k.map{|x| [x] * nrows})
63
+ value = ObjectTable::BasicGrid[value_key, value] unless value.is_a?(ObjectTable::BasicGrid)
64
+ value
65
+ end
77
66
 
78
- grid = case value
79
- when ObjectTable::BasicGrid
80
- ObjectTable::BasicGrid[keys].merge!(value)
81
- else
82
- ObjectTable::BasicGrid[keys + [[value_key, value]]]
67
+ keys = groups.keys.transpose.map{|col| col.zip(nrows).flat_map{|key, rows| [key] * rows}}
68
+ keys = ObjectTable::BasicGrid[names.zip(keys)]
69
+
70
+ result = __table_cls__.stack(*data)
71
+ __table_cls__.new(keys.merge!(result.columns))
72
+ end
73
+
74
+
75
+ def _make_groups(names, groups)
76
+ key_struct = Struct.new(*names.map(&:to_sym))
77
+ enumerator = Enumerator.new do |y|
78
+ groups.each do |k, v|
79
+ y.yield __group_cls__.new(@parent, key_struct.new(*k), v)
83
80
  end
81
+ @parent
84
82
  end
85
-
86
- __table_cls__.stack(*data)
87
83
  end
88
84
 
89
85
  def self._generate_name(prefix, existing_names)
@@ -1,41 +1,31 @@
1
1
  require_relative 'column'
2
2
 
3
3
  class ObjectTable::MaskedColumn < NArray
4
- attr_accessor :indices, :parent, :padded_dims
4
+ attr_accessor :indices, :parent
5
5
 
6
6
  EMPTY = NArray[]
7
7
 
8
8
  def self.mask(parent, indices)
9
- if parent.rank > 1
10
- padded_dims = [nil] * (parent.rank - 1)
9
+ if parent.empty?
10
+ masked = parent.slice(indices)
11
11
  else
12
- padded_dims = []
12
+ masked = parent.slice(false, indices)
13
13
  end
14
- masked = parent.slice(*padded_dims, indices)
15
14
 
16
15
  if masked.rank <= 0
17
16
  column = self.new(masked.typecode, 0)
18
17
  else
19
- column = self.new(masked.typecode, *masked.shape)
20
- column.super_slice_assign(masked)
18
+ column = self.cast(masked)
21
19
  end
22
20
 
23
21
  column.parent = parent
24
22
  column.indices = indices
25
- column.padded_dims = padded_dims
26
23
  column
27
24
  end
28
25
 
29
- # let ObjectTable::Column do this, since we've overriden []=
30
- def self.make(*args)
31
- ObjectTable::Column.make(*args)
32
- end
33
-
34
- alias_method :super_slice_assign, :[]=
35
-
36
26
  def []=(*keys, value)
37
27
  unless parent.nil? or ((value.is_a?(Array) or value.is_a?(NArray)) and value.empty?)
38
- parent[*padded_dims, indices[*keys]] = value
28
+ parent[false, indices[*keys]] = value
39
29
  end
40
30
  super
41
31
  end
@@ -44,7 +34,7 @@ class ObjectTable::MaskedColumn < NArray
44
34
  %w{ fill! indgen! indgen random! map! collect! conj! imag= mod! add! div! sbt! mul! }.each do |op|
45
35
  define_method(op) do |*args, &block|
46
36
  result = super(*args, &block)
47
- parent[*padded_dims, indices] = result if parent
37
+ parent[false, indices] = result if parent
48
38
  result
49
39
  end
50
40
  end
@@ -1,23 +1,38 @@
1
1
  module ObjectTable::Printable
2
2
 
3
- def self.get_printable_column(name, column)
4
- padding = [nil] * (column.rank - 1)
5
- rows = column.shape[-1].times.map do |i|
6
- row = column[*padding, i]
3
+ def self.get_printable_column(column)
4
+ column.shape[-1].times.map do |i|
5
+ row = column[false, i]
7
6
  str = row.is_a?(NArray) ? row.inspect.partition("\n")[-1].strip : row.inspect
8
7
  str.split("\n")
9
8
  end
9
+ end
10
10
 
11
- name = name.to_s
12
- [[name]] + rows + [[name]]
11
+ def self.calc_column_widths(columns)
12
+ columns.map{|col| col.flatten.map(&:length).max}
13
13
  end
14
14
 
15
- def self.get_printable_line_numbers(numbers)
16
- rows = numbers.map do |i|
17
- ["#{i}: "]
15
+ def _format_section(row_slice)
16
+ numbers = row_slice.map{|i| ["#{i}: "]}
17
+ section = columns.map do |name, c|
18
+ c = c.slice(false, row_slice)
19
+ ObjectTable::Printable.get_printable_column(c)
18
20
  end
19
21
 
20
- [['']] + rows + [['']]
22
+ [numbers] + section
23
+ end
24
+
25
+ def _format_rows(rows, widths)
26
+ rows.flat_map do |row|
27
+ height = row.map(&:length).max
28
+
29
+ row = row.zip(widths).map do |cell, width|
30
+ cell += [" "] * (height - cell.length)
31
+ cell.map{|i| i.rjust(width)}
32
+ end
33
+
34
+ row.transpose.map(&:join)
35
+ end
21
36
  end
22
37
 
23
38
  def inspect(max_section = 5, col_padding = 2)
@@ -26,47 +41,32 @@ module ObjectTable::Printable
26
41
  return (header + "(empty table)") if ncols == 0
27
42
  return (header + "(empty table with columns: #{colnames.join(", ")})") if nrows == 0
28
43
 
29
- printed_columns = []
44
+ column_headers = [''] + colnames.map(&:to_s)
30
45
 
31
46
  if nrows > max_section * 2
32
- head = (0...max_section)
33
- tail = ((nrows - max_section)...nrows)
47
+ head = _format_section(0 ... max_section)
48
+ tail = _format_section((nrows - max_section) ... nrows)
34
49
 
35
- printed_columns.push ObjectTable::Printable.get_printable_line_numbers(head.to_a + tail.to_a)
50
+ columns = [column_headers, head, tail].transpose
51
+ widths = NArray.to_na(ObjectTable::Printable.calc_column_widths(columns)) + col_padding
52
+ total_width = widths.sum
53
+
54
+ rows = _format_rows(head.transpose, widths)
55
+ rows.push('-' * total_width)
56
+ rows += _format_rows(tail.transpose, widths)
36
57
 
37
- printed_columns += columns.map do |name, c|
38
- padding = [nil] * (c.rank - 1)
39
- c = c.slice(*padding, [head, tail])
40
- ObjectTable::Printable.get_printable_column(name, c)
41
- end
42
58
  else
43
- max_section = -1
44
- printed_columns.push ObjectTable::Printable.get_printable_line_numbers(0...nrows)
45
- printed_columns += columns.map do |name, c|
46
- ObjectTable::Printable.get_printable_column(name, c)
47
- end
59
+ section = _format_section(0...nrows)
60
+ columns = [column_headers, section].transpose
61
+ widths = NArray.to_na(ObjectTable::Printable.calc_column_widths(columns)) + col_padding
62
+ rows = _format_rows(section.transpose, widths)
48
63
  end
49
64
 
50
- widths = printed_columns.map{|row| row.flat_map{|c| c.map(&:length)}.max + col_padding}
51
-
52
- header + printed_columns.transpose.each_with_index.map do |row, index|
53
- height = row.map(&:length).max
54
-
55
- row = row.zip(widths).map do |cell, width|
56
- cell += [" "] * (height - cell.length)
57
- cell.map{|i| i.rjust(width)}
58
- end
59
-
60
- row = row.transpose.map{|i| i.join('')}.join("\n")
61
-
62
- if index == max_section
63
- row += "\n" + '-'*widths.reduce(:+)
64
- end
65
- row
66
- end.join("\n")
65
+ column_headers = _format_rows([[column_headers].transpose], widths).join
66
+ header + ([column_headers] + rows + [column_headers]).join("\n")
67
67
 
68
68
  rescue NoMethodError => e
69
69
  raise Exception.new(e)
70
70
  end
71
71
 
72
- end
72
+ end
@@ -0,0 +1,63 @@
1
+ module ObjectTable::Stacker
2
+
3
+ def stack!(*others)
4
+ @columns.replace( self.class.stack(self, *others).columns )
5
+ self
6
+ end
7
+
8
+ module ClassMethods
9
+ def stack(*grids)
10
+ keys = nil
11
+
12
+ grids = grids.map do |grid|
13
+ grid = _process_stackable_grid(grid, keys)
14
+ keys ||= grid.keys if grid
15
+ grid
16
+ end.compact
17
+ return self.new if grids.empty?
18
+
19
+ result = keys.map do |k|
20
+ segments = grids.map{|grid| grid[k]}
21
+ [k, _stack_segments(segments)]
22
+ end
23
+
24
+ self.new(ObjectTable::BasicGrid[result])
25
+ end
26
+
27
+ def _stack_segments(segments)
28
+ if segments.all?{|seg| seg.is_a? Array}
29
+ column = NArray.to_na(segments.flatten(1))
30
+
31
+ elsif segments.all?{|seg| seg.is_a? NArray} and segments.map{|seg| seg.shape}.uniq.length == 1
32
+ column = NArray.to_na(segments)
33
+ column = column.reshape(*column.shape[0...-2], column.shape[-2] * column.shape[-1])
34
+
35
+ else
36
+ segments.map!{|seg| NArray.to_na seg}
37
+ column = ObjectTable::Column.stack(*segments)
38
+
39
+ end
40
+ end
41
+
42
+ def _process_stackable_grid(grid, keys)
43
+ case grid
44
+ when ObjectTable::TableMethods
45
+ grid = grid.columns
46
+ when ObjectTable::BasicGrid
47
+ grid._ensure_uniform_columns!
48
+ end
49
+
50
+ raise "Don't know how to join a #{grid.class}" unless grid.is_a?(ObjectTable::BasicGrid)
51
+ return if grid.empty?
52
+ raise 'Mismatch in column names' unless !keys or ( (keys - grid.keys).empty? and (grid.keys - keys).empty? )
53
+ return grid
54
+ end
55
+
56
+ end
57
+
58
+
59
+ def self.included(base)
60
+ base.extend(ClassMethods)
61
+ end
62
+
63
+ end
@@ -35,29 +35,30 @@ module ObjectTable::TableMethods
35
35
 
36
36
  def set_column(name, value, *args)
37
37
  column = get_column(name)
38
+ new_column = column.nil?
39
+
38
40
  value = value.to_a if value.is_a?(Range)
41
+ is_vector = (value.is_a?(Array) or value.is_a?(NArray))
39
42
 
40
- if column
41
- return value if column.empty? and value.empty?
42
- return (column[] = value)
43
- end
43
+ if new_column
44
+ if is_vector and args.empty?
45
+ value = NArray.to_na(value)
46
+ unless (value.shape[-1] or 0) == nrows
47
+ raise ArgumentError.new("Expected size of last dimension to be #{nrows}, was #{value.shape[-1].inspect}")
48
+ end
44
49
 
45
- if (value.is_a?(Array) or value.is_a?(NArray)) and args.empty?
46
- value = NArray.to_na(value)
47
- unless (value.shape[-1] or 0) == nrows
48
- raise ArgumentError.new("Expected size of last dimension to be #{nrows}, was #{value.shape[-1].inspect}")
50
+ args = [value.typecode] + value.shape[0...-1]
49
51
  end
50
52
 
51
- args = [value.typecode] + value.shape[0...-1]
53
+ column = add_column(name, *args)
52
54
  end
53
55
 
54
- column = add_column(name, *args)
55
- return column if value.is_a?(NArray) and value.empty?
56
+ return column if column.empty? and (!is_vector or value.empty?)
56
57
 
57
58
  begin
58
59
  column[] = value
59
60
  rescue Exception => e
60
- pop_column(name)
61
+ pop_column(name) if new_column
61
62
  raise e
62
63
  end
63
64
  end
@@ -100,7 +101,7 @@ module ObjectTable::TableMethods
100
101
  get_column(meth) or super
101
102
  end
102
103
 
103
- def respond_to?(meth)
104
+ def respond_to?(meth, include_all = false)
104
105
  super or has_column?(meth)
105
106
  end
106
107
 
@@ -1,3 +1,3 @@
1
1
  class ObjectTable
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -14,14 +14,13 @@ class ObjectTable::View
14
14
  @filter = block
15
15
  end
16
16
 
17
- def_delegators :@parent, :has_column?
18
-
19
17
  def make_view
20
18
  __static_view_cls__.new @parent, indices
21
19
  end
22
20
 
23
21
  def clone
24
- __table_cls__.new(columns)
22
+ cols = ObjectTable::BasicGrid[@parent.columns.map{|k, v| [k, v[false, indices]]}]
23
+ __table_cls__.new(cols)
25
24
  end
26
25
 
27
26
  def inspect(*args)
@@ -7,6 +7,8 @@ module ObjectTable::ViewMethods
7
7
  include ObjectTable::TableMethods
8
8
  include ObjectTable::TableChild
9
9
 
10
+ def_delegators :@parent, :has_column?
11
+
10
12
  def nrows
11
13
  indices.length
12
14
  end
data/lib/object_table.rb CHANGED
@@ -5,9 +5,11 @@ require_relative "object_table/view"
5
5
  require_relative "object_table/static_view"
6
6
  require_relative "object_table/column"
7
7
  require_relative "object_table/grouped"
8
+ require_relative "object_table/stacker"
8
9
 
9
10
  class ObjectTable
10
11
  include TableMethods
12
+ include Stacker
11
13
 
12
14
  attr_reader :columns
13
15
 
@@ -30,51 +32,6 @@ class ObjectTable
30
32
  columns[name] = col
31
33
  end
32
34
 
33
- def stack!(*others)
34
- new_values = Hash[colnames.zip(ncols.times.map{[]})]
35
-
36
- others.each do |x|
37
- case x
38
- when ObjectTable::TableMethods
39
- x = x.columns
40
- when ObjectTable::BasicGrid
41
- x._ensure_uniform_columns!
42
- end
43
-
44
- raise "Don't know how to append a #{x.class}" unless x.is_a?(ObjectTable::BasicGrid)
45
- next if x.empty?
46
- raise 'Mismatch in column names' unless (colnames - x.keys).empty?
47
-
48
- x.each do |k, v|
49
- unless new_values.include?(k) and v.empty?
50
- new_values[k].push(NArray.to_na(v))
51
- end
52
- end
53
- end
54
-
55
- return self if new_values.values.first.empty?
56
-
57
- new_values.each do |k, v|
58
- @columns[k] = ObjectTable::Column.stack(@columns[k], *v)
59
- end
60
- self
61
- end
62
-
63
- def self.stack(*values)
64
- return self.new if values.empty?
65
- base = values.shift
66
-
67
- case base
68
- when ObjectTable::BasicGrid
69
- base = self.new(base.clone)
70
- when ObjectTable, ObjectTable::View
71
- base = base.clone
72
- else
73
- raise "Don't know how to join a #{base.class}"
74
- end
75
- base.stack!(*values)
76
- end
77
-
78
35
  def sort_by!(*keys)
79
36
  sort_index = _get_sort_index(keys)
80
37
 
@@ -84,73 +41,6 @@ class ObjectTable
84
41
  self
85
42
  end
86
43
 
87
- def join(other, key, options={})
88
- type = (options[:type] || 'inner')
89
- key = [key] unless key.is_a?(Array)
90
-
91
- right_cols = other.colnames - key
92
- left_cols = colnames
93
-
94
- lkeys = key.map{|k| get_column(k).to_a}.transpose
95
- rkeys = key.map{|k| other[k].to_a}.transpose
96
-
97
- rgroups = rkeys.length.times.group_by{|i| rkeys[i]}
98
- rindex = rgroups.values_at(*lkeys)
99
-
100
- if type == 'left' or type == 'outer'
101
- common, lmissing = rindex.each_with_index.partition(&:first)
102
- lmissing = lmissing.transpose[-1]
103
- lindex = common.flat_map{|r, i| [i] * r.length}
104
- rindex.flatten!.compact!
105
-
106
- lindex += lmissing
107
- rindex += [-1] * lmissing.length
108
- else
109
- lindex = rindex.each_with_index.flat_map{|r, i| [i] * r.length if r}.compact
110
- rindex.flatten!.compact!
111
- end
112
-
113
-
114
- if type == 'right' or type == 'outer'
115
- left_cols -= key
116
- rmissing = (0...other.nrows).to_a - rindex
117
- lindex += [-1] * rmissing.length
118
- rindex += rmissing
119
- end
120
-
121
- lindex = NArray.to_na(lindex)
122
- rindex = NArray.to_na(rindex)
123
- lblank = lindex.eq(-1)
124
- rblank = rindex.eq(-1)
125
-
126
- data = [
127
- [left_cols, lindex, lblank, self],
128
- [right_cols, rindex, rblank, other],
129
- ].flat_map do |cols, index, blanks, table|
130
- cols.map do |k|
131
- col = table.get_column(k)
132
- padding = [nil] * (col.rank - 1)
133
- col = col[*padding, index]
134
- col[*padding, blanks] = [nil]
135
- [k, col]
136
- end
137
- end
138
-
139
- keys = []
140
- if type == 'right' or type == 'outer'
141
- keys = key.map do |k|
142
- col = get_column(k)
143
- padding = [nil] * (col.rank - 1)
144
- col = col[*padding, lindex]
145
- col[*padding, lblank] = other[k][*padding, rmissing]
146
- [k, col]
147
- end
148
- end
149
-
150
- self.class.new(keys + data)
151
- end
152
-
153
-
154
44
  def __static_view_cls__
155
45
  self.class::StaticView
156
46
  end
data/object_table.gemspec CHANGED
@@ -23,5 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "bundler", "~> 1.3"
24
24
  spec.add_development_dependency "rake"
25
25
  spec.add_development_dependency 'rspec', "~> 3.1"
26
+ spec.add_development_dependency 'coveralls', ">= 0.7"
26
27
  end
27
28