portable 1.0.0.pre.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +8 -0
- data/.gitignore +6 -0
- data/.rubocop.yml +32 -0
- data/.ruby-version +1 -0
- data/.travis.yml +26 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +5 -0
- data/Guardfile +16 -0
- data/LICENSE +7 -0
- data/README.md +169 -0
- data/Rakefile +17 -0
- data/bin/console +18 -0
- data/exe/.gitkeep +0 -0
- data/lib/portable.rb +17 -0
- data/lib/portable/column.rb +37 -0
- data/lib/portable/export.rb +39 -0
- data/lib/portable/transformer.rb +32 -0
- data/lib/portable/version.rb +12 -0
- data/lib/portable/writer.rb +82 -0
- data/portable.gemspec +42 -0
- metadata +210 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 06ca8f7296a55a271a94e228c6e47f7c8d572e42ed43ea7f03b3dc9547b05fc1
|
4
|
+
data.tar.gz: ebc9dc0c2f3867c468e27e4976a9f8a9304f739449b228b520a97cd14ec23b2f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1497db394e1dab96acbe34327a683e5e3390f0912461c8ae2e312def8996b7add5f025012e9871ccb3193014d123e23ba2993625af9a462e86756f00d00b1550
|
7
|
+
data.tar.gz: 5e0ea223a2d1894075e6fcf07b0eecd6a7242e37263ba7bea4e01ffefe22f95c7bcaad18fef35e74ae4b7435efc8012636dcb1e0d10a349c802327726a65dcf1
|
data/.editorconfig
ADDED
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.5
|
3
|
+
NewCops: enable
|
4
|
+
|
5
|
+
Layout/LineLength:
|
6
|
+
Max: 100
|
7
|
+
Exclude:
|
8
|
+
- portable.gemspec
|
9
|
+
|
10
|
+
Metrics/BlockLength:
|
11
|
+
ExcludedMethods:
|
12
|
+
- let
|
13
|
+
- it
|
14
|
+
- describe
|
15
|
+
- context
|
16
|
+
- specify
|
17
|
+
- define
|
18
|
+
|
19
|
+
Metrics/MethodLength:
|
20
|
+
Max: 30
|
21
|
+
|
22
|
+
Metrics/AbcSize:
|
23
|
+
Max: 16
|
24
|
+
|
25
|
+
Metrics/ClassLength:
|
26
|
+
Max: 125
|
27
|
+
|
28
|
+
Style/TrailingCommaInHashLiteral:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Style/TrailingCommaInArrayLiteral:
|
32
|
+
Enabled: false
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.6.6
|
data/.travis.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
env:
|
2
|
+
global:
|
3
|
+
- CC_TEST_REPORTER_ID=f40f0e6f9946420b05b247f1640b2f5fcef181ca86659a2e71c747f790fcecdd
|
4
|
+
language: ruby
|
5
|
+
services:
|
6
|
+
- mysql
|
7
|
+
rvm:
|
8
|
+
# Build on the latest stable of all supported Rubies (https://www.ruby-lang.org/en/downloads/):
|
9
|
+
- 2.5.8
|
10
|
+
- 2.6.6
|
11
|
+
- 2.7.1
|
12
|
+
cache: bundler
|
13
|
+
before_script:
|
14
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
15
|
+
- chmod +x ./cc-test-reporter
|
16
|
+
- ./cc-test-reporter before-build
|
17
|
+
script:
|
18
|
+
- bundle exec rubocop
|
19
|
+
- bundle exec rspec spec --format documentation
|
20
|
+
after_script:
|
21
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
22
|
+
addons:
|
23
|
+
# https://docs.travis-ci.com/user/uploading-artifacts/
|
24
|
+
artifacts:
|
25
|
+
paths:
|
26
|
+
- Gemfile.lock
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
guard :rspec, cmd: 'DISABLE_SIMPLECOV=true bundle exec rspec --format=documentation' do
|
4
|
+
require 'guard/rspec/dsl'
|
5
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
6
|
+
|
7
|
+
# RSpec files
|
8
|
+
rspec = dsl.rspec
|
9
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
10
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
11
|
+
watch(rspec.spec_files)
|
12
|
+
|
13
|
+
# Ruby files
|
14
|
+
ruby = dsl.ruby
|
15
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
16
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright 2020 Blue Marble Payroll, LLC
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
# Portable
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/portable.svg)](https://badge.fury.io/rb/portable) [![Build Status](https://travis-ci.org/bluemarblepayroll/portable.svg?branch=master)](https://travis-ci.org/bluemarblepayroll/portable) [![Maintainability](https://api.codeclimate.com/v1/badges/4b47ce94b0c9d889e648/maintainability)](https://codeclimate.com/github/bluemarblepayroll/portable/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/4b47ce94b0c9d889e648/test_coverage)](https://codeclimate.com/github/bluemarblepayroll/portable/test_coverage) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
4
|
+
|
5
|
+
This library provides a configuration layer that allows you to express transformations, using [Realize](https://github.com/bluemarblepayroll/realize), and will write the transformed data down to disk. Essentially it is meant to be the transformation and load steps within a larger ETL system. We currently use this in production paired up with [Dbee](https://github.com/bluemarblepayroll/dbee) to go from configurable data model + query to file.
|
6
|
+
|
7
|
+
Current limitations:
|
8
|
+
|
9
|
+
1. Only supports CSV with limited options
|
10
|
+
2. Only supports writing to local file system.
|
11
|
+
|
12
|
+
Future extension considerations:
|
13
|
+
|
14
|
+
1. Support Excel and richer formatting, sheets, etc.
|
15
|
+
2. Expand CSV options: delimiter, forcing quotes, etc.
|
16
|
+
3. Support PDF
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
To install through Rubygems:
|
21
|
+
|
22
|
+
````
|
23
|
+
gem install install portable
|
24
|
+
````
|
25
|
+
|
26
|
+
You can also add this to your Gemfile:
|
27
|
+
|
28
|
+
````
|
29
|
+
bundle add portable
|
30
|
+
````
|
31
|
+
|
32
|
+
## Examples
|
33
|
+
|
34
|
+
### Getting Started with Exports
|
35
|
+
|
36
|
+
Consider the following data set as an array of hashes:
|
37
|
+
|
38
|
+
````ruby
|
39
|
+
patients = [
|
40
|
+
{ first: 'Marky', last: 'Mark', dob: '2000-04-05' },
|
41
|
+
{ first: 'Frank', last: 'Rizzo', dob: '1930-09-22' }
|
42
|
+
]
|
43
|
+
````
|
44
|
+
|
45
|
+
We could configure an export like so:
|
46
|
+
|
47
|
+
````ruby
|
48
|
+
export = {
|
49
|
+
columns: [
|
50
|
+
{ header: :first },
|
51
|
+
{ header: :last },
|
52
|
+
{ header: :dob }
|
53
|
+
]
|
54
|
+
}
|
55
|
+
````
|
56
|
+
|
57
|
+
And execute the export against the example dataset in order to generate a CSV file:
|
58
|
+
|
59
|
+
````ruby
|
60
|
+
writer = Portable::Writer.new(export)
|
61
|
+
filename = File.join('tmp', 'patients.csv')
|
62
|
+
|
63
|
+
writer.open(filename) do |writer|
|
64
|
+
patients.each do |patient|
|
65
|
+
writer.write(object: patient)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
````
|
69
|
+
|
70
|
+
We should now have a CSV file at tmp/patients.csv that looks like this:
|
71
|
+
|
72
|
+
first | last | dob
|
73
|
+
----- | ---- | -----
|
74
|
+
Marky | Mark | 2000-04-05
|
75
|
+
Frank | Rizzo | 1930-09-22
|
76
|
+
|
77
|
+
### Realize Transformation Pipelines
|
78
|
+
|
79
|
+
This library uses Realize under the hood, so you have the option of configuring any transformation pipeline for each column. Reviewing [Realize's list of transformers](https://github.com/bluemarblepayroll/realize#transformer-gallery) is recommended to see what is available.
|
80
|
+
|
81
|
+
Let's expand our example above with different headers and date formatting:
|
82
|
+
|
83
|
+
````ruby
|
84
|
+
export = {
|
85
|
+
columns: [
|
86
|
+
{
|
87
|
+
header: 'First Name',
|
88
|
+
transformers: [
|
89
|
+
{ type: 'r/value/resolve', key: :first }
|
90
|
+
]
|
91
|
+
},
|
92
|
+
{
|
93
|
+
header: 'Last Name',
|
94
|
+
transformers: [
|
95
|
+
{ type: 'r/value/resolve', key: :last }
|
96
|
+
]
|
97
|
+
},
|
98
|
+
{
|
99
|
+
header: 'Date of Birth',
|
100
|
+
transformers: [
|
101
|
+
{ type: 'r/value/resolve', key: :dob },
|
102
|
+
{ type: 'r/format/date', output_format: '%m/%d/%Y' },
|
103
|
+
]
|
104
|
+
}
|
105
|
+
]
|
106
|
+
}
|
107
|
+
````
|
108
|
+
|
109
|
+
Executing it the same way would now yield a different CSV file:
|
110
|
+
|
111
|
+
First Name | Last Name | Date of Birth
|
112
|
+
---------- | --------- | -------------
|
113
|
+
Marky | Mark | 04/05/2000
|
114
|
+
Frank | Rizzo | 09/22/1930
|
115
|
+
|
116
|
+
Realize is also [pluggable](https://github.com/bluemarblepayroll/realize#plugging-in-transformers), so you are able to create your own and plug them directly into Realize.
|
117
|
+
|
118
|
+
## Contributing
|
119
|
+
|
120
|
+
### Development Environment Configuration
|
121
|
+
|
122
|
+
Basic steps to take to get this repository compiling:
|
123
|
+
|
124
|
+
1. Install [Ruby](https://www.ruby-lang.org/en/documentation/installation/) (check portable.gemspec for versions supported)
|
125
|
+
2. Install bundler (gem install bundler)
|
126
|
+
3. Clone the repository (git clone git@github.com:bluemarblepayroll/portable.git)
|
127
|
+
4. Navigate to the root folder (cd portable)
|
128
|
+
5. Install dependencies (bundle)
|
129
|
+
|
130
|
+
### Running Tests
|
131
|
+
|
132
|
+
To execute the test suite run:
|
133
|
+
|
134
|
+
````bash
|
135
|
+
bundle exec rspec spec --format documentation
|
136
|
+
````
|
137
|
+
|
138
|
+
Alternatively, you can have Guard watch for changes:
|
139
|
+
|
140
|
+
````bash
|
141
|
+
bundle exec guard
|
142
|
+
````
|
143
|
+
|
144
|
+
Also, do not forget to run Rubocop:
|
145
|
+
|
146
|
+
````bash
|
147
|
+
bundle exec rubocop
|
148
|
+
````
|
149
|
+
|
150
|
+
### Publishing
|
151
|
+
|
152
|
+
Note: ensure you have proper authorization before trying to publish new versions.
|
153
|
+
|
154
|
+
After code changes have successfully gone through the Pull Request review process then the following steps should be followed for publishing new versions:
|
155
|
+
|
156
|
+
1. Merge Pull Request into master
|
157
|
+
2. Update `lib/portable/version.rb` using [semantic versioning](https://semver.org/)
|
158
|
+
3. Install dependencies: `bundle`
|
159
|
+
4. Update `CHANGELOG.md` with release notes
|
160
|
+
5. Commit & push master to remote and ensure CI builds master successfully
|
161
|
+
6. Run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
162
|
+
|
163
|
+
## Code of Conduct
|
164
|
+
|
165
|
+
Everyone interacting in this codebase, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/bluemarblepayroll/portable/blob/master/CODE_OF_CONDUCT.md).
|
166
|
+
|
167
|
+
## License
|
168
|
+
|
169
|
+
This project is MIT Licensed.
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
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 'bundler/gem_tasks'
|
11
|
+
require 'rspec/core/rake_task'
|
12
|
+
require 'rubocop/rake_task'
|
13
|
+
|
14
|
+
RSpec::Core::RakeTask.new(:spec)
|
15
|
+
RuboCop::RakeTask.new
|
16
|
+
|
17
|
+
task default: %i[rubocop spec]
|
data/bin/console
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
6
|
+
#
|
7
|
+
# This source code is licensed under the MIT license found in the
|
8
|
+
# LICENSE file in the root directory of this source tree.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'bundler/setup'
|
12
|
+
require 'portable'
|
13
|
+
|
14
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
15
|
+
# with your gem easier. You can also use a different console, if you like.
|
16
|
+
|
17
|
+
require 'pry'
|
18
|
+
Pry.start
|
data/exe/.gitkeep
ADDED
File without changes
|
data/lib/portable.rb
ADDED
@@ -0,0 +1,17 @@
|
|
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 'acts_as_hashable'
|
11
|
+
require 'csv'
|
12
|
+
require 'fileutils'
|
13
|
+
require 'objectable'
|
14
|
+
require 'realize'
|
15
|
+
require 'time'
|
16
|
+
|
17
|
+
require_relative 'portable/writer'
|
@@ -0,0 +1,37 @@
|
|
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
|
+
# Defines all the options a column can contain. The most basic would to just include a header
|
12
|
+
# (defaults to ''). If no transformers are defined then a simple resolver using the header
|
13
|
+
# will be used. This works well for pass-through file writes. Use the transformers to further
|
14
|
+
# customize each data point being written.
|
15
|
+
class Column
|
16
|
+
acts_as_hashable
|
17
|
+
|
18
|
+
DEFAULT_TRANSFORMER_TYPE = 'r/value/resolve'
|
19
|
+
|
20
|
+
attr_reader :header, :transformers
|
21
|
+
|
22
|
+
def initialize(header: '', transformers: [])
|
23
|
+
@header = header.to_s
|
24
|
+
@transformers = Realize::Transformers.array(transformers)
|
25
|
+
|
26
|
+
@transformers << default_transformer if @transformers.empty?
|
27
|
+
|
28
|
+
freeze
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def default_transformer
|
34
|
+
Realize::Transformers.make(type: DEFAULT_TRANSFORMER_TYPE, key: header)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,39 @@
|
|
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 'column'
|
11
|
+
|
12
|
+
module Portable
|
13
|
+
# Defines all the options for an export like columns, whether or not you want to include
|
14
|
+
# headers, and more.
|
15
|
+
class Export
|
16
|
+
acts_as_hashable
|
17
|
+
|
18
|
+
module Bom
|
19
|
+
UTF8 = "\uFEFF"
|
20
|
+
end
|
21
|
+
include Bom
|
22
|
+
|
23
|
+
attr_reader :bom, :columns, :include_headers
|
24
|
+
|
25
|
+
alias include_headers? include_headers
|
26
|
+
|
27
|
+
def initialize(bom: nil, columns: [], include_headers: true)
|
28
|
+
@bom = bom ? Bom.const_get(bom.to_s.upcase.to_sym) : nil
|
29
|
+
@columns = Column.array(columns)
|
30
|
+
@include_headers = include_headers || false
|
31
|
+
|
32
|
+
freeze
|
33
|
+
end
|
34
|
+
|
35
|
+
def headers
|
36
|
+
columns.map(&:header)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
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 'export'
|
11
|
+
|
12
|
+
module Portable
|
13
|
+
# Internal intermediary class that knows how to combine columns specification instances with their
|
14
|
+
# respective Realize pipelines.
|
15
|
+
class Transformer # :nodoc: all
|
16
|
+
attr_reader :column_pipelines
|
17
|
+
|
18
|
+
def initialize(columns, resolver: Objectable.resolver)
|
19
|
+
@column_pipelines = columns.each_with_object({}) do |column, memo|
|
20
|
+
memo[column] = Realize::Pipeline.new(column.transformers, resolver: resolver)
|
21
|
+
end
|
22
|
+
|
23
|
+
freeze
|
24
|
+
end
|
25
|
+
|
26
|
+
def transform(object, time)
|
27
|
+
column_pipelines.each_with_object({}) do |(column, pipeline), memo|
|
28
|
+
memo[column.header] = pipeline.transform(object, time)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,12 @@
|
|
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
|
+
VERSION = '1.0.0-alpha'
|
12
|
+
end
|
@@ -0,0 +1,82 @@
|
|
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 'export'
|
11
|
+
require_relative 'transformer'
|
12
|
+
|
13
|
+
module Portable
|
14
|
+
# Main API for writing files. There are two main patterns to choose from:
|
15
|
+
# 1. calling #open, #write, and #close manually.
|
16
|
+
# 2. calling #open and passing a block and having #close automatically called.
|
17
|
+
class Writer
|
18
|
+
class AlreadyOpenError < StandardError; end
|
19
|
+
class NotOpenError < StandardError; end
|
20
|
+
|
21
|
+
attr_reader :csv, :export, :transformer
|
22
|
+
|
23
|
+
def initialize(export, resolver: Objectable.resolver)
|
24
|
+
@export = Export.make(export, nullable: false)
|
25
|
+
@transformer = Transformer.new(@export.columns, resolver: resolver)
|
26
|
+
end
|
27
|
+
|
28
|
+
def open?
|
29
|
+
!csv.nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
# Will raise a AlreadyOpenError exception if a writer has already been opened but
|
33
|
+
# not yet closed.
|
34
|
+
def open(filename)
|
35
|
+
raise AlreadyOpenError, 'writer is already open' if open?
|
36
|
+
|
37
|
+
initialize_csv(filename)
|
38
|
+
|
39
|
+
if block_given?
|
40
|
+
yield self
|
41
|
+
close
|
42
|
+
end
|
43
|
+
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
# Will raise a NotOpenError exception if a writer has not yet been opened.
|
48
|
+
def write(object: {}, time: Time.now.utc)
|
49
|
+
raise NotOpenError, 'writer is not open' unless open?
|
50
|
+
|
51
|
+
csv << transformer.transform(object, time).values
|
52
|
+
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
# Will raise a NotOpenError exception if a writer has not yet been opened.
|
57
|
+
def close
|
58
|
+
raise NotOpenError, 'writer is not open' unless open?
|
59
|
+
|
60
|
+
@csv.close
|
61
|
+
@csv = nil
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def ensure_directory_exists(filename)
|
68
|
+
path = File.dirname(filename)
|
69
|
+
|
70
|
+
FileUtils.mkdir_p(path) unless File.exist?(path)
|
71
|
+
end
|
72
|
+
|
73
|
+
def initialize_csv(filename)
|
74
|
+
ensure_directory_exists(filename)
|
75
|
+
|
76
|
+
@csv = CSV.open(filename, 'w')
|
77
|
+
|
78
|
+
csv.to_io.write(export.bom) if export.bom
|
79
|
+
csv << export.headers if export.include_headers?
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/portable.gemspec
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require './lib/portable/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'portable'
|
7
|
+
s.version = Portable::VERSION
|
8
|
+
s.summary = 'Transformable export writer'
|
9
|
+
|
10
|
+
s.description = <<-DESCRIPTION
|
11
|
+
This library allows you to configure exports, using Realize pipelines, creating a transformation and writing layer. It is meant to serve as an intermediary library within a much larger ETL framework.
|
12
|
+
DESCRIPTION
|
13
|
+
|
14
|
+
s.authors = ['Matthew Ruggio']
|
15
|
+
s.email = ['mruggio@bluemarblepayroll.com']
|
16
|
+
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
s.bindir = 'exe'
|
18
|
+
s.executables = []
|
19
|
+
s.homepage = 'https://github.com/bluemarblepayroll/portable'
|
20
|
+
s.license = 'MIT'
|
21
|
+
s.metadata = {
|
22
|
+
'bug_tracker_uri' => 'https://github.com/bluemarblepayroll/portable/issues',
|
23
|
+
'changelog_uri' => 'https://github.com/bluemarblepayroll/portable/blob/master/CHANGELOG.md',
|
24
|
+
'documentation_uri' => 'https://www.rubydoc.info/gems/portable',
|
25
|
+
'homepage_uri' => s.homepage,
|
26
|
+
'source_code_uri' => s.homepage
|
27
|
+
}
|
28
|
+
|
29
|
+
s.required_ruby_version = '>= 2.5'
|
30
|
+
|
31
|
+
s.add_dependency('acts_as_hashable', '~>1')
|
32
|
+
s.add_dependency('objectable', '~>1')
|
33
|
+
s.add_dependency('realize', '~>1.1')
|
34
|
+
|
35
|
+
s.add_development_dependency('guard-rspec', '~>4.7')
|
36
|
+
s.add_development_dependency('pry', '~>0')
|
37
|
+
s.add_development_dependency('rake', '~> 13')
|
38
|
+
s.add_development_dependency('rspec', '~> 3.8')
|
39
|
+
s.add_development_dependency('rubocop', '~>0.88.0')
|
40
|
+
s.add_development_dependency('simplecov', '~>0.18.5')
|
41
|
+
s.add_development_dependency('simplecov-console', '~>0.7.0')
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: portable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.pre.alpha
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matthew Ruggio
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-08-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: acts_as_hashable
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: objectable
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: realize
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.1'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: guard-rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '4.7'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '4.7'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '13'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '13'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.8'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.8'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.88.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.88.0
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: simplecov
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.18.5
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 0.18.5
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: simplecov-console
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 0.7.0
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 0.7.0
|
153
|
+
description: " This library allows you to configure exports, using Realize pipelines,
|
154
|
+
creating a transformation and writing layer. It is meant to serve as an intermediary
|
155
|
+
library within a much larger ETL framework.\n"
|
156
|
+
email:
|
157
|
+
- mruggio@bluemarblepayroll.com
|
158
|
+
executables: []
|
159
|
+
extensions: []
|
160
|
+
extra_rdoc_files: []
|
161
|
+
files:
|
162
|
+
- ".editorconfig"
|
163
|
+
- ".gitignore"
|
164
|
+
- ".rubocop.yml"
|
165
|
+
- ".ruby-version"
|
166
|
+
- ".travis.yml"
|
167
|
+
- CHANGELOG.md
|
168
|
+
- Gemfile
|
169
|
+
- Guardfile
|
170
|
+
- LICENSE
|
171
|
+
- README.md
|
172
|
+
- Rakefile
|
173
|
+
- bin/console
|
174
|
+
- exe/.gitkeep
|
175
|
+
- lib/portable.rb
|
176
|
+
- lib/portable/column.rb
|
177
|
+
- lib/portable/export.rb
|
178
|
+
- lib/portable/transformer.rb
|
179
|
+
- lib/portable/version.rb
|
180
|
+
- lib/portable/writer.rb
|
181
|
+
- portable.gemspec
|
182
|
+
homepage: https://github.com/bluemarblepayroll/portable
|
183
|
+
licenses:
|
184
|
+
- MIT
|
185
|
+
metadata:
|
186
|
+
bug_tracker_uri: https://github.com/bluemarblepayroll/portable/issues
|
187
|
+
changelog_uri: https://github.com/bluemarblepayroll/portable/blob/master/CHANGELOG.md
|
188
|
+
documentation_uri: https://www.rubydoc.info/gems/portable
|
189
|
+
homepage_uri: https://github.com/bluemarblepayroll/portable
|
190
|
+
source_code_uri: https://github.com/bluemarblepayroll/portable
|
191
|
+
post_install_message:
|
192
|
+
rdoc_options: []
|
193
|
+
require_paths:
|
194
|
+
- lib
|
195
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - ">="
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: '2.5'
|
200
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
201
|
+
requirements:
|
202
|
+
- - ">"
|
203
|
+
- !ruby/object:Gem::Version
|
204
|
+
version: 1.3.1
|
205
|
+
requirements: []
|
206
|
+
rubygems_version: 3.0.3
|
207
|
+
signing_key:
|
208
|
+
specification_version: 4
|
209
|
+
summary: Transformable export writer
|
210
|
+
test_files: []
|