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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b9fa7e8020098fb9dd2d9e2c9c984e0d71ff0aa02d4f568879bb013ae65b8d4
4
- data.tar.gz: 1e01f15d35797f4954b5a4861b6a8d44e54f3571fc81cd73c5ff2c08ac8ef550
3
+ metadata.gz: ab583e6beab687062935129db41650e353f23ec7ca2af9c610f49d8ac60a4811
4
+ data.tar.gz: 5999aab0a2a8bb37337d0923a2c06bffe9876dd8e8b4b879b799112090b4f393
5
5
  SHA512:
6
- metadata.gz: 97d59eb7d25b5ea806d908995f8978c8f711d280bd9c8b1e2dd0c09ca173f1c2fcf132f828e2218c17f3637fc6d92e8f7e12b827212ae404c153b2c5722cbbeb
7
- data.tar.gz: 3878dc2b2f38b9de6cc90c6644e3913379cecefd21adef98b35adf9cbcce3bf0fae4832491de6f3a063477b2d64416778c55e4f0383820cdfc75970d0ece5152
6
+ metadata.gz: b485fead56c787bc169135b0c084289fcc690c49a9bface4f5d394c5494ed1139096ea5da5916001a2a845a1817c057f40d8d498d005288958e1792ebfa96b72
7
+ data.tar.gz: 93a3912588240c7c3172e06f47d8226627e50016ab9444a43c4d60aa536919542e8cbf35cb6e7369a226e15796b1b25e9af77e168dcb16a3c1a8a6193a8b481b
@@ -2,8 +2,6 @@ env:
2
2
  global:
3
3
  - CC_TEST_REPORTER_ID=f40f0e6f9946420b05b247f1640b2f5fcef181ca86659a2e71c747f790fcecdd
4
4
  language: ruby
5
- services:
6
- - mysql
7
5
  rvm:
8
6
  # Build on the latest stable of all supported Rubies (https://www.ruby-lang.org/en/downloads/):
9
7
  - 2.5.8
@@ -17,7 +17,7 @@ require 'realize'
17
17
  require 'time'
18
18
 
19
19
  # Shared modules/classes
20
- require_relative 'portable/uniqueness'
20
+ require_relative 'portable/util'
21
21
 
22
22
  # Main implementation points
23
23
  require_relative 'portable/data'
@@ -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 Uniqueness
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
@@ -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 Uniqueness
16
+ include Util::Pivotable
17
+ include Util::Uniqueness
17
18
  acts_as_hashable
18
19
 
19
- attr_reader :sheets, :options
20
+ attr_reader :options
20
21
 
21
22
  def initialize(sheets: [], options: {})
22
- @sheets = Modeling::Sheet.array(sheets)
23
- @sheets << Modeling::Sheet.new if @sheets.empty?
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
- def initialize(columns: [])
22
- @columns = Column.array(columns)
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
- attr_reader :data_table,
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
- @name = name.to_s
35
- @data_table = DataTable.make(data_table)
36
- @footer_rows = footer_rows || []
37
- @header_rows = header_rows || []
38
- @include_headers = include_headers || false
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
- def include_headers?
44
- include_headers
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
- next unless sheet.data_table
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
- row_renderers.fetch(sheet_name, dynamic_row_renderer(fields))
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 dynamic_row_renderer(fields)
41
- fields = (fields || []).map { |f| { header: f.to_s } }
42
- columns = Modeling::Column.array(fields)
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
- Row.new(columns, resolver: resolver)
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
@@ -8,5 +8,5 @@
8
8
  #
9
9
 
10
10
  module Portable
11
- VERSION = '1.0.0-alpha.5'
11
+ VERSION = '1.0.0-alpha.6'
12
12
  end
@@ -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.name)
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.5
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-08 00:00:00.000000000 Z
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/uniqueness.rb
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
@@ -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