portable 1.0.0.pre.alpha.5 → 1.0.0.pre.alpha.6
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 +0 -2
- data/lib/portable.rb +1 -1
- data/lib/portable/data/provider.rb +2 -11
- data/lib/portable/document.rb +25 -7
- data/lib/portable/modeling/data_table.rb +8 -3
- data/lib/portable/modeling/sheet.rb +26 -12
- data/lib/portable/rendering/row.rb +7 -1
- data/lib/portable/rendering/sheet.rb +13 -8
- data/lib/portable/util.rb +11 -0
- data/lib/portable/util/pivotable.rb +19 -0
- data/lib/portable/util/uniqueness.rb +25 -0
- data/lib/portable/version.rb +1 -1
- data/lib/portable/writers/csv.rb +1 -1
- metadata +5 -3
- data/lib/portable/uniqueness.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab583e6beab687062935129db41650e353f23ec7ca2af9c610f49d8ac60a4811
|
4
|
+
data.tar.gz: 5999aab0a2a8bb37337d0923a2c06bffe9876dd8e8b4b879b799112090b4f393
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b485fead56c787bc169135b0c084289fcc690c49a9bface4f5d394c5494ed1139096ea5da5916001a2a845a1817c057f40d8d498d005288958e1792ebfa96b72
|
7
|
+
data.tar.gz: 93a3912588240c7c3172e06f47d8226627e50016ab9444a43c4d60aa536919542e8cbf35cb6e7369a226e15796b1b25e9af77e168dcb16a3c1a8a6193a8b481b
|
data/.travis.yml
CHANGED
data/lib/portable.rb
CHANGED
@@ -14,11 +14,10 @@ module Portable
|
|
14
14
|
# Container of data sources that is inputted into a writer alongside a document.
|
15
15
|
# It contains all the data sources the writer will use to render a document.
|
16
16
|
class Provider
|
17
|
-
include
|
17
|
+
include Util::Pivotable
|
18
|
+
include Util::Uniqueness
|
18
19
|
acts_as_hashable
|
19
20
|
|
20
|
-
DEFAULT_NAME = ''
|
21
|
-
|
22
21
|
def initialize(data_sources: [])
|
23
22
|
sources = Source.array(data_sources)
|
24
23
|
@data_sources_by_name = pivot_by_name(sources)
|
@@ -28,24 +27,16 @@ module Portable
|
|
28
27
|
freeze
|
29
28
|
end
|
30
29
|
|
31
|
-
# Use exact name if possible, if not then use the "default" one (noted by a blank name).
|
32
30
|
# Fail hard if we cannot identify which data source to use. This should help prevent
|
33
31
|
# possible configuration issues (i.e. typos.)
|
34
32
|
def data_source(name)
|
35
33
|
data_sources_by_name[name.to_s] ||
|
36
|
-
data_sources_by_name[DEFAULT_NAME] ||
|
37
34
|
raise(ArgumentError, "data source: '#{name}' cannot be found.")
|
38
35
|
end
|
39
36
|
|
40
37
|
private
|
41
38
|
|
42
39
|
attr_reader :data_sources_by_name
|
43
|
-
|
44
|
-
def pivot_by_name(data_sources)
|
45
|
-
data_sources.each_with_object({}) do |data_source, memo|
|
46
|
-
memo[data_source.name] = data_source
|
47
|
-
end
|
48
|
-
end
|
49
40
|
end
|
50
41
|
end
|
51
42
|
end
|
data/lib/portable/document.rb
CHANGED
@@ -13,19 +13,37 @@ require_relative 'modeling/sheet'
|
|
13
13
|
module Portable
|
14
14
|
# Top-level object model for a renderable document.
|
15
15
|
class Document
|
16
|
-
include
|
16
|
+
include Util::Pivotable
|
17
|
+
include Util::Uniqueness
|
17
18
|
acts_as_hashable
|
18
19
|
|
19
|
-
attr_reader :
|
20
|
+
attr_reader :options
|
20
21
|
|
21
22
|
def initialize(sheets: [], options: {})
|
22
|
-
@
|
23
|
-
@
|
24
|
-
@options = Modeling::Options.make(options)
|
25
|
-
|
26
|
-
assert_no_duplicate_names(@sheets)
|
23
|
+
@sheets_by_name = make_unique_sheets_by_name(sheets)
|
24
|
+
@options = Modeling::Options.make(options, nullable: false)
|
27
25
|
|
28
26
|
freeze
|
29
27
|
end
|
28
|
+
|
29
|
+
def sheet(name)
|
30
|
+
sheets_by_name.fetch(name.to_s)
|
31
|
+
end
|
32
|
+
|
33
|
+
def sheets
|
34
|
+
sheets_by_name.values
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_reader :sheets_by_name
|
40
|
+
|
41
|
+
def make_unique_sheets_by_name(sheets)
|
42
|
+
sheets = Modeling::Sheet.array(sheets)
|
43
|
+
sheets << Modeling::Sheet.new if sheets.empty?
|
44
|
+
|
45
|
+
assert_no_duplicate_names(sheets)
|
46
|
+
pivot_by_name(sheets)
|
47
|
+
end
|
30
48
|
end
|
31
49
|
end
|
@@ -16,10 +16,15 @@ module Portable
|
|
16
16
|
class DataTable
|
17
17
|
acts_as_hashable
|
18
18
|
|
19
|
-
attr_reader :columns
|
19
|
+
attr_reader :auto, :columns, :include_headers
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
alias include_headers? include_headers
|
22
|
+
alias auto? auto
|
23
|
+
|
24
|
+
def initialize(auto: true, columns: [], include_headers: true)
|
25
|
+
@auto = auto || false
|
26
|
+
@columns = Column.array(columns)
|
27
|
+
@include_headers = include_headers || false
|
23
28
|
|
24
29
|
freeze
|
25
30
|
end
|
@@ -17,31 +17,45 @@ module Portable
|
|
17
17
|
# one file.
|
18
18
|
class Sheet
|
19
19
|
acts_as_hashable
|
20
|
+
extend Forwardable
|
20
21
|
|
21
|
-
|
22
|
+
def_delegators :data_table,
|
23
|
+
:auto?,
|
24
|
+
:columns,
|
25
|
+
:include_headers?
|
26
|
+
|
27
|
+
attr_reader :data_source_name,
|
28
|
+
:data_table,
|
22
29
|
:footer_rows,
|
23
30
|
:header_rows,
|
24
|
-
:name
|
25
|
-
:include_headers
|
31
|
+
:name
|
26
32
|
|
27
33
|
def initialize(
|
34
|
+
data_source_name: '',
|
28
35
|
data_table: nil,
|
29
36
|
footer_rows: [],
|
30
37
|
header_rows: [],
|
31
|
-
name: ''
|
32
|
-
include_headers: true
|
38
|
+
name: ''
|
33
39
|
)
|
34
|
-
@
|
35
|
-
@
|
36
|
-
@
|
37
|
-
@
|
38
|
-
@
|
40
|
+
@data_source_name = decide_data_source_name(data_source_name, name)
|
41
|
+
@name = name.to_s
|
42
|
+
@data_table = DataTable.make(data_table, nullable: false)
|
43
|
+
@footer_rows = footer_rows || []
|
44
|
+
@header_rows = header_rows || []
|
39
45
|
|
40
46
|
freeze
|
41
47
|
end
|
42
48
|
|
43
|
-
|
44
|
-
|
49
|
+
# Use exact name if possible, if not then use the sheet name or else use the
|
50
|
+
# "default" one (noted by a blank name).
|
51
|
+
def decide_data_source_name(data_source_name, sheet_name)
|
52
|
+
if !data_source_name.to_s.empty?
|
53
|
+
data_source_name.to_s
|
54
|
+
elsif !sheet_name.to_s.empty?
|
55
|
+
sheet_name.to_s
|
56
|
+
else
|
57
|
+
''
|
58
|
+
end
|
45
59
|
end
|
46
60
|
end
|
47
61
|
end
|
@@ -12,9 +12,11 @@ module Portable
|
|
12
12
|
# Internal intermediary class that knows how to combine columns specification
|
13
13
|
# instances with their respective Realize pipelines.
|
14
14
|
class Row # :nodoc: all
|
15
|
-
attr_reader :column_pipelines
|
15
|
+
attr_reader :column_pipelines, :resolver
|
16
16
|
|
17
17
|
def initialize(columns, resolver: Objectable.resolver)
|
18
|
+
@resolver = resolver
|
19
|
+
|
18
20
|
@column_pipelines = columns.each_with_object({}) do |column, memo|
|
19
21
|
memo[column] = Realize::Pipeline.new(column.transformers, resolver: resolver)
|
20
22
|
end
|
@@ -35,6 +37,10 @@ module Portable
|
|
35
37
|
def headers
|
36
38
|
columns.map(&:header)
|
37
39
|
end
|
40
|
+
|
41
|
+
def merge(other)
|
42
|
+
self.class.new(columns + other.columns, resolver: resolver)
|
43
|
+
end
|
38
44
|
end
|
39
45
|
end
|
40
46
|
end
|
@@ -21,27 +21,32 @@ module Portable
|
|
21
21
|
@resolver = resolver
|
22
22
|
|
23
23
|
@row_renderers = @document.sheets.each_with_object({}) do |sheet, memo|
|
24
|
-
|
25
|
-
|
26
|
-
memo[sheet.name] = Row.new(sheet.data_table.columns, resolver: resolver)
|
24
|
+
memo[sheet.name] = Row.new(sheet.columns, resolver: resolver)
|
27
25
|
end
|
28
26
|
|
29
27
|
freeze
|
30
28
|
end
|
31
29
|
|
32
30
|
def row_renderer(sheet_name, fields)
|
33
|
-
|
31
|
+
sheet = document.sheet(sheet_name)
|
32
|
+
row_renderer = row_renderers.fetch(sheet_name.to_s)
|
33
|
+
|
34
|
+
return row_renderer unless sheet.auto?
|
35
|
+
|
36
|
+
dynamic_row_renderer(fields).merge(row_renderer)
|
34
37
|
end
|
35
38
|
|
36
39
|
private
|
37
40
|
|
38
41
|
attr_reader :row_renderers
|
39
42
|
|
40
|
-
def
|
41
|
-
fields
|
42
|
-
|
43
|
+
def fields_to_columns(fields)
|
44
|
+
fields = (fields || []).map { |f| { header: f.to_s } }
|
45
|
+
Modeling::Column.array(fields)
|
46
|
+
end
|
43
47
|
|
44
|
-
|
48
|
+
def dynamic_row_renderer(fields)
|
49
|
+
Row.new(fields_to_columns(fields), resolver: resolver)
|
45
50
|
end
|
46
51
|
end
|
47
52
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'util/pivotable'
|
11
|
+
require_relative 'util/uniqueness'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Portable
|
11
|
+
module Util # :nodoc: all
|
12
|
+
# Mixes in helpers for asserting uniqueness across collections
|
13
|
+
module Pivotable
|
14
|
+
def pivot_by_name(array)
|
15
|
+
array.each_with_object({}) { |object, memo| memo[object.name] = object }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Portable
|
11
|
+
module Util # :nodoc: all
|
12
|
+
# Mixes in helpers for asserting uniqueness across collections
|
13
|
+
module Uniqueness
|
14
|
+
class DuplicateNameError < StandardError; end
|
15
|
+
|
16
|
+
def assert_no_duplicate_names(array)
|
17
|
+
names = array.map { |a| a.name.downcase }
|
18
|
+
|
19
|
+
return if names.uniq.length == array.length
|
20
|
+
|
21
|
+
raise DuplicateNameError, "cannot contain duplicate names: #{names}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/portable/version.rb
CHANGED
data/lib/portable/writers/csv.rb
CHANGED
@@ -22,7 +22,7 @@ module Portable
|
|
22
22
|
sheet_filenames = extrapolate_filenames(filename, document.sheets.length)
|
23
23
|
|
24
24
|
document.sheets.map.with_index do |sheet, index|
|
25
|
-
data_source = data_provider.data_source(sheet.
|
25
|
+
data_source = data_provider.data_source(sheet.data_source_name)
|
26
26
|
sheet_filename = sheet_filenames[index]
|
27
27
|
|
28
28
|
time_in_seconds = Benchmark.measure do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: portable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.alpha.
|
4
|
+
version: 1.0.0.pre.alpha.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Ruggio
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-08-
|
11
|
+
date: 2020-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: acts_as_hashable
|
@@ -185,7 +185,9 @@ files:
|
|
185
185
|
- lib/portable/rendering.rb
|
186
186
|
- lib/portable/rendering/row.rb
|
187
187
|
- lib/portable/rendering/sheet.rb
|
188
|
-
- lib/portable/
|
188
|
+
- lib/portable/util.rb
|
189
|
+
- lib/portable/util/pivotable.rb
|
190
|
+
- lib/portable/util/uniqueness.rb
|
189
191
|
- lib/portable/version.rb
|
190
192
|
- lib/portable/writers.rb
|
191
193
|
- lib/portable/writers/base.rb
|
data/lib/portable/uniqueness.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
#
|
4
|
-
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
-
#
|
6
|
-
# This source code is licensed under the MIT license found in the
|
7
|
-
# LICENSE file in the root directory of this source tree.
|
8
|
-
#
|
9
|
-
|
10
|
-
module Portable
|
11
|
-
# Mixes in helpers for asserting uniqueness across collections
|
12
|
-
module Uniqueness
|
13
|
-
class DuplicateNameError < StandardError; end
|
14
|
-
|
15
|
-
def assert_no_duplicate_names(array)
|
16
|
-
names = array.map { |a| a.name.downcase }
|
17
|
-
|
18
|
-
return if names.uniq.length == array.length
|
19
|
-
|
20
|
-
raise DuplicateNameError, "cannot contain duplicate names: #{names}"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|