csv_blueprints 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5e8bed90e0ed20e6d0af5e2679335742d3b1be6b444efcb8922264ccf25224b1
4
+ data.tar.gz: a70c04fd366e675cb2292fe7bb9628160e33e0d970104d70460197dab72cff95
5
+ SHA512:
6
+ metadata.gz: d1789c1526bbac517fb7de815d41b9797a837389f1103f163d72abf719eb18d53f856d2347a13541d992b12517db30d08cc767dbcac69f027fa0fcb08a5b6ae2
7
+ data.tar.gz: a94f9fb2758f6cc5e36d860b82310e2e154b68a408e02262b47e068bf0631ea57993f3cf5e0f511d4a45ee079e9a57dff54bd3d941fdbba64ef1b90195c890f4
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ coverage
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
13
+
14
+ # Gems should not include the lock file -- dependency versions are handled by the gemspec
15
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,9 @@
1
+ ---
2
+ sudo: false
3
+ before_install: gem install bundler -v 1.17.3
4
+ cache: bundler
5
+
6
+ language: ruby
7
+ rvm:
8
+ - 2.4.5
9
+ - 2.5.3
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in csv_blueprints.gemspec
6
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Jason Schweier
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,87 @@
1
+ # CSV Blueprints
2
+
3
+ [![Build Status](https://travis-ci.com/jmks/csv_blueprints.svg?branch=master)](https://travis-ci.com/jmks/csv_blueprints)
4
+
5
+ A simple and small DSL to generate CSV files.
6
+
7
+ ## Usage
8
+
9
+ Declaratively specify a CSV blueprint:
10
+
11
+ ```ruby
12
+ require "csv_blueprints"
13
+ require "faker"
14
+
15
+ blueprint = CsvBlueprints.specify do
16
+ column "ID", value: :sequence
17
+ column "Name", value: -> i { Faker::Name.name }
18
+ columns "Login", "Email", value: -> i { "email#{i}@example.com" }
19
+ column "Type", static: "Client"
20
+ column "Notes", value: :blank
21
+ end
22
+ ```
23
+
24
+ > We're using the [faker](https://github.com/stympy/faker) gem here for realistic names
25
+
26
+ This one blueprint can generate multiple plans. E.g. differing numbers of rows or to override the row's values:
27
+
28
+ ```ruby
29
+ # three rows
30
+ plan = blueprint.plan.standard(3)
31
+ plan.write
32
+ ```
33
+
34
+ will generate a CSV like:
35
+
36
+ ```
37
+ ID,Name,Login,Email,Type,Notes
38
+ 1,Val Kulas DVM,email1@example.com,email1@example.com,Client,
39
+ 2,Marsha Sporer,email2@example.com,email2@example.com,Client,
40
+ 3,Mrs. Bennett Bechtelar,email3@example.com,email3@example.com,Client,
41
+ ```
42
+
43
+ Another plan from the same blueprint
44
+
45
+ ```ruby
46
+ # two rows with duplicate IDs and a note
47
+ plan_with_duplicate_ids = blueprint.plan.customized(2, "ID" => 999, "Notes" => "Imported on #{Date.today.strftime('%Y-%m-%d')}")
48
+ plan_with_duplicate_ids.write
49
+ ```
50
+
51
+ would generate
52
+
53
+ ```
54
+ ID,Name,Login,Email,Type,Notes
55
+ 999,Tiffanie Schaden,email1@example.com,email1@example.com,Client,Imported on 2019-03-04
56
+ 999,Mr. Arie Stroman,email2@example.com,email2@example.com,Client,Imported on 2019-03-04
57
+ ```
58
+
59
+ ## Installation
60
+
61
+ Add this line to your application's Gemfile:
62
+
63
+ ```ruby
64
+ gem "csv_blueprints"
65
+ ```
66
+
67
+ And then execute:
68
+
69
+ $ bundle
70
+
71
+ Or install it yourself as:
72
+
73
+ $ gem install csv_blueprints
74
+
75
+ ## Development
76
+
77
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
78
+
79
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then 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).
80
+
81
+ ## Contributing
82
+
83
+ Bug reports and pull requests are welcome on GitHub at https://github.com/jmks/csv_blueprints.
84
+
85
+ ## License
86
+
87
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "csv_blueprints"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+ IFS=$'\n\t'
5
+ set -vx
6
+
7
+ gem uninstall --all csv_blueprints
8
+ gem build csv_blueprints.gemspec
9
+ find . -name csv_blueprints*.gem -exec gem install {} \;
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,31 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "csv_blueprints/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "csv_blueprints"
8
+ spec.version = CsvBlueprints::VERSION
9
+ spec.authors = ["Jason Schweier"]
10
+ spec.email = ["jason.schweier@gmail.com"]
11
+
12
+ spec.summary = %q{A declarative way to generate CSVs}
13
+ spec.description = %q{Declaratively specify a CSV blueprint, then create customized plans for CSV generation.}
14
+ spec.homepage = "https://github.com/jmks/csv_blueprints"
15
+ spec.license = "MIT"
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.17"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rspec", "~> 3.0"
29
+ spec.add_development_dependency "pry", "~> 0.12.2"
30
+ spec.add_development_dependency "simplecov", "~> 0.16"
31
+ end
@@ -0,0 +1,14 @@
1
+ require "csv_blueprints/plan"
2
+ require "csv_blueprints/plan_writer"
3
+ require "csv_blueprints/plan_builder"
4
+ require "csv_blueprints/blueprint"
5
+
6
+ require "csv_blueprints/version"
7
+
8
+ module CsvBlueprints
9
+ def self.specify(&block)
10
+ Blueprint.new.tap do |blueprint|
11
+ blueprint.instance_eval(&block) if block_given?
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,84 @@
1
+ module CsvBlueprints
2
+ Column = Struct.new(:name, :value) do
3
+ def value_for(i)
4
+ if value.respond_to?(:call)
5
+ value.call(i)
6
+ else
7
+ value
8
+ end
9
+ end
10
+ end
11
+
12
+ class RepeatedValue
13
+ def initialize(callable, max_repetitions)
14
+ @callable = callable
15
+ @max_repetitions = max_repetitions
16
+ @repetitions = 0
17
+ @value = nil
18
+ end
19
+
20
+ def call(index)
21
+ calculate_value(index)
22
+ increment_repetitions
23
+ value
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :value
29
+
30
+ def calculate_value(index)
31
+ if @repetitions < @max_repetitions
32
+ @value ||= @callable.call(index)
33
+ else
34
+ @repetitions = 0
35
+ @value = @callable.call(index)
36
+ end
37
+ end
38
+
39
+ def increment_repetitions
40
+ @repetitions += 1
41
+ end
42
+ end
43
+
44
+ class Blueprint
45
+ def initialize
46
+ @columns = []
47
+ end
48
+
49
+ def column(name, value: nil)
50
+ @columns << column_for_value(name, value)
51
+ end
52
+
53
+ def columns(*names, value:)
54
+ wrapped_value = value.respond_to?(:call) ? RepeatedValue.new(value, names.length) : value
55
+
56
+ names.each { |name| column(name, value: wrapped_value) }
57
+ end
58
+
59
+ def plan
60
+ PlanBuilder.new(self)
61
+ end
62
+
63
+ def column_names
64
+ @columns.map(&:name)
65
+ end
66
+
67
+ def default_values(row)
68
+ Hash[@columns.map { |c| [c.name, c.value_for(row)] }]
69
+ end
70
+
71
+ private
72
+
73
+ def column_for_value(name, value)
74
+ case value
75
+ when :blank
76
+ Column.new(name, nil)
77
+ when :sequence
78
+ Column.new(name, -> i { i })
79
+ else
80
+ Column.new(name, value)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,50 @@
1
+ module CsvBlueprints
2
+ class Plan
3
+ class StandardRow
4
+ def values_for(index, blueprint)
5
+ blueprint.default_values(index)
6
+ end
7
+ end
8
+
9
+ class CustomizedRow < StandardRow
10
+ def initialize(overrides)
11
+ @overrides = overrides
12
+ end
13
+
14
+ def values_for(index, blueprint)
15
+ values = super
16
+
17
+ @overrides.each_pair do |column, value|
18
+ if values.key?(column)
19
+ values[column] = value
20
+ end
21
+ end
22
+
23
+ values
24
+ end
25
+ end
26
+
27
+ def initialize(blueprint)
28
+ @blueprint = blueprint
29
+ @rows = []
30
+ end
31
+
32
+ def add_row(overrides = {})
33
+ if overrides.any?
34
+ @rows << CustomizedRow.new(overrides)
35
+ else
36
+ @rows << StandardRow.new
37
+ end
38
+ end
39
+
40
+ def column_names
41
+ @blueprint.column_names
42
+ end
43
+
44
+ def each_row
45
+ @rows.each.with_index do |row, index|
46
+ yield row.values_for(index + 1, @blueprint)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,22 @@
1
+ module CsvBlueprints
2
+ class PlanBuilder
3
+ def initialize(blueprint)
4
+ @blueprint = blueprint
5
+ @plan = Plan.new(@blueprint)
6
+ end
7
+
8
+ def standard(number)
9
+ number.times { @plan.add_row }
10
+ self
11
+ end
12
+
13
+ def customized(number, overrides)
14
+ number.times { @plan.add_row(overrides) }
15
+ self
16
+ end
17
+
18
+ def write(out = STDOUT)
19
+ PlanWriter.new(@plan).write(out)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ require "csv"
2
+
3
+ module CsvBlueprints
4
+ class PlanWriter
5
+ def initialize(plan)
6
+ @plan = plan
7
+ end
8
+
9
+ def write(out)
10
+ csv = CSV.new(out, headers: @plan.column_names, write_headers: true)
11
+
12
+ @plan.each_row { |row| csv << row }
13
+
14
+ csv
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module CsvBlueprints
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: csv_blueprints
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jason Schweier
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-03-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.17'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.12.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.12.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.16'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.16'
83
+ description: Declaratively specify a CSV blueprint, then create customized plans for
84
+ CSV generation.
85
+ email:
86
+ - jason.schweier@gmail.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - bin/console
99
+ - bin/install_local
100
+ - bin/setup
101
+ - csv_blueprints.gemspec
102
+ - lib/csv_blueprints.rb
103
+ - lib/csv_blueprints/blueprint.rb
104
+ - lib/csv_blueprints/plan.rb
105
+ - lib/csv_blueprints/plan_builder.rb
106
+ - lib/csv_blueprints/plan_writer.rb
107
+ - lib/csv_blueprints/version.rb
108
+ homepage: https://github.com/jmks/csv_blueprints
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.7.6
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: A declarative way to generate CSVs
132
+ test_files: []