table_structure 0.3.22 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +33 -0
  4. data/Gemfile.lock +7 -7
  5. data/README.md +30 -31
  6. data/lib/table_structure.rb +6 -12
  7. data/lib/table_structure/csv/writer.rb +4 -41
  8. data/lib/table_structure/iterator.rb +48 -89
  9. data/lib/table_structure/schema.rb +63 -76
  10. data/lib/table_structure/schema/class_methods.rb +9 -28
  11. data/lib/table_structure/schema/column_builder_factory.rb +75 -0
  12. data/lib/table_structure/schema/columns/attributes.rb +14 -9
  13. data/lib/table_structure/schema/columns/schema.rb +14 -9
  14. data/lib/table_structure/schema/composite_class.rb +40 -0
  15. data/lib/table_structure/schema/definition/columns/compiler.rb +7 -3
  16. data/lib/table_structure/schema/definition/columns/validator.rb +2 -6
  17. data/lib/table_structure/schema/dsl/column_builder.rb +29 -0
  18. data/lib/table_structure/schema/dsl/column_definition.rb +12 -2
  19. data/lib/table_structure/schema/dsl/context_builder.rb +2 -11
  20. data/lib/table_structure/schema/dsl/row_builder.rb +2 -9
  21. data/lib/table_structure/schema/{key_converter.rb → keys_builder.rb} +2 -2
  22. data/lib/table_structure/schema/row_context_builder_factory.rb +26 -0
  23. data/lib/table_structure/table.rb +31 -56
  24. data/lib/table_structure/utils.rb +40 -0
  25. data/lib/table_structure/version.rb +1 -1
  26. data/lib/table_structure/writer.rb +7 -54
  27. metadata +8 -14
  28. data/lib/table_structure/schema/column_converter.rb +0 -46
  29. data/lib/table_structure/schema/definition/column_converter.rb +0 -31
  30. data/lib/table_structure/schema/definition/context_builder.rb +0 -17
  31. data/lib/table_structure/schema/definition/row_builder.rb +0 -25
  32. data/lib/table_structure/schema/dsl/column_converter.rb +0 -41
  33. data/lib/table_structure/schema/dsl/option.rb +0 -19
  34. data/lib/table_structure/schema/row_builder.rb +0 -21
  35. data/lib/table_structure/table/column_converter.rb +0 -46
  36. data/lib/table_structure/table/context_builder.rb +0 -49
  37. data/lib/table_structure/table/iterator.rb +0 -22
  38. data/lib/table_structure/table/row_builder.rb +0 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae9b604db5214e4001824da3583481ad03b93e22785b6c7819874cd546b65025
4
- data.tar.gz: 5883b75571629c06eb71f7b06ffb0923c1ce2660113f9804eaeaf0ecd8d94ce6
3
+ metadata.gz: bebf267d2cae044dd2f493b213950954c88b384d2b3e6dd15c09b7947b104eb7
4
+ data.tar.gz: cbe61559035246eb4dc80edf4e34b1b67a0e1f8db16749368e81d23e48bd2b81
5
5
  SHA512:
6
- metadata.gz: 2839f25ac4d152627f70dd733a01f49b92a8c07bfcdf43c0b67fcc2891a105f136570e272c93580c5f68c869b20808c92edc56bb4c5aa836f07288dea9eac75a
7
- data.tar.gz: 1e49f3a7400bb993eafd7c24fa2622ece9aa1edb480b921179c92d4579f65e5316579c9606f522d9cdfc7d8e9f38b4e71693fd9edc52788996b8ba9f24af2122
6
+ metadata.gz: cd6f1e4299eda55eb1959c38248911c9fc052dee5cb541cc3b1517cb00947f069e5896ca9d69e792fa2258f6bb636aaee251efedb11af96cd55241cf44ab3dd1
7
+ data.tar.gz: 0e52a02afa1dc1c669233edc2e900cdfae5e5085bd6138bd2055aa57f4fadfdf0c587228f5eb560b5ba857555d34bbdc4477c1128fd193f144625e8f099a2cf7
@@ -8,4 +8,4 @@ rvm:
8
8
  - 2.5
9
9
  - 2.4
10
10
  - 2.3
11
- before_install: gem install bundler:2.1.2
11
+ before_install: gem install bundler:2.1.4
@@ -1,3 +1,36 @@
1
+ # 0.4.3
2
+ Changes:
3
+ - `TableStructure::Schema`
4
+ - Change to be able to use a block with `columns` DSL.
5
+
6
+ # 0.4.2
7
+ Changes:
8
+ - `TableStructure::Schema`
9
+ - Improve performance.
10
+ - `TableStructure::Iterator`
11
+ - `TableStructure::Writer`
12
+ - `TableStructure::CSV::Writer`
13
+ - Add validation for `header: { step: n }` option.
14
+ - `n` is allowed positive number or `nil`(default).
15
+
16
+ # 0.4.1
17
+ Changes:
18
+ - `TableStructure::Iterator`
19
+ - `TableStructure::Writer`
20
+ - `TableStructure::CSV::Writer`
21
+ - Add `header: { step: n }` option. Header rows are output at intervals of step number.
22
+ - e.g. `TableStructure::Iterator.new(schema, header: { step: 10 })`
23
+
24
+ # 0.4.0
25
+ Changes:
26
+ - Remove deprecated methods, arguments and options.
27
+ - It is recommended that you update to `0.3.23` first. If you get warnings or errors, fix them and then update to `0.4.0`.
28
+
29
+ # 0.3.23
30
+ Changes:
31
+ - `TableStructure::CSV::Writer`
32
+ - Fix not to output wrong warning.
33
+
1
34
  # 0.3.22
2
35
  Changes:
3
36
  - `TableStructure::Schema`
@@ -1,26 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- table_structure (0.3.22)
4
+ table_structure (0.4.3)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- diff-lcs (1.3)
9
+ diff-lcs (1.4.4)
10
10
  rake (13.0.1)
11
11
  rspec (3.9.0)
12
12
  rspec-core (~> 3.9.0)
13
13
  rspec-expectations (~> 3.9.0)
14
14
  rspec-mocks (~> 3.9.0)
15
- rspec-core (3.9.1)
16
- rspec-support (~> 3.9.1)
17
- rspec-expectations (3.9.1)
15
+ rspec-core (3.9.2)
16
+ rspec-support (~> 3.9.3)
17
+ rspec-expectations (3.9.2)
18
18
  diff-lcs (>= 1.2.0, < 2.0)
19
19
  rspec-support (~> 3.9.0)
20
20
  rspec-mocks (3.9.1)
21
21
  diff-lcs (>= 1.2.0, < 2.0)
22
22
  rspec-support (~> 3.9.0)
23
- rspec-support (3.9.2)
23
+ rspec-support (3.9.3)
24
24
 
25
25
  PLATFORMS
26
26
  ruby
@@ -32,4 +32,4 @@ DEPENDENCIES
32
32
  table_structure!
33
33
 
34
34
  BUNDLED WITH
35
- 2.1.2
35
+ 2.1.4
data/README.md CHANGED
@@ -44,19 +44,19 @@ class SampleTableSchema
44
44
  column name: 'Name',
45
45
  value: ->(row, *) { row[:name] }
46
46
 
47
- columns name: ['Pet 1', 'Pet 2', 'Pet 3'],
47
+ column name: ['Pet 1', 'Pet 2', 'Pet 3'],
48
48
  value: ->(row, *) { row[:pets] }
49
49
 
50
- columns ->(table) {
50
+ columns do |table|
51
51
  table[:questions].map do |question|
52
52
  {
53
53
  name: question[:id],
54
54
  value: ->(row, *) { row[:answers][question[:id]] }
55
55
  }
56
56
  end
57
- }
57
+ end
58
58
 
59
- column_converter :to_s do |val, _row, _table|
59
+ column_builder :to_s do |val, _row, _table|
60
60
  val.to_s
61
61
  end
62
62
  end
@@ -106,10 +106,10 @@ items = [
106
106
  ## or
107
107
  # items = Enumerator.new { |y| Item.find_each { |item| y << item } }
108
108
 
109
- table = []
110
- writer.write(items, to: table)
109
+ array = []
110
+ writer.write(items, to: array)
111
111
 
112
- # table
112
+ # array
113
113
  # => [["ID", "Name", "Pet 1", "Pet 2", "Pet 3", "Q1", "Q2", "Q3"], ["1", "Taro", "🐱", "🐶", "", "⭕️", "❌", "⭕️"], ["2", "Hanako", "🐇", "🐢", "🐿", "⭕️", "⭕️", "❌"]]
114
114
  ```
115
115
 
@@ -159,7 +159,6 @@ Define a schema:
159
159
  class SampleTableSchema
160
160
  include TableStructure::Schema
161
161
 
162
- # If `:header` is set to `false`, `:name` is optional.
163
162
  column name: 'ID',
164
163
  key: :id,
165
164
  value: ->(row, *) { row[:id] }
@@ -168,11 +167,11 @@ class SampleTableSchema
168
167
  key: :name,
169
168
  value: ->(row, *) { row[:name] }
170
169
 
171
- columns name: ['Pet 1', 'Pet 2', 'Pet 3'],
170
+ column name: ['Pet 1', 'Pet 2', 'Pet 3'],
172
171
  key: %i[pet1 pet2 pet3],
173
172
  value: ->(row, *) { row[:pets] }
174
173
 
175
- columns ->(table) {
174
+ columns do |table|
176
175
  table[:questions].map do |question|
177
176
  {
178
177
  name: question[:id],
@@ -180,7 +179,7 @@ class SampleTableSchema
180
179
  value: ->(row, *) { row[:answers][question[:id]] }
181
180
  }
182
181
  end
183
- }
182
+ end
184
183
  end
185
184
  ```
186
185
 
@@ -256,6 +255,10 @@ Initialize a table with the schema and render the table:
256
255
  <% end %>
257
256
  ```
258
257
 
258
+ ### Sample with docker
259
+
260
+ https://github.com/jsmmr/ruby_table_structure_sample
261
+
259
262
  ### Advanced
260
263
 
261
264
  You can add definitions when initializing the schema.
@@ -271,7 +274,7 @@ class UserTableSchema
271
274
  end
272
275
 
273
276
  schema = UserTableSchema.new do
274
- column_converter :to_s do |val, *|
277
+ column_builder :to_s do |val|
275
278
  val.to_s
276
279
  end
277
280
  end
@@ -310,14 +313,14 @@ class SampleTableSchema
310
313
  column name: 'Name',
311
314
  value: ->(row, *) { row[:name] }
312
315
 
313
- columns ->(table) {
316
+ columns do |table|
314
317
  if table[:pet_num].positive?
315
318
  {
316
319
  name: (1..table[:pet_num]).map { |num| "Pet #{num}" },
317
320
  value: ->(row, *) { row[:pets] }
318
321
  }
319
322
  end
320
- }
323
+ end
321
324
  end
322
325
 
323
326
  context = { pet_num: 0 }
@@ -342,7 +345,7 @@ class SampleTableSchema
342
345
  TableContext.new(**context)
343
346
  end
344
347
 
345
- context_builder :row, :value do |context|
348
+ context_builder :row do |context|
346
349
  RowContext.new(**context)
347
350
  end
348
351
 
@@ -352,17 +355,17 @@ class SampleTableSchema
352
355
  column name: 'Name',
353
356
  value: ->(row, *) { row.name }
354
357
 
355
- columns name: ['Pet 1', 'Pet 2', 'Pet 3'],
358
+ column name: ['Pet 1', 'Pet 2', 'Pet 3'],
356
359
  value: ->(row, *) { row.increase_pets }
357
360
 
358
- columns ->(table) {
361
+ columns do |table|
359
362
  table.questions.map do |question|
360
363
  {
361
364
  name: question[:id],
362
365
  value: ->(row, *) { row.answers[question[:id]] }
363
366
  }
364
367
  end
365
- }
368
+ end
366
369
  end
367
370
  ```
368
371
 
@@ -388,13 +391,13 @@ class SampleTableSchema
388
391
 
389
392
  columns UserTableSchema
390
393
 
391
- columns ->(table) {
394
+ columns do |table|
392
395
  UserTableSchema.new(context: table, name_prefix: 'Friend ', key_prefix: 'friend_') do
393
396
  context_builder :row do |context|
394
397
  context[:friend]
395
398
  end
396
399
  end
397
- }
400
+ end
398
401
  end
399
402
 
400
403
  items = [
@@ -416,9 +419,9 @@ You can also concatenate or merge the schema classes.
416
419
  Both create a schema class, with a few differences.
417
420
  - `+`
418
421
  - Similar to nesting the schemas.
419
- `column_converter` works only to columns in the schema that they was defined.
422
+ `column_builder` works only to columns in the schema that they was defined.
420
423
  - `merge`
421
- - If there are some definitions of `column_converter` with the same name in the schemas to be merged, the one in the schema that is merged last will work to all columns.
424
+ - If there are some definitions of `column_builder` with the same name in the schemas to be merged, the one in the schema that is merged last will work to all columns.
422
425
 
423
426
  ```ruby
424
427
  class UserTableSchema
@@ -434,10 +437,10 @@ end
434
437
  class PetTableSchema
435
438
  include TableStructure::Schema
436
439
 
437
- columns name: ['Pet 1', 'Pet 2', 'Pet 3'],
440
+ column name: ['Pet 1', 'Pet 2', 'Pet 3'],
438
441
  value: ->(row, *) { row[:pets] }
439
442
 
440
- column_converter :same_name do |val, *|
443
+ column_builder :same_name do |val|
441
444
  "pet: #{val}"
442
445
  end
443
446
  end
@@ -445,16 +448,16 @@ end
445
448
  class QuestionTableSchema
446
449
  include TableStructure::Schema
447
450
 
448
- columns ->(table) {
451
+ columns do |table|
449
452
  table[:questions].map do |question|
450
453
  {
451
454
  name: question[:id],
452
455
  value: ->(row, *) { row[:answers][question[:id]] }
453
456
  }
454
457
  end
455
- }
458
+ end
456
459
 
457
- column_converter :same_name do |val, *|
460
+ column_builder :same_name do |val|
458
461
  "question: #{val}"
459
462
  end
460
463
  end
@@ -472,10 +475,6 @@ concatenated_schema = (UserTableSchema + PetTableSchema + QuestionTableSchema).n
472
475
  merged_schema = UserTableSchema.merge(PetTableSchema, QuestionTableSchema).new(context: context)
473
476
  ```
474
477
 
475
- ## Sample with docker
476
-
477
- https://github.com/jsmmr/ruby_table_structure_sample
478
-
479
478
  ## Contributing
480
479
 
481
480
  Bug reports and pull requests are welcome on GitHub at https://github.com/jsmmr/ruby_table_structure.
@@ -5,33 +5,27 @@ module TableStructure
5
5
 
6
6
  require 'table_structure/version'
7
7
  require 'forwardable'
8
+ require 'table_structure/utils'
8
9
  require 'table_structure/schema'
9
10
  require 'table_structure/schema/class_methods'
10
- require 'table_structure/schema/dsl/column_converter'
11
+ require 'table_structure/schema/composite_class'
12
+ require 'table_structure/schema/dsl/column_builder'
11
13
  require 'table_structure/schema/dsl/column_definition'
12
14
  require 'table_structure/schema/dsl/context_builder'
13
- require 'table_structure/schema/dsl/option'
14
15
  require 'table_structure/schema/dsl/row_builder'
15
- require 'table_structure/schema/definition/column_converter'
16
- require 'table_structure/schema/definition/context_builder'
17
- require 'table_structure/schema/definition/row_builder'
18
16
  require 'table_structure/schema/definition/columns/compiler'
19
17
  require 'table_structure/schema/definition/columns/error'
20
18
  require 'table_structure/schema/definition/columns/validator'
21
19
  require 'table_structure/schema/definition/columns/attributes'
22
20
  require 'table_structure/schema/definition/columns/schema_class'
23
21
  require 'table_structure/schema/definition/columns/schema_instance'
24
- require 'table_structure/schema/column_converter'
25
- require 'table_structure/schema/row_builder'
26
- require 'table_structure/schema/key_converter'
22
+ require 'table_structure/schema/column_builder_factory'
23
+ require 'table_structure/schema/keys_builder'
24
+ require 'table_structure/schema/row_context_builder_factory'
27
25
  require 'table_structure/schema/columns/attributes'
28
26
  require 'table_structure/schema/columns/schema'
29
27
  require 'table_structure/schema/utils'
30
28
  require 'table_structure/table'
31
- require 'table_structure/table/column_converter'
32
- require 'table_structure/table/context_builder'
33
- require 'table_structure/table/row_builder'
34
- require 'table_structure/table/iterator'
35
29
  require 'table_structure/writer'
36
30
  require 'table_structure/csv/writer'
37
31
  require 'table_structure/iterator'
@@ -9,32 +9,19 @@ module TableStructure
9
9
  schema,
10
10
  bom: false,
11
11
  csv_options: {},
12
- header: { context: nil },
13
- **deprecated_options
12
+ header: { context: nil, step: nil }
14
13
  )
15
- if deprecated_options.key?(:header_omitted)
16
- header_omitted = deprecated_options[:header_omitted]
17
- warn "[TableStructure] `header_omitted: #{!!header_omitted}` option has been deprecated. Use `header: #{!header_omitted}` option instead."
18
- header = !header_omitted
19
- end
20
-
21
- if deprecated_options.key?(:header_context)
22
- header_context = deprecated_options[:header_context]
23
- warn '[TableStructure] `:header_context` option has been deprecated. Use `header: { context: ... }` option instead.'
24
- header = { context: header_context }
25
- end
26
-
27
14
  require 'csv'
28
15
 
29
16
  @options = {
30
17
  bom: bom,
31
18
  csv_options: csv_options
32
19
  }
33
- @inner_options = {
20
+ inner_options = {
34
21
  header: header
35
22
  }
36
23
 
37
- @writer = ::TableStructure::Writer.new(schema, **@inner_options)
24
+ @writer = ::TableStructure::Writer.new(schema, **inner_options)
38
25
  end
39
26
 
40
27
  def write(
@@ -42,36 +29,12 @@ module TableStructure
42
29
  to:,
43
30
  bom: @options[:bom],
44
31
  csv_options: @options[:csv_options],
45
- **deprecated_options,
46
32
  &block
47
33
  )
48
- header = @inner_options[:header]
49
-
50
- if deprecated_options.key?(:header)
51
- header = deprecated_options[:header]
52
- warn '[TableStructure] Specify :header option as an argument for initialize method.'
53
- end
54
-
55
- if deprecated_options.key?(:header_omitted)
56
- header_omitted = deprecated_options[:header_omitted]
57
- warn "[TableStructure] `header_omitted: #{!!header_omitted}` option has been deprecated. Use `header: #{!header_omitted}` option instead."
58
- header = !header_omitted
59
- end
60
-
61
- if deprecated_options.key?(:header_context)
62
- header_context = deprecated_options[:header_context]
63
- warn '[TableStructure] `:header_context` option has been deprecated. Use `header: { context: ... }` option instead.'
64
- header = { context: header_context }
65
- end
66
-
67
- inner_options = {
68
- header: header
69
- }
70
-
71
34
  to << BOM if bom
72
35
 
73
36
  csv = ::CSV.new(to, **csv_options)
74
- @writer.write(items, to: csv, **inner_options, &block)
37
+ @writer.write(items, to: csv, &block)
75
38
  end
76
39
  end
77
40
  end
@@ -2,106 +2,65 @@
2
2
 
3
3
  module TableStructure
4
4
  class Iterator
5
- def initialize(
6
- schema,
7
- header: { context: nil },
8
- row_type: :array,
9
- **deprecated_options
10
- )
11
- if deprecated_options.key?(:header_omitted)
12
- header_omitted = deprecated_options[:header_omitted]
13
- warn "[TableStructure] `header_omitted: #{!!header_omitted}` option has been deprecated. Use `header: #{!header_omitted}` option instead."
14
- header = !header_omitted
5
+ class HeaderOptions
6
+ attr_reader :enabled, :context, :step
7
+ alias enabled? enabled
8
+
9
+ def initialize(options)
10
+ @enabled = !!options
11
+ if options.is_a?(Hash)
12
+ @context = options[:context]
13
+ @step = options[:step]
14
+ end
15
+
16
+ validate
15
17
  end
16
18
 
17
- if deprecated_options.key?(:header_context)
18
- header_context = deprecated_options[:header_context]
19
- warn '[TableStructure] `:header_context` option has been deprecated. Use `header: { context: ... }` option instead.'
20
- header = { context: header_context }
21
- end
19
+ private
22
20
 
23
- if deprecated_options.key?(:result_type)
24
- warn '[TableStructure] `:result_type` option has been deprecated. Use `:row_type` option instead.'
25
- row_type = deprecated_options[:result_type]
21
+ def validate
22
+ if @step
23
+ raise ::TableStructure::Error, ':step must be numeric.' unless @step.is_a?(Numeric)
24
+ raise ::TableStructure::Error, ':step must be positive number.' unless @step.positive?
25
+ end
26
26
  end
27
-
28
- unless schema.is_a?(Schema)
29
- raise ::TableStructure::Error, "Must be use Schema. #{schema}"
30
- end
31
-
32
- @schema = schema
33
- @options = {
34
- header: header,
35
- row_type: row_type
36
- }
37
27
  end
38
28
 
39
- def iterate(
40
- items,
41
- **deprecated_options,
42
- &block
29
+ def initialize(
30
+ schema,
31
+ header: { context: nil, step: nil },
32
+ row_type: :array
43
33
  )
44
- header = @options[:header]
45
- row_type = @options[:row_type]
46
-
47
- if deprecated_options.key?(:header)
48
- header = deprecated_options[:header]
49
- warn '[TableStructure] Use :header option on initialize method.'
50
- end
51
-
52
- if deprecated_options.key?(:header_omitted)
53
- header_omitted = deprecated_options[:header_omitted]
54
- warn "[TableStructure] `header_omitted: #{!!header_omitted}` option has been deprecated. Use `header: #{!header_omitted}` option instead."
55
- header = !header_omitted
56
- end
57
-
58
- if deprecated_options.key?(:header_context)
59
- header_context = deprecated_options[:header_context]
60
- warn '[TableStructure] `:header_context` option has been deprecated. Use `header: { context: ... }` option instead.'
61
- header = { context: header_context }
62
- end
63
-
64
- if deprecated_options.key?(:row_type)
65
- row_type = deprecated_options[:row_type]
66
- warn '[TableStructure] Use :row_type option on initialize method.'
67
- end
68
-
69
- if deprecated_options.key?(:result_type)
70
- warn '[TableStructure] `:result_type` option has been deprecated. Use `:row_type` option instead.'
71
- row_type = deprecated_options[:result_type]
72
- end
73
-
74
- items = enumerize(items)
75
-
76
- enum =
77
- Table::Iterator
78
- .new(
79
- Table.new(@schema, row_type: row_type),
80
- header: header
81
- )
82
- .iterate(items)
34
+ @table = Table.new(schema, row_type: row_type)
35
+ @header_options = HeaderOptions.new(header)
36
+ end
83
37
 
84
- if block_given?
85
- enum =
86
- enum
87
- .lazy
88
- .map { |row| block.call(row) }
38
+ def iterate(items, &block)
39
+ raise ::TableStructure::Error, "Must be enumerable. #{items}" unless items.respond_to?(:each)
40
+
41
+ table_enum = ::Enumerator.new do |y|
42
+ body_enum = @table.body(items)
43
+
44
+ if @header_options.enabled?
45
+ header_row = @table.header(context: @header_options.context)
46
+ y << header_row
47
+
48
+ if @header_options.step
49
+ loop do
50
+ @header_options.step.times { y << body_enum.next }
51
+ y << header_row
52
+ end
53
+ else
54
+ body_enum.each { |row| y << row }
55
+ end
56
+ else
57
+ body_enum.each { |row| y << row }
58
+ end
89
59
  end
90
60
 
91
- enum
92
- end
93
-
94
- private
61
+ table_enum = table_enum.lazy.map(&block) if block_given?
95
62
 
96
- def enumerize(items)
97
- if items.respond_to?(:each)
98
- items
99
- elsif items.respond_to?(:call)
100
- warn "[TableStructure] Use `Enumerator` to wrap items instead of `lambda`. The use of `lambda` has been deprecated. #{items}"
101
- Enumerator.new { |y| items.call(y) }
102
- else
103
- raise ::TableStructure::Error, "Must be enumerable. #{items}"
104
- end
63
+ table_enum
105
64
  end
106
65
  end
107
66
  end