dreader 0.1.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: be77a7a58ae4abcdcba7d3b734bc64f2cf756efd34bab78c30a4b0633fa6027a
4
+ data.tar.gz: d06cc4188e57c2e93297cece38b09b992cfeacad1f8cbbe6e645534965c45f4d
5
+ SHA512:
6
+ metadata.gz: b3cbaeb434fea0a8f3c7dafcf2a096fd28b18deef69e66360be27eeff4cd8b0b42ea0f080f3fab85f01f26c90f4ce35424668fac855d15f6f0be8c1f25a9bc9c
7
+ data.tar.gz: 4da7939fa5e05ae685ad21f21a120067f4e4ddb5370b8171a37a7c00407f69300b162f0779cb69816ce3f8141f606c992226bf1125428911f1b7cd5dcb8a6b8d
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
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 dreader.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Adolfo Villafiorita
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.
data/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # Dreader
2
+
3
+ A simple DSL built on top of `roo` to read and process tabular data (CSV,
4
+ LibreOffice, Excel).
5
+
6
+ Use this gem to specify the structure of some tabular data you want to
7
+ process. The input data can be in CSV, LibreOffice, and Excel. Each row can
8
+ then be passed to a block of code you define.
9
+
10
+ The gem can thus be used to check, process, import data. We use it to import data into
11
+ Rails application, but the gem can used in any Ruby application.
12
+
13
+ The gem should be relatively easy to use, despite its name: *dread* stands for
14
+ *d*ata *r*eader.
15
+
16
+ The gem depends on `roo`.
17
+
18
+ ## Installation
19
+
20
+ Add this line to your application's Gemfile:
21
+
22
+ ```ruby
23
+ gem 'dreader'
24
+ ```
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install dreader
33
+
34
+ ## Usage
35
+
36
+ ```
37
+ i = Dreader::Engine.new
38
+
39
+ i.options do
40
+ start_at 1
41
+ end
42
+
43
+ # first column is called name
44
+ # :name should be non nil and of length greater than 0
45
+ i.column :name do
46
+ check do |x|
47
+ x and x.length > 0
48
+ end
49
+ end
50
+
51
+ # second column is called surname
52
+ # :surname should be non nil and of length greater than 0
53
+ i.column :surname do
54
+ check do |x|
55
+ x and x.length > 0
56
+ end
57
+ end
58
+
59
+ # third column is called birthdate
60
+ # :name should be non nil and of length greater than 0
61
+ i.column :birthdate do
62
+ check do |x|
63
+ x.class == Date
64
+ end
65
+ end
66
+
67
+ # fourth column is called age
68
+ # we make it into an integer
69
+ # age should be greater than 0
70
+ i.column :age do
71
+ process do |r|
72
+ r.to_i
73
+ end
74
+
75
+ check do |r|
76
+ r > 0
77
+ end
78
+ end
79
+
80
+ # when we decide to process the file, for every row
81
+ # we print the value of the name and the value of the surname
82
+ i.mapping do |r|
83
+ puts "#{r[:name][:value]} #{r[:surname][:value]}"
84
+ end
85
+
86
+ i.read "/home/adolfo/Desktop/a.ods"
87
+ i.process
88
+ ```
89
+
90
+ ## Known Bugs and Limitations
91
+
92
+ No known bugs and an unknown number of unknown bugs.
93
+
94
+ (See the open issues for the known bugs.)
95
+
96
+
97
+ ## Development
98
+
99
+ After checking out the repo, run `bin/setup` to install dependencies. You can
100
+ also run `bin/console` for an interactive prompt that will allow you to
101
+ experiment.
102
+
103
+ To install this gem onto your local machine, run `bundle exec rake
104
+ install`. To release a new version, update the version number in `version.rb`,
105
+ and then run `bundle exec rake release`, which will create a git tag for the
106
+ version, push git commits and tags, and push the `.gem` file to
107
+ [rubygems.org](https://rubygems.org).
108
+
109
+ ## Contributing
110
+
111
+ Bug reports and pull requests are welcome on GitHub at
112
+ https://github.com/avillafiorita/dreader.
113
+
114
+ ## License
115
+
116
+ The gem is available as open source under the terms of the [MIT
117
+ License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "dreader"
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__)
data/bin/setup ADDED
@@ -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
data/dreader.gemspec ADDED
@@ -0,0 +1,36 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "dreader/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dreader"
8
+ spec.version = Dreader::VERSION
9
+ spec.authors = ["Adolfo Villafiorita"]
10
+ spec.email = ["adolfo.villafiorita@ict4g.net"]
11
+
12
+ spec.summary = %q{Process and import data from cvs and spreadsheets}
13
+ spec.description = %q{Use this gem to specify the structure of some tabular data
14
+ you want to process. The input data can be in CSV, LibreOffice, and Excel. Each row
15
+ can then be passed to a block of code you define.
16
+
17
+ The gem can thus be used to check, process, import data. We use it to import data into
18
+ Rails application, but the gem can used in any Ruby application.
19
+
20
+ The gem should be relatively easy to use, despite its name. (Dread
21
+ stands for *d*ata *r*eader)}
22
+ spec.homepage = "http://github.com/avillafiorita/dreader"
23
+ spec.license = "MIT"
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(test|spec|features)/})
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_development_dependency "bundler", "~> 1.16"
33
+ spec.add_development_dependency "rake", "~> 10.0"
34
+
35
+ spec.add_runtime_dependency "roo"
36
+ end
@@ -0,0 +1,3 @@
1
+ module Dreader
2
+ VERSION = "0.1.1"
3
+ end
data/lib/dreader.rb ADDED
@@ -0,0 +1,151 @@
1
+ require "dreader/version"
2
+
3
+ module Dreader
4
+ # service class to implement the column DSL language
5
+ class Column
6
+ def process &block
7
+ @process = block
8
+ end
9
+
10
+ def check &block
11
+ @check = block
12
+ end
13
+
14
+ def to_hash
15
+ {process: @process, check: @check }
16
+ end
17
+ end
18
+
19
+ # service class to implement the options DSL language
20
+ class Options
21
+ def initialize
22
+ @attributes = {}
23
+ end
24
+
25
+ def method_missing(name, *args, &block)
26
+ @attributes[name] = args[0]
27
+ end
28
+
29
+ def to_hash
30
+ @attributes
31
+ end
32
+ end
33
+
34
+ #
35
+ # This is where the real stuff begins
36
+ #
37
+ class Engine
38
+
39
+ # readable for debugging purposes
40
+ # the options we passed
41
+ attr_reader :options
42
+ # the specification of the columns to process
43
+ attr_reader :colspec
44
+ # the data we read
45
+ attr_reader :array
46
+
47
+ def initialize
48
+ @options = {}
49
+ @colspec = []
50
+ end
51
+
52
+ # define a DSL for options
53
+ # any string is processed as an option and it ends up in the
54
+ # @options hash
55
+ def options &block
56
+ options = Options.new
57
+ options.instance_eval(&block)
58
+
59
+ @options = options.to_hash
60
+ end
61
+
62
+ # define a DSL for column specification
63
+ # - `name` is the name of the column
64
+ # - `block` contains two declarations, `process` and `check`, which are
65
+ # used, respectively, to make a cell into the desired data and to check
66
+ # whether the desired data is ok
67
+ def column name, &block
68
+ column = Column.new
69
+ column.instance_eval(&block)
70
+
71
+ @colspec << column.to_hash.merge({name: name})
72
+ end
73
+
74
+ # define what we do with each line we read
75
+ # - `block` is the code which takes as input a `row` and processes
76
+ # `row` is a hash in which each spreadsheet cell is accessible under
77
+ # the column names. Each cell has the following values:
78
+ # :value, :error, :row_number, :col_number
79
+ def mapping &block
80
+ @mapping = block
81
+ end
82
+
83
+ # read a file and store it internally
84
+ # return the data we read in the form of an array of hashes
85
+ def read filename=nil
86
+ spreadsheet = self.open_spreadsheet filename || @options[:filename]
87
+ sheet = spreadsheet.sheet(@options[:sheet] || 0)
88
+
89
+ @array = Array.new
90
+ @errors = Array.new
91
+ first_row = @options[:start_at] || 1
92
+ (first_row..spreadsheet.last_row).each do |row_number|
93
+ row = spreadsheet.row(row_number)
94
+
95
+ r = Hash.new
96
+ @colspec.each_with_index do |colspec, index|
97
+ colname = colspec[:name]
98
+
99
+ r[colname] = Hash.new
100
+
101
+ r[colname][:row_number] = row_number
102
+ r[colname][:col_number] = index + 1
103
+
104
+ r[colname][:value] = value = colspec[:process] ? colspec[:process].call(row[index]) : row[index]
105
+
106
+ if colspec[:check] and not colspec[:check].call(value) then
107
+ r[colname][:error] = true
108
+ @errors << "Error: value \"#{row[index]}\" for #{colname} at row #{row_number} (col #{index + 1}) is incorrect"
109
+ else
110
+ r[colname][:error] = false
111
+ end
112
+ end
113
+
114
+ @array << r
115
+ end
116
+
117
+ @array
118
+ end
119
+
120
+ # return an array of strings with all the errors we have encounterd
121
+ # an empty array is a good news
122
+ def errors
123
+ @errors
124
+ end
125
+
126
+ # apply the mapping code to the array
127
+ # it makes sense to invoke it only
128
+ def process
129
+ @array.each do |r|
130
+ @mapping.call(r)
131
+ end
132
+ end
133
+
134
+ def to_s
135
+ @array.to_s
136
+ end
137
+
138
+ private
139
+
140
+ def self.open_spreadsheet(filename)
141
+ case File.extname(filename)
142
+ when ".csv" then Csv.new(filename)
143
+ when ".ods" then Roo::OpenOffice.new(filename)
144
+ when ".xls" then Roo::Excel.new(filename)
145
+ when ".xlsx" then Roo::Excelx.new(filename)
146
+ else raise "Unknown file type: #{filename}"
147
+ end
148
+ end
149
+ end
150
+
151
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dreader
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Adolfo Villafiorita
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-03-22 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.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
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: roo
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: |-
56
+ Use this gem to specify the structure of some tabular data
57
+ you want to process. The input data can be in CSV, LibreOffice, and Excel. Each row
58
+ can then be passed to a block of code you define.
59
+
60
+ The gem can thus be used to check, process, import data. We use it to import data into
61
+ Rails application, but the gem can used in any Ruby application.
62
+
63
+ The gem should be relatively easy to use, despite its name. (Dread
64
+ stands for *d*ata *r*eader)
65
+ email:
66
+ - adolfo.villafiorita@ict4g.net
67
+ executables: []
68
+ extensions: []
69
+ extra_rdoc_files: []
70
+ files:
71
+ - ".gitignore"
72
+ - Gemfile
73
+ - LICENSE.txt
74
+ - README.md
75
+ - Rakefile
76
+ - bin/console
77
+ - bin/setup
78
+ - dreader.gemspec
79
+ - lib/dreader.rb
80
+ - lib/dreader/version.rb
81
+ homepage: http://github.com/avillafiorita/dreader
82
+ licenses:
83
+ - MIT
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.7.3
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Process and import data from cvs and spreadsheets
105
+ test_files: []