portable 1.0.0.pre.alpha.5 → 1.0.0.pre.alpha.6

Sign up to get free protection for your applications and to get access to all the features.
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