table_structure 0.4.1 → 0.4.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 +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +7 -7
- data/README.md +3 -3
- data/lib/table_structure.rb +6 -10
- data/lib/table_structure/iterator.rb +13 -4
- data/lib/table_structure/schema.rb +67 -41
- data/lib/table_structure/schema/class_methods.rb +2 -2
- data/lib/table_structure/schema/column_builder_factory.rb +75 -0
- data/lib/table_structure/schema/columns/attributes.rb +14 -9
- data/lib/table_structure/schema/columns/schema.rb +14 -9
- data/lib/table_structure/schema/composite_class.rb +40 -0
- data/lib/table_structure/schema/definition/columns/compiler.rb +7 -3
- data/lib/table_structure/schema/definition/columns/validator.rb +2 -6
- data/lib/table_structure/schema/dsl/column_builder.rb +29 -0
- data/lib/table_structure/schema/dsl/context_builder.rb +1 -4
- data/lib/table_structure/schema/dsl/row_builder.rb +2 -2
- data/lib/table_structure/schema/{key_converter.rb → keys_builder.rb} +2 -2
- data/lib/table_structure/schema/row_context_builder_factory.rb +30 -0
- data/lib/table_structure/table.rb +31 -46
- data/lib/table_structure/utils.rb +40 -0
- data/lib/table_structure/version.rb +1 -1
- data/lib/table_structure/writer.rb +0 -2
- metadata +8 -12
- data/lib/table_structure/schema/column_converter.rb +0 -46
- data/lib/table_structure/schema/definition/column_converter.rb +0 -31
- data/lib/table_structure/schema/definition/context_builder.rb +0 -17
- data/lib/table_structure/schema/definition/row_builder.rb +0 -25
- data/lib/table_structure/schema/dsl/column_converter.rb +0 -28
- data/lib/table_structure/schema/row_builder.rb +0 -21
- data/lib/table_structure/table/column_converter.rb +0 -46
- data/lib/table_structure/table/context_builder.rb +0 -49
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06f36abaa1bc4478901ea51a27e0e22b00ecf70ecbfd18b4c785c2e86e08ca1d
|
4
|
+
data.tar.gz: 26990e2f8ac30764a3d571dbf8a35e422ce163989f9eda5e92aa3c2b9e5cf498
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 288ea6944e5efa303a3c39e4502dce7b0d2994504796a7de0b69b28d8b0cd91f878670db9846a51cbb57d16797bb8124e50f2162db00ec89b49d83de3a345030
|
7
|
+
data.tar.gz: 72d983aef1de40282befe38d230806b1fb3deec4ecf08801822867d43ea656a6a307ad53c46ae87f2661bcc90ef5c6f0b3d8c5ea515eb80ddeb78e559b552585
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
# 0.4.2
|
2
|
+
Changes:
|
3
|
+
- `TableStructure::Schema`
|
4
|
+
- Improve performance.
|
5
|
+
- `TableStructure::Iterator`
|
6
|
+
- `TableStructure::Writer`
|
7
|
+
- `TableStructure::CSV::Writer`
|
8
|
+
- Add validation for `header: { step: n }` option.
|
9
|
+
- `n` is allowed positive number or `nil`(default).
|
10
|
+
|
1
11
|
# 0.4.1
|
2
12
|
Changes:
|
3
13
|
- `TableStructure::Iterator`
|
data/Gemfile.lock
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
table_structure (0.4.
|
4
|
+
table_structure (0.4.2)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
diff-lcs (1.
|
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.
|
16
|
-
rspec-support (~> 3.9.
|
17
|
-
rspec-expectations (3.9.
|
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.
|
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.
|
35
|
+
2.1.4
|
data/README.md
CHANGED
@@ -106,10 +106,10 @@ items = [
|
|
106
106
|
## or
|
107
107
|
# items = Enumerator.new { |y| Item.find_each { |item| y << item } }
|
108
108
|
|
109
|
-
|
110
|
-
writer.write(items, to:
|
109
|
+
array = []
|
110
|
+
writer.write(items, to: array)
|
111
111
|
|
112
|
-
#
|
112
|
+
# array
|
113
113
|
# => [["ID", "Name", "Pet 1", "Pet 2", "Pet 3", "Q1", "Q2", "Q3"], ["1", "Taro", "🐱", "🐶", "", "⭕️", "❌", "⭕️"], ["2", "Hanako", "🐇", "🐢", "🐿", "⭕️", "⭕️", "❌"]]
|
114
114
|
```
|
115
115
|
|
data/lib/table_structure.rb
CHANGED
@@ -5,31 +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/
|
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
15
|
require 'table_structure/schema/dsl/row_builder'
|
14
|
-
require 'table_structure/schema/definition/column_converter'
|
15
|
-
require 'table_structure/schema/definition/context_builder'
|
16
|
-
require 'table_structure/schema/definition/row_builder'
|
17
16
|
require 'table_structure/schema/definition/columns/compiler'
|
18
17
|
require 'table_structure/schema/definition/columns/error'
|
19
18
|
require 'table_structure/schema/definition/columns/validator'
|
20
19
|
require 'table_structure/schema/definition/columns/attributes'
|
21
20
|
require 'table_structure/schema/definition/columns/schema_class'
|
22
21
|
require 'table_structure/schema/definition/columns/schema_instance'
|
23
|
-
require 'table_structure/schema/
|
24
|
-
require 'table_structure/schema/
|
25
|
-
require 'table_structure/schema/
|
22
|
+
require 'table_structure/schema/column_builder_factory'
|
23
|
+
require 'table_structure/schema/keys_builder'
|
24
|
+
require 'table_structure/schema/row_context_builder_factory'
|
26
25
|
require 'table_structure/schema/columns/attributes'
|
27
26
|
require 'table_structure/schema/columns/schema'
|
28
27
|
require 'table_structure/schema/utils'
|
29
28
|
require 'table_structure/table'
|
30
|
-
require 'table_structure/table/column_converter'
|
31
|
-
require 'table_structure/table/context_builder'
|
32
|
-
require 'table_structure/table/row_builder'
|
33
29
|
require 'table_structure/writer'
|
34
30
|
require 'table_structure/csv/writer'
|
35
31
|
require 'table_structure/iterator'
|
@@ -12,6 +12,17 @@ module TableStructure
|
|
12
12
|
@context = options[:context]
|
13
13
|
@step = options[:step]
|
14
14
|
end
|
15
|
+
|
16
|
+
validate
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
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
|
15
26
|
end
|
16
27
|
end
|
17
28
|
|
@@ -25,9 +36,7 @@ module TableStructure
|
|
25
36
|
end
|
26
37
|
|
27
38
|
def iterate(items, &block)
|
28
|
-
unless items.respond_to?(:each)
|
29
|
-
raise ::TableStructure::Error, "Must be enumerable. #{items}"
|
30
|
-
end
|
39
|
+
raise ::TableStructure::Error, "Must be enumerable. #{items}" unless items.respond_to?(:each)
|
31
40
|
|
32
41
|
table_enum = ::Enumerator.new do |y|
|
33
42
|
body_enum = @table.body(items)
|
@@ -36,7 +45,7 @@ module TableStructure
|
|
36
45
|
header_row = @table.header(context: @header_options.context)
|
37
46
|
y << header_row
|
38
47
|
|
39
|
-
if @header_options.step
|
48
|
+
if @header_options.step
|
40
49
|
loop do
|
41
50
|
@header_options.step.times { y << body_enum.next }
|
42
51
|
y << header_row
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module TableStructure
|
4
4
|
module Schema
|
5
5
|
def self.included(klass)
|
6
|
-
klass.extend(DSL::
|
6
|
+
klass.extend(DSL::ColumnBuilder)
|
7
7
|
klass.extend(DSL::ColumnDefinition)
|
8
8
|
klass.extend(DSL::ContextBuilder)
|
9
9
|
klass.extend(DSL::RowBuilder)
|
@@ -11,20 +11,17 @@ module TableStructure
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.create_class(&block)
|
14
|
-
raise ::TableStructure::Error, 'No block given.' unless block
|
14
|
+
raise ::TableStructure::Error, 'No block has been given.' unless block
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
include schema_module
|
16
|
+
::Class.new do
|
17
|
+
include Schema
|
19
18
|
class_eval(&block)
|
20
19
|
end
|
21
20
|
end
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
:key_converter,
|
27
|
-
:row_builders,
|
22
|
+
Row = ::Struct.new(:keys, :values, :context)
|
23
|
+
|
24
|
+
attr_reader :row_builders,
|
28
25
|
:context
|
29
26
|
|
30
27
|
def initialize(
|
@@ -37,56 +34,85 @@ module TableStructure
|
|
37
34
|
nil_definitions_ignored: false,
|
38
35
|
&block
|
39
36
|
)
|
40
|
-
|
41
|
-
|
42
|
-
if block_given?
|
43
|
-
schema_classes << ::TableStructure::Schema.create_class(&block)
|
44
|
-
end
|
37
|
+
schema_class = CompositeClass.new.compose(self.class)
|
38
|
+
schema_class.compose(Schema.create_class(&block)) if block
|
45
39
|
|
46
|
-
|
47
|
-
schema_classes
|
48
|
-
.map(&:context_builders)
|
49
|
-
.reduce({}, &:merge!)
|
40
|
+
context_builders = schema_class.context_builders
|
50
41
|
|
51
|
-
table_context_builder =
|
42
|
+
table_context_builder = context_builders.delete(:table)
|
52
43
|
|
53
44
|
@context = table_context_builder ? table_context_builder.call(context) : context
|
54
45
|
|
55
|
-
@
|
56
|
-
|
57
|
-
|
58
|
-
.
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
)
|
64
|
-
)
|
46
|
+
@row_context_builder_factory = RowContextBuilderFactory.new(self, context_builders)
|
47
|
+
|
48
|
+
@column_builder_factory = ColumnBuilderFactory.new(
|
49
|
+
schema_class.column_builders,
|
50
|
+
context: @context,
|
51
|
+
name_prefix: name_prefix,
|
52
|
+
name_suffix: name_suffix
|
53
|
+
)
|
65
54
|
|
66
|
-
@
|
55
|
+
@keys_builder = KeysBuilder.new(
|
67
56
|
prefix: key_prefix,
|
68
57
|
suffix: key_suffix
|
69
58
|
)
|
70
59
|
|
71
|
-
@row_builders =
|
72
|
-
RowBuilder.prepend_default_builders(
|
73
|
-
schema_classes
|
74
|
-
.map(&:row_builders)
|
75
|
-
.reduce({}, &:merge!)
|
76
|
-
)
|
60
|
+
@row_builders = schema_class.row_builders
|
77
61
|
|
78
62
|
@columns =
|
79
63
|
Definition::Columns::Compiler
|
80
64
|
.new(
|
81
65
|
name,
|
82
|
-
|
83
|
-
|
66
|
+
schema_class.column_definitions,
|
67
|
+
nil_definitions_ignored: nil_definitions_ignored
|
84
68
|
)
|
85
69
|
.compile(@context)
|
86
70
|
end
|
87
71
|
|
88
|
-
def
|
89
|
-
@
|
72
|
+
def columns_keys
|
73
|
+
@columns_keys ||= @keys_builder.build(@columns.map(&:keys).flatten)
|
74
|
+
end
|
75
|
+
|
76
|
+
def columns_size
|
77
|
+
@columns.map(&:size).reduce(0, &:+)
|
78
|
+
end
|
79
|
+
|
80
|
+
def contain_name_callable?
|
81
|
+
@columns.any? { |column| column.name_callable? }
|
82
|
+
end
|
83
|
+
|
84
|
+
def contain_value_callable?
|
85
|
+
@columns.any? { |column| column.value_callable? }
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_header_row_generator
|
89
|
+
::TableStructure::Utils::CompositeCallable.new.compose(
|
90
|
+
@row_context_builder_factory.create_header_builder,
|
91
|
+
proc do |context|
|
92
|
+
values =
|
93
|
+
@columns
|
94
|
+
.map { |column| column.names(context, @context) }
|
95
|
+
.flatten
|
96
|
+
|
97
|
+
Row.new(columns_keys, values, context)
|
98
|
+
end,
|
99
|
+
@column_builder_factory.create_header_builder
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
def create_data_row_generator
|
104
|
+
::TableStructure::Utils::CompositeCallable.new.compose(
|
105
|
+
@row_context_builder_factory.create_data_builder,
|
106
|
+
proc do |context|
|
107
|
+
values =
|
108
|
+
@columns
|
109
|
+
.map { |column| column.values(context, @context) }
|
110
|
+
.flatten
|
111
|
+
|
112
|
+
Row.new(columns_keys, values, context)
|
113
|
+
end,
|
114
|
+
@column_builder_factory.create_data_builder
|
115
|
+
)
|
90
116
|
end
|
91
117
|
end
|
92
118
|
end
|
@@ -36,9 +36,9 @@ module TableStructure
|
|
36
36
|
.map(&:context_builders)
|
37
37
|
.reduce({}, &:merge!)
|
38
38
|
|
39
|
-
@
|
39
|
+
@__column_builders__ =
|
40
40
|
schema_classes
|
41
|
-
.map(&:
|
41
|
+
.map(&:column_builders)
|
42
42
|
.reduce({}, &:merge!)
|
43
43
|
|
44
44
|
@__row_builders__ =
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TableStructure
|
4
|
+
module Schema
|
5
|
+
class ColumnBuilderFactory
|
6
|
+
def initialize(
|
7
|
+
builders,
|
8
|
+
context: nil,
|
9
|
+
name_prefix: nil,
|
10
|
+
name_suffix: nil
|
11
|
+
)
|
12
|
+
@builders = builders
|
13
|
+
@context = context
|
14
|
+
|
15
|
+
optional_builders = {}
|
16
|
+
|
17
|
+
if name_prefix
|
18
|
+
optional_builders[:_name_prepender_] =
|
19
|
+
::TableStructure::Utils::TypedProc.new(
|
20
|
+
types: :header
|
21
|
+
) do |val, *|
|
22
|
+
val.nil? ? val : "#{name_prefix}#{val}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if name_suffix
|
27
|
+
optional_builders[:_name_appender_] =
|
28
|
+
::TableStructure::Utils::TypedProc.new(
|
29
|
+
types: :header
|
30
|
+
) do |val, *|
|
31
|
+
val.nil? ? val : "#{val}#{name_suffix}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
@builders.merge!(optional_builders) unless optional_builders.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_header_builder
|
39
|
+
builders =
|
40
|
+
@builders
|
41
|
+
.select { |_k, v| v.typed?(:header) }
|
42
|
+
.values
|
43
|
+
|
44
|
+
return if builders.empty?
|
45
|
+
|
46
|
+
proc do |row|
|
47
|
+
row.values = row.values.map do |value|
|
48
|
+
builders.reduce(value) do |value, builder|
|
49
|
+
builder.call(value, row.context, @context)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
row
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_data_builder
|
57
|
+
builders =
|
58
|
+
@builders
|
59
|
+
.select { |_k, v| v.typed?(:body) }
|
60
|
+
.values
|
61
|
+
|
62
|
+
return if builders.empty?
|
63
|
+
|
64
|
+
proc do |row|
|
65
|
+
row.values = row.values.map do |value|
|
66
|
+
builders.reduce(value) do |value, builder|
|
67
|
+
builder.call(value, row.context, @context)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
row
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -7,25 +7,30 @@ module TableStructure
|
|
7
7
|
attr_reader :keys, :size
|
8
8
|
|
9
9
|
def initialize(name:, key:, value:, size:)
|
10
|
-
@
|
10
|
+
@name_callable = Utils.callable?(name)
|
11
|
+
@name = @name_callable ? name : proc { name }
|
11
12
|
@keys = optimize_size([key].flatten, size)
|
12
|
-
@
|
13
|
+
@value_callable = Utils.callable?(value)
|
14
|
+
@value = @value_callable ? value : proc { value }
|
13
15
|
@size = size
|
14
16
|
end
|
15
17
|
|
16
18
|
def names(context, table_context)
|
17
|
-
|
18
|
-
optimize_size(
|
19
|
+
names = @name.call(context, table_context)
|
20
|
+
optimize_size(names, @size)
|
19
21
|
end
|
20
22
|
|
21
23
|
def values(context, table_context)
|
22
|
-
|
23
|
-
optimize_size(
|
24
|
+
values = @value.call(context, table_context)
|
25
|
+
optimize_size(values, @size)
|
24
26
|
end
|
25
27
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
28
|
+
def name_callable?
|
29
|
+
@name_callable
|
30
|
+
end
|
31
|
+
|
32
|
+
def value_callable?
|
33
|
+
@value_callable
|
29
34
|
end
|
30
35
|
|
31
36
|
private
|
@@ -6,27 +6,32 @@ module TableStructure
|
|
6
6
|
class Schema
|
7
7
|
def initialize(schema)
|
8
8
|
@schema = schema
|
9
|
-
@
|
9
|
+
@header_row_generator = schema.create_header_row_generator
|
10
|
+
@data_row_generator = schema.create_data_row_generator
|
10
11
|
end
|
11
12
|
|
12
|
-
def names(
|
13
|
-
@
|
13
|
+
def names(row_context, *)
|
14
|
+
@header_row_generator.call(row_context).values
|
14
15
|
end
|
15
16
|
|
16
17
|
def keys
|
17
|
-
@
|
18
|
+
@schema.columns_keys
|
18
19
|
end
|
19
20
|
|
20
|
-
def values(row_context,
|
21
|
-
@
|
21
|
+
def values(row_context, *)
|
22
|
+
@data_row_generator.call(row_context).values
|
22
23
|
end
|
23
24
|
|
24
25
|
def size
|
25
|
-
@
|
26
|
+
@schema.columns_size
|
26
27
|
end
|
27
28
|
|
28
|
-
def
|
29
|
-
@schema.
|
29
|
+
def name_callable?
|
30
|
+
@schema.contain_name_callable?
|
31
|
+
end
|
32
|
+
|
33
|
+
def value_callable?
|
34
|
+
@schema.contain_value_callable?
|
30
35
|
end
|
31
36
|
end
|
32
37
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TableStructure
|
4
|
+
module Schema
|
5
|
+
class CompositeClass
|
6
|
+
def initialize
|
7
|
+
@classes = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def compose(*classes)
|
11
|
+
@classes.concat(classes.flatten.compact)
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def column_definitions
|
16
|
+
@classes
|
17
|
+
.map(&:column_definitions)
|
18
|
+
.reduce([], &:concat)
|
19
|
+
end
|
20
|
+
|
21
|
+
def context_builders
|
22
|
+
@classes
|
23
|
+
.map(&:context_builders)
|
24
|
+
.reduce({}, &:merge!)
|
25
|
+
end
|
26
|
+
|
27
|
+
def column_builders
|
28
|
+
@classes
|
29
|
+
.map(&:column_builders)
|
30
|
+
.reduce({}, &:merge!)
|
31
|
+
end
|
32
|
+
|
33
|
+
def row_builders
|
34
|
+
@classes
|
35
|
+
.map(&:row_builders)
|
36
|
+
.reduce({}, &:merge!)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -5,10 +5,14 @@ module TableStructure
|
|
5
5
|
module Definition
|
6
6
|
module Columns
|
7
7
|
class Compiler
|
8
|
-
def initialize(
|
8
|
+
def initialize(
|
9
|
+
schema_name,
|
10
|
+
definitions,
|
11
|
+
nil_definitions_ignored: false
|
12
|
+
)
|
9
13
|
@schema_name = schema_name
|
10
14
|
@definitions = definitions
|
11
|
-
@
|
15
|
+
@nil_definitions_ignored = !!nil_definitions_ignored
|
12
16
|
end
|
13
17
|
|
14
18
|
def compile(context = nil)
|
@@ -26,7 +30,7 @@ module TableStructure
|
|
26
30
|
SchemaInstance.new(definition)
|
27
31
|
elsif Utils.schema_class?(definition)
|
28
32
|
SchemaClass.new(definition)
|
29
|
-
elsif definition.nil? && @
|
33
|
+
elsif definition.nil? && @nil_definitions_ignored
|
30
34
|
next
|
31
35
|
else
|
32
36
|
raise Error.new('Invalid definition.', @schema_name, i)
|
@@ -13,15 +13,11 @@ module TableStructure
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def validate(name:, key:, size:, **)
|
16
|
-
if key.respond_to?(:call)
|
17
|
-
raise Error.new('"key" must not be lambda.', @name, @index)
|
18
|
-
end
|
16
|
+
raise Error.new('"key" must not be lambda.', @name, @index) if key.respond_to?(:call)
|
19
17
|
if !key && name.respond_to?(:call) && !size
|
20
18
|
raise Error.new('"size" must be defined, because column size cannot be determined.', @name, @index)
|
21
19
|
end
|
22
|
-
if size && size < DEFAULT_SIZE
|
23
|
-
raise Error.new('"size" must be positive.', @name, @index)
|
24
|
-
end
|
20
|
+
raise Error.new('"size" must be positive.', @name, @index) if size && size < DEFAULT_SIZE
|
25
21
|
if key && size && [key].flatten.size < size
|
26
22
|
raise Error.new('"key" size must not be less than specified "size".', @name, @index)
|
27
23
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TableStructure
|
4
|
+
module Schema
|
5
|
+
module DSL
|
6
|
+
module ColumnBuilder
|
7
|
+
def column_builder(
|
8
|
+
name,
|
9
|
+
header: true,
|
10
|
+
body: true,
|
11
|
+
&block
|
12
|
+
)
|
13
|
+
column_builders[name] =
|
14
|
+
::TableStructure::Utils::TypedProc.new(
|
15
|
+
types: { header: !!header, body: !!body }.select { |_k, v| v }.keys,
|
16
|
+
&block
|
17
|
+
)
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def column_builders
|
22
|
+
@__column_builders__ ||= {}
|
23
|
+
end
|
24
|
+
|
25
|
+
alias column_converter column_builder
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -6,10 +6,7 @@ module TableStructure
|
|
6
6
|
module ContextBuilder
|
7
7
|
# TODO: Change definition style
|
8
8
|
def context_builder(name, &block)
|
9
|
-
context_builders[name] =
|
10
|
-
::TableStructure::Schema::Definition::ContextBuilder.new(
|
11
|
-
&block
|
12
|
-
)
|
9
|
+
context_builders[name] = block
|
13
10
|
nil
|
14
11
|
end
|
15
12
|
|
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
module TableStructure
|
4
4
|
module Schema
|
5
|
-
class
|
5
|
+
class KeysBuilder
|
6
6
|
def initialize(prefix: nil, suffix: nil)
|
7
7
|
@prefix = prefix
|
8
8
|
@suffix = suffix
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def build(keys)
|
12
12
|
return keys unless has_any_options?
|
13
13
|
|
14
14
|
keys.map do |key|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TableStructure
|
4
|
+
module Schema
|
5
|
+
class RowContextBuilderFactory
|
6
|
+
def initialize(schema, builders)
|
7
|
+
@schema = schema
|
8
|
+
@builders = builders
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_header_builder
|
12
|
+
return unless @schema.contain_name_callable?
|
13
|
+
return unless @builders.key?(:header)
|
14
|
+
|
15
|
+
proc do |context|
|
16
|
+
@builders[:header].call(context)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_data_builder
|
21
|
+
return unless @schema.contain_value_callable?
|
22
|
+
return unless @builders.key?(:row)
|
23
|
+
|
24
|
+
proc do |context|
|
25
|
+
@builders[:row].call(context)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -2,61 +2,46 @@
|
|
2
2
|
|
3
3
|
module TableStructure
|
4
4
|
class Table
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
apply_to_name: schema.contain_callable?(:name),
|
13
|
-
apply_to_value: schema.contain_callable?(:value),
|
14
|
-
context: schema.context
|
15
|
-
) { |mod| extend mod }
|
16
|
-
|
17
|
-
ColumnConverter.create_module(
|
18
|
-
schema.column_converters,
|
19
|
-
context: schema.context
|
20
|
-
) { |mod| extend mod }
|
5
|
+
DEFAULT_ROW_BUILDERS = {
|
6
|
+
_to_hash_: Utils::TypedProc.new(
|
7
|
+
types: :hash
|
8
|
+
) do |values, keys, *|
|
9
|
+
keys.map.with_index { |key, i| [key || i, values[i]] }.to_h
|
10
|
+
end
|
11
|
+
}.freeze
|
21
12
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
13
|
+
def initialize(schema, row_type: :array)
|
14
|
+
@header_row_generator = schema.create_header_row_generator
|
15
|
+
@data_row_generator = schema.create_data_row_generator
|
16
|
+
|
17
|
+
row_builders =
|
18
|
+
DEFAULT_ROW_BUILDERS
|
19
|
+
.merge(schema.row_builders)
|
20
|
+
.select { |_k, v| v.typed?(row_type) }
|
21
|
+
.values
|
22
|
+
|
23
|
+
unless row_builders.empty?
|
24
|
+
row_build_task = proc do |row|
|
25
|
+
row.values = row_builders.reduce(row.values) do |values, builder|
|
26
|
+
builder.call(values, row.keys, row.context, schema.context)
|
27
|
+
end
|
28
|
+
row
|
29
|
+
end
|
30
|
+
@header_row_generator.compose(row_build_task)
|
31
|
+
@data_row_generator.compose(row_build_task)
|
32
|
+
end
|
28
33
|
|
29
34
|
yield self if block_given?
|
30
35
|
end
|
31
36
|
|
32
37
|
def header(context: nil)
|
33
|
-
|
38
|
+
@header_row_generator.call(context).values
|
34
39
|
end
|
35
40
|
|
36
|
-
def body(
|
37
|
-
Enumerator.new do |y|
|
38
|
-
|
41
|
+
def body(contexts)
|
42
|
+
::Enumerator.new do |y|
|
43
|
+
contexts.each { |context| y << @data_row_generator.call(context).values }
|
39
44
|
end
|
40
45
|
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def data(context: nil)
|
45
|
-
row_values(:values, context)
|
46
|
-
end
|
47
|
-
|
48
|
-
def keys
|
49
|
-
@keys ||= @key_converter.convert(@columns.map(&:keys).flatten)
|
50
|
-
end
|
51
|
-
|
52
|
-
def size
|
53
|
-
@size ||= @columns.map(&:size).reduce(0, &:+)
|
54
|
-
end
|
55
|
-
|
56
|
-
def row_values(method, context)
|
57
|
-
@columns
|
58
|
-
.map { |column| column.send(method, context, @context) }
|
59
|
-
.flatten
|
60
|
-
end
|
61
46
|
end
|
62
47
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TableStructure
|
4
|
+
module Utils
|
5
|
+
class Proc < ::Proc
|
6
|
+
attr_reader :options
|
7
|
+
|
8
|
+
def initialize(**options, &block)
|
9
|
+
@options = options
|
10
|
+
super(&block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class TypedProc < Proc
|
15
|
+
def initialize(types:, **options, &block)
|
16
|
+
@types = [types].flatten.compact
|
17
|
+
super(**options, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def typed?(type)
|
21
|
+
@types.include?(type)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class CompositeCallable
|
26
|
+
def initialize
|
27
|
+
@callables = []
|
28
|
+
end
|
29
|
+
|
30
|
+
def compose(*callables)
|
31
|
+
@callables.concat(callables.flatten.compact)
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def call(source)
|
36
|
+
@callables.reduce(source) { |memo, callable| callable.call(memo) }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: table_structure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jsmmr
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -75,29 +75,25 @@ files:
|
|
75
75
|
- lib/table_structure/iterator.rb
|
76
76
|
- lib/table_structure/schema.rb
|
77
77
|
- lib/table_structure/schema/class_methods.rb
|
78
|
-
- lib/table_structure/schema/
|
78
|
+
- lib/table_structure/schema/column_builder_factory.rb
|
79
79
|
- lib/table_structure/schema/columns/attributes.rb
|
80
80
|
- lib/table_structure/schema/columns/schema.rb
|
81
|
-
- lib/table_structure/schema/
|
81
|
+
- lib/table_structure/schema/composite_class.rb
|
82
82
|
- lib/table_structure/schema/definition/columns/attributes.rb
|
83
83
|
- lib/table_structure/schema/definition/columns/compiler.rb
|
84
84
|
- lib/table_structure/schema/definition/columns/error.rb
|
85
85
|
- lib/table_structure/schema/definition/columns/schema_class.rb
|
86
86
|
- lib/table_structure/schema/definition/columns/schema_instance.rb
|
87
87
|
- lib/table_structure/schema/definition/columns/validator.rb
|
88
|
-
- lib/table_structure/schema/
|
89
|
-
- lib/table_structure/schema/definition/row_builder.rb
|
90
|
-
- lib/table_structure/schema/dsl/column_converter.rb
|
88
|
+
- lib/table_structure/schema/dsl/column_builder.rb
|
91
89
|
- lib/table_structure/schema/dsl/column_definition.rb
|
92
90
|
- lib/table_structure/schema/dsl/context_builder.rb
|
93
91
|
- lib/table_structure/schema/dsl/row_builder.rb
|
94
|
-
- lib/table_structure/schema/
|
95
|
-
- lib/table_structure/schema/
|
92
|
+
- lib/table_structure/schema/keys_builder.rb
|
93
|
+
- lib/table_structure/schema/row_context_builder_factory.rb
|
96
94
|
- lib/table_structure/schema/utils.rb
|
97
95
|
- lib/table_structure/table.rb
|
98
|
-
- lib/table_structure/
|
99
|
-
- lib/table_structure/table/context_builder.rb
|
100
|
-
- lib/table_structure/table/row_builder.rb
|
96
|
+
- lib/table_structure/utils.rb
|
101
97
|
- lib/table_structure/version.rb
|
102
98
|
- lib/table_structure/writer.rb
|
103
99
|
- table_structure.gemspec
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TableStructure
|
4
|
-
module Schema
|
5
|
-
module ColumnConverter
|
6
|
-
class << self
|
7
|
-
def create_optional_converters(
|
8
|
-
name_prefix: nil,
|
9
|
-
name_suffix: nil
|
10
|
-
)
|
11
|
-
column_converters = {}
|
12
|
-
|
13
|
-
if name_prefix
|
14
|
-
column_converters[:_name_prepender_] =
|
15
|
-
create_prepender(name_prefix, header: true, body: false)
|
16
|
-
end
|
17
|
-
|
18
|
-
if name_suffix
|
19
|
-
column_converters[:_name_appender_] =
|
20
|
-
create_appender(name_suffix, header: true, body: false)
|
21
|
-
end
|
22
|
-
|
23
|
-
column_converters
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def create_prepender(string, **options)
|
29
|
-
Definition::ColumnConverter.new(
|
30
|
-
**options
|
31
|
-
) do |val, *|
|
32
|
-
val.nil? ? val : "#{string}#{val}"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def create_appender(string, **options)
|
37
|
-
Definition::ColumnConverter.new(
|
38
|
-
**options
|
39
|
-
) do |val, *|
|
40
|
-
val.nil? ? val : "#{val}#{string}"
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TableStructure
|
4
|
-
module Schema
|
5
|
-
module Definition
|
6
|
-
class ColumnConverter
|
7
|
-
extend Forwardable
|
8
|
-
|
9
|
-
def_delegator :@callable, :call
|
10
|
-
|
11
|
-
def initialize(
|
12
|
-
header: true,
|
13
|
-
body: true,
|
14
|
-
&block
|
15
|
-
)
|
16
|
-
@applicable_to_header = header
|
17
|
-
@applicable_to_body = body
|
18
|
-
@callable = block
|
19
|
-
end
|
20
|
-
|
21
|
-
def applicable_to_header?
|
22
|
-
!!@applicable_to_header
|
23
|
-
end
|
24
|
-
|
25
|
-
def applicable_to_body?
|
26
|
-
!!@applicable_to_body
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TableStructure
|
4
|
-
module Schema
|
5
|
-
module Definition
|
6
|
-
class ContextBuilder
|
7
|
-
extend Forwardable
|
8
|
-
|
9
|
-
def_delegator :@callable, :call
|
10
|
-
|
11
|
-
def initialize(&block)
|
12
|
-
@callable = block
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TableStructure
|
4
|
-
module Schema
|
5
|
-
module Definition
|
6
|
-
class RowBuilder
|
7
|
-
extend Forwardable
|
8
|
-
|
9
|
-
def_delegator :@callable, :call
|
10
|
-
|
11
|
-
def initialize(
|
12
|
-
enabled_row_types: %i[array hash],
|
13
|
-
&block
|
14
|
-
)
|
15
|
-
@enabled_row_types = [enabled_row_types].flatten
|
16
|
-
@callable = block
|
17
|
-
end
|
18
|
-
|
19
|
-
def enabled?(row_type)
|
20
|
-
@enabled_row_types.include?(row_type)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TableStructure
|
4
|
-
module Schema
|
5
|
-
module DSL
|
6
|
-
module ColumnConverter
|
7
|
-
def column_converter(
|
8
|
-
name,
|
9
|
-
header: true,
|
10
|
-
body: true,
|
11
|
-
&block
|
12
|
-
)
|
13
|
-
column_converters[name] =
|
14
|
-
::TableStructure::Schema::Definition::ColumnConverter.new(
|
15
|
-
header: header,
|
16
|
-
body: body,
|
17
|
-
&block
|
18
|
-
)
|
19
|
-
nil
|
20
|
-
end
|
21
|
-
|
22
|
-
def column_converters
|
23
|
-
@__column_converters__ ||= {}
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TableStructure
|
4
|
-
module Schema
|
5
|
-
module RowBuilder
|
6
|
-
DEFAULT_ROW_BUILDERS = {
|
7
|
-
_to_hash_: Definition::RowBuilder.new(
|
8
|
-
enabled_row_types: [:hash]
|
9
|
-
) do |values, keys, *|
|
10
|
-
keys.map.with_index { |key, i| [key || i, values[i]] }.to_h
|
11
|
-
end
|
12
|
-
}.freeze
|
13
|
-
|
14
|
-
class << self
|
15
|
-
def prepend_default_builders(builders)
|
16
|
-
DEFAULT_ROW_BUILDERS.merge(builders)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TableStructure
|
4
|
-
class Table::ColumnConverter
|
5
|
-
class ColumnConvertible < Module
|
6
|
-
def initialize(methods)
|
7
|
-
methods.each do |name, method|
|
8
|
-
define_method(name, &method)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class << self
|
14
|
-
def create_module(converters, context:)
|
15
|
-
return if converters.empty?
|
16
|
-
|
17
|
-
header_converters = converters.select { |_k, v| v.applicable_to_header? }
|
18
|
-
body_converters = converters.select { |_k, v| v.applicable_to_body? }
|
19
|
-
|
20
|
-
methods = {}
|
21
|
-
|
22
|
-
unless header_converters.empty?
|
23
|
-
methods[:header] = create_method(header_converters, context)
|
24
|
-
end
|
25
|
-
|
26
|
-
unless body_converters.empty?
|
27
|
-
methods[:data] = create_method(body_converters, context)
|
28
|
-
end
|
29
|
-
|
30
|
-
yield ColumnConvertible.new(methods)
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def create_method(converters, table_context)
|
36
|
-
proc do |context: nil|
|
37
|
-
super(context: context).map do |val|
|
38
|
-
converters.reduce(val) do |val, (_, converter)|
|
39
|
-
converter.call(val, context, table_context)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TableStructure
|
4
|
-
class Table::ContextBuilder
|
5
|
-
class ContextBuildable < Module
|
6
|
-
def initialize(methods)
|
7
|
-
methods.each do |name, method|
|
8
|
-
define_method(name, &method)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class << self
|
14
|
-
def create_module(
|
15
|
-
builders,
|
16
|
-
apply_to_name: true,
|
17
|
-
apply_to_value: true,
|
18
|
-
context:
|
19
|
-
)
|
20
|
-
return if builders.empty?
|
21
|
-
|
22
|
-
header_builder = builders[:header] # TODO: Change not to use keyword of `header`
|
23
|
-
row_builder = builders[:row]
|
24
|
-
|
25
|
-
methods = {}
|
26
|
-
|
27
|
-
if apply_to_name && builders.key?(:header)
|
28
|
-
methods[:header] = create_method(builders[:header])
|
29
|
-
end
|
30
|
-
|
31
|
-
if apply_to_value && builders.key?(:row)
|
32
|
-
methods[:data] = create_method(builders[:row])
|
33
|
-
end
|
34
|
-
|
35
|
-
yield ContextBuildable.new(methods)
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def create_method(builder)
|
41
|
-
return if builder.nil?
|
42
|
-
|
43
|
-
proc do |context: nil|
|
44
|
-
super(context: builder.call(context))
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TableStructure
|
4
|
-
class Table::RowBuilder
|
5
|
-
class ResultBuildable < Module
|
6
|
-
def initialize(methods)
|
7
|
-
methods.each do |name, method|
|
8
|
-
define_method(name, &method)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class << self
|
14
|
-
def create_module(builders, row_type:, keys:, context:)
|
15
|
-
return if builders.empty?
|
16
|
-
|
17
|
-
builders = builders.select { |_k, v| v.enabled?(row_type) }
|
18
|
-
return if builders.empty?
|
19
|
-
|
20
|
-
yield ResultBuildable.new(
|
21
|
-
header: create_method(builders, keys, context),
|
22
|
-
data: create_method(builders, keys, context)
|
23
|
-
)
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def create_method(builders, table_keys, table_context)
|
29
|
-
proc do |context: nil|
|
30
|
-
builders
|
31
|
-
.reduce(super(context: context)) do |vals, (_, builder)|
|
32
|
-
builder.call(vals, table_keys, context, table_context)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|