parceira 0.0.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.
- data/.gitignore +23 -0
- data/Gemfile +4 -0
- data/Guardfile +9 -0
- data/LICENSE +22 -0
- data/README.md +70 -0
- data/Rakefile +11 -0
- data/example/contacts-us-ascii.csv +4 -0
- data/example/products.csv +5 -0
- data/lib/parceira/reader.rb +179 -0
- data/lib/parceira/version.rb +4 -0
- data/lib/parceira.rb +20 -0
- data/parceira.gemspec +23 -0
- data/spec/parceira/reader_spec.rb +291 -0
- data/spec/parceira/version_spec.rb +5 -0
- data/spec/spec_helper.rb +6 -0
- metadata +128 -0
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
.DS_Store
|
2
|
+
.*.swp
|
3
|
+
*.orig
|
4
|
+
*.cp
|
5
|
+
*~
|
6
|
+
*.gem
|
7
|
+
*.rbc
|
8
|
+
.bundle
|
9
|
+
.config
|
10
|
+
.yardoc
|
11
|
+
.rvmrc
|
12
|
+
Gemfile.lock
|
13
|
+
InstalledFiles
|
14
|
+
_yardoc
|
15
|
+
coverage
|
16
|
+
doc/
|
17
|
+
lib/bundler/man
|
18
|
+
pkg
|
19
|
+
rdoc
|
20
|
+
spec/reports
|
21
|
+
test/tmp
|
22
|
+
test/version_tmp
|
23
|
+
tmp
|
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', :cli => '--color' do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/parceira/(.+)\.rb$}) { |m| "spec/parceira/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
end
|
9
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Marcos G. Zimmermann
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
parceira
|
2
|
+
========
|
3
|
+
|
4
|
+
Importing of CSV Files as Array(s) of Hashes with featured to process large csv files and better support for file encoding.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'parceira'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install parceira
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
```bash
|
23
|
+
$ cat example/products.csv
|
24
|
+
Product ID,Name,Price
|
25
|
+
1,Macbook Air,999
|
26
|
+
2,Ipad mini,329.99
|
27
|
+
3,Iphone 5,199.00
|
28
|
+
4,MacBook Pro,
|
29
|
+
```
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
> require 'parceira'
|
33
|
+
> filename = File.expand_path('./../example/products.csv', __FILE__)
|
34
|
+
> Parceira.process(filename)
|
35
|
+
=> [{:product_id=>1, :name=>"Macbook Air", :price=>999}, {:product_id=>2, :name=>"Ipad mini", :price=>329.99}, {:product_id=>3, :name=>"Iphone 5", :price=>199.0}, {:product_id=>4, :name=>"MacBook Pro", :price=>nil}]
|
36
|
+
|
37
|
+
> Parceira.process(filename, key_mapping: {name: :description})
|
38
|
+
=> [{:product_id=>1, :description=>"Macbook Air", :price=>999}, {:product_id=>2, :description=>"Ipad mini", :price=>329.99}, {:product_id=>3, :description=>"Iphone 5", :price=>199.0}, {:product_id=>4, :description=>"MacBook Pro", :price=>nil}]
|
39
|
+
|
40
|
+
> Parceira.process(filename, reject_nil: true)
|
41
|
+
=> [{:product_id=>1, :name=>"Macbook Air", :price=>999}, {:product_id=>2, :name=>"Ipad mini", :price=>329.99}, {:product_id=>3, :name=>"Iphone 5", :price=>199.0}, {:product_id=>4, :name=>"MacBook Pro"}]
|
42
|
+
|
43
|
+
> Parceira.process(filename, reject_matching: /^Macbook/i)
|
44
|
+
=> [{:product_id=>1, :name=>nil, :price=>999}, {:product_id=>2, :name=>"Ipad mini", :price=>329.99}, {:product_id=>3, :name=>"Iphone 5", :price=>199.0}, {:product_id=>4, :name=>nil, :price=>nil}]
|
45
|
+
|
46
|
+
> Parceira.process(filename, file_encoding: 'utf-8')
|
47
|
+
=> [{:product_id=>1, :name=>"Macbook Air", :price=>999}, {:product_id=>2, :name=>"Ipad mini", :price=>329.99}, {:product_id=>3, :name=>"Iphone 5", :price=>199.0}, {:product_id=>4, :name=>"MacBook Pro", :price=>nil}]
|
48
|
+
|
49
|
+
> Parceira.process(filename, headers: false)
|
50
|
+
=> [[1, "Macbook Air", 999], [2, "Ipad mini", 329.99], [3, "Iphone 5", 199.0], [4, "MacBook Pro", nil]]
|
51
|
+
|
52
|
+
> Parceira.process(filename, headers: false, headers_included: false)
|
53
|
+
=> [["Product ID", "Name", "Price"], [1, "Macbook Air", 999], [2, "Ipad mini", 329.99], [3, "Iphone 5", 199.0], [4, "MacBook Pro", nil]]
|
54
|
+
|
55
|
+
> Parceira.process(filename, headers: %w(ID Name Value))
|
56
|
+
=> [{"ID"=>1, "Name"=>"Macbook Air", "Value"=>999}, {"ID"=>2, "Name"=>"Ipad mini", "Value"=>329.99}, {"ID"=>3, "Name"=>"Iphone 5", "Value"=>199.0}, {"ID"=>4, "Name"=>"MacBook Pro", "Value"=>nil}]
|
57
|
+
```
|
58
|
+
|
59
|
+
|
60
|
+
## Reporting Bugs / Feature Requests
|
61
|
+
Please [open an Issue on GitHub](https://github.com/marcosgz/parceira/issues) if you have feedback, new feature requests, or want to report a bug. Thank you!
|
62
|
+
|
63
|
+
|
64
|
+
## Contributing
|
65
|
+
|
66
|
+
1. Fork it
|
67
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
68
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
69
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
70
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module Parceira
|
3
|
+
class Reader
|
4
|
+
DEFAULT_OPTIONS = {
|
5
|
+
# CSV options
|
6
|
+
col_sep: ',',
|
7
|
+
row_sep: $/,
|
8
|
+
quote_char: '"',
|
9
|
+
# Header
|
10
|
+
headers: true,
|
11
|
+
headers_included: true,
|
12
|
+
key_mapping: nil,
|
13
|
+
file_encoding: nil,
|
14
|
+
# Values
|
15
|
+
reject_blank: true,
|
16
|
+
reject_nil: false,
|
17
|
+
reject_zero: false,
|
18
|
+
reject_matching: nil,
|
19
|
+
convert_to_numeric: true,
|
20
|
+
}
|
21
|
+
attr_reader :options
|
22
|
+
|
23
|
+
|
24
|
+
def initialize(input, options, &block)
|
25
|
+
@input = input
|
26
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def process!
|
31
|
+
if input_file.nil? && @input.is_a?(String)
|
32
|
+
data = CSV.parse(@input, csv_options) # content is already in memory. Process with CSV
|
33
|
+
header_data = data.shift if options[:headers_included] # Remove header row
|
34
|
+
header_keys = \
|
35
|
+
if options[:headers] == true
|
36
|
+
self.parse_header( header_data )
|
37
|
+
elsif options[:headers].is_a?(Array)
|
38
|
+
options[:headers]
|
39
|
+
end
|
40
|
+
data.map do |arr|
|
41
|
+
values = parse_values(arr)
|
42
|
+
if header_keys
|
43
|
+
convert_to_hash(header_keys, values)
|
44
|
+
else
|
45
|
+
values
|
46
|
+
end
|
47
|
+
end
|
48
|
+
elsif input_file.is_a?(File)
|
49
|
+
output = []
|
50
|
+
begin
|
51
|
+
$/ = options[:row_sep]
|
52
|
+
# Build header
|
53
|
+
header_data = input_file.readline.to_s.chomp(options[:row_sep]) if options[:headers_included] # Remove header row
|
54
|
+
header_keys = \
|
55
|
+
if options[:headers] == true
|
56
|
+
data = CSV.parse(header_data, self.csv_options)
|
57
|
+
self.parse_header( data )
|
58
|
+
elsif options[:headers].is_a?(Array)
|
59
|
+
options[:headers]
|
60
|
+
end
|
61
|
+
|
62
|
+
# now on to processing all the rest of the lines in the CSV file:
|
63
|
+
while !input_file.eof? # we can't use f.readlines() here, because this would read the whole file into memory at once, and eof => true
|
64
|
+
values = parse_values( CSV.parse(input_file.readline.chomp, csv_options) )
|
65
|
+
if header_keys
|
66
|
+
output << convert_to_hash(header_keys, values)
|
67
|
+
else
|
68
|
+
output << values
|
69
|
+
end
|
70
|
+
end
|
71
|
+
ensure
|
72
|
+
$/ = $/
|
73
|
+
end
|
74
|
+
output
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
def convert_to_hash(header, values)
|
80
|
+
header.each_with_index.inject({}) do |r, (key, index)|
|
81
|
+
value = values[index]
|
82
|
+
if options[:reject_nil] && value.nil?
|
83
|
+
else
|
84
|
+
r[key] = value
|
85
|
+
end
|
86
|
+
r
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def parse_values(arr)
|
91
|
+
arr.flatten.map do |v|
|
92
|
+
value = \
|
93
|
+
if options[:convert_to_numeric]
|
94
|
+
case v
|
95
|
+
when /^[+-]?\d+\.\d+$/
|
96
|
+
v.to_f
|
97
|
+
when /^[+-]?\d+$/
|
98
|
+
v.to_i
|
99
|
+
else
|
100
|
+
v.to_s.strip
|
101
|
+
end
|
102
|
+
else
|
103
|
+
v.to_s.strip
|
104
|
+
end
|
105
|
+
value = nil if options[:reject_blank] && value.blank?
|
106
|
+
value = nil if options[:reject_zero] && value.respond_to?(:zero?) && value.zero?
|
107
|
+
value = nil if options[:reject_matching] && value =~ options[:reject_matching]
|
108
|
+
value
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def parse_header(arr)
|
113
|
+
arr.flatten.each_with_index.inject([]) do |arr, (value, index)|
|
114
|
+
v = \
|
115
|
+
if (str=value.to_s.parameterize('_')).present?
|
116
|
+
str.to_sym
|
117
|
+
else
|
118
|
+
"field_#{index.next}".to_sym
|
119
|
+
end
|
120
|
+
v = options[:key_mapping][v] if options[:key_mapping].is_a?(Hash) && options[:key_mapping].has_key?(v)
|
121
|
+
arr.push(v)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def input_file
|
126
|
+
@input_file ||= \
|
127
|
+
case @input
|
128
|
+
when File
|
129
|
+
@input
|
130
|
+
when String
|
131
|
+
if File.exists?(@input)
|
132
|
+
File.open(@input, "r:#{self.charset}")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
def charset
|
139
|
+
options[:file_encoding] || begin
|
140
|
+
filename = \
|
141
|
+
case @input
|
142
|
+
when String
|
143
|
+
@input if File.exists?(@input)
|
144
|
+
when File
|
145
|
+
@input.path
|
146
|
+
end
|
147
|
+
if filename
|
148
|
+
IO.popen(['file', '--brief', '--mime', filename]).read.chomp.match(/charset=([^\s]+)/) { $1 }
|
149
|
+
else
|
150
|
+
default_charset
|
151
|
+
end
|
152
|
+
rescue
|
153
|
+
default_charset
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
def csv_options
|
159
|
+
options.select do |k,v|
|
160
|
+
[
|
161
|
+
:col_sep,
|
162
|
+
:row_sep,
|
163
|
+
:quote_char,
|
164
|
+
:field_size_limit,
|
165
|
+
:converters,
|
166
|
+
:unconverted_fields,
|
167
|
+
:skip_blanks,
|
168
|
+
:force_quotes
|
169
|
+
].include?(k)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
def default_charset
|
175
|
+
'utf-8'
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
end
|
data/lib/parceira.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'csv'
|
5
|
+
require 'i18n'
|
6
|
+
require 'active_support/lazy_load_hooks'
|
7
|
+
require 'active_support/i18n'
|
8
|
+
require 'active_support/inflector'
|
9
|
+
require 'active_support/core_ext/string'
|
10
|
+
|
11
|
+
require "parceira/version"
|
12
|
+
require "parceira/reader"
|
13
|
+
|
14
|
+
include ActiveSupport::Inflector
|
15
|
+
|
16
|
+
module Parceira
|
17
|
+
def self.process(input, options={}, &block)
|
18
|
+
Parceira::Reader.new(input, options.symbolize_keys, &block).process!
|
19
|
+
end
|
20
|
+
end
|
data/parceira.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/parceira/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Marcos G. Zimmermann"]
|
6
|
+
gem.email = ["mgzmaster@gmail.com"]
|
7
|
+
gem.description = %q{Importing of CSV Files as Array(s) of Hashes with featured to process large csv files and better support for file encoding.}
|
8
|
+
gem.summary = %q{Importing of CSV Files as Array(s) of Hashes}
|
9
|
+
gem.homepage = "http://github.com/marcosgz/parceira"
|
10
|
+
|
11
|
+
gem.add_development_dependency "rspec"
|
12
|
+
gem.add_development_dependency "guard-rspec"
|
13
|
+
|
14
|
+
gem.add_dependency "i18n"
|
15
|
+
gem.add_dependency "active_support"
|
16
|
+
|
17
|
+
gem.files = `git ls-files`.split($\)
|
18
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
19
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
|
+
gem.name = "parceira"
|
21
|
+
gem.require_paths = ["lib"]
|
22
|
+
gem.version = Parceira::VERSION
|
23
|
+
end
|
@@ -0,0 +1,291 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Parceira::Reader do
|
4
|
+
|
5
|
+
describe :process! do
|
6
|
+
describe "using default headers" do
|
7
|
+
let(:path) { File.expand_path('./../../../example/contacts-us-ascii.csv', __FILE__) }
|
8
|
+
let(:expected) {
|
9
|
+
[
|
10
|
+
{:first_name=>"Marcos", :last_name=>"Zimmermann"},
|
11
|
+
{:first_name=>"Paul", :last_name=>"Molive"},
|
12
|
+
{:first_name=>"Maya", :last_name=>"Didas"}
|
13
|
+
]
|
14
|
+
}
|
15
|
+
|
16
|
+
context "from string" do
|
17
|
+
subject { Parceira::Reader.new(File.read(path), {}).process! }
|
18
|
+
it { should eq(expected)}
|
19
|
+
end
|
20
|
+
|
21
|
+
context "from file" do
|
22
|
+
subject { Parceira::Reader.new(path, {}).process! }
|
23
|
+
it { should eq(expected)}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "disable headers" do
|
28
|
+
let(:path) { File.expand_path('./../../../example/contacts-us-ascii.csv', __FILE__) }
|
29
|
+
let(:options) { {headers: false} }
|
30
|
+
let(:expected) {
|
31
|
+
[
|
32
|
+
["Marcos", "Zimmermann"],
|
33
|
+
["Paul", "Molive"],
|
34
|
+
["Maya", "Didas"]
|
35
|
+
]
|
36
|
+
}
|
37
|
+
|
38
|
+
context "from string" do
|
39
|
+
subject { Parceira::Reader.new(File.read(path), options).process! }
|
40
|
+
it { should eq(expected)}
|
41
|
+
end
|
42
|
+
|
43
|
+
context "from file" do
|
44
|
+
subject { Parceira::Reader.new(path, options).process! }
|
45
|
+
it { should eq(expected)}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "overwriting headers" do
|
50
|
+
let(:path) { File.expand_path('./../../../example/contacts-us-ascii.csv', __FILE__) }
|
51
|
+
let(:options) { {headers: ['First Name', 'Middle Name']} }
|
52
|
+
let(:expected) {
|
53
|
+
[
|
54
|
+
{'First Name'=>"Marcos", 'Middle Name'=>"Zimmermann"},
|
55
|
+
{'First Name'=>"Paul", 'Middle Name'=>"Molive"},
|
56
|
+
{'First Name'=>"Maya", 'Middle Name'=>"Didas"}
|
57
|
+
]
|
58
|
+
}
|
59
|
+
|
60
|
+
context "from string" do
|
61
|
+
subject { Parceira::Reader.new(File.read(path), options).process! }
|
62
|
+
it { should eq(expected)}
|
63
|
+
end
|
64
|
+
|
65
|
+
context "from file" do
|
66
|
+
subject { Parceira::Reader.new(path, options).process! }
|
67
|
+
it { should eq(expected)}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "include first row(Header)" do
|
72
|
+
let(:path) { File.expand_path('./../../../example/contacts-us-ascii.csv', __FILE__) }
|
73
|
+
let(:options) { {headers_included: false, headers: false} }
|
74
|
+
let(:expected) {
|
75
|
+
[
|
76
|
+
["First Name", "Last Name"],
|
77
|
+
["Marcos", "Zimmermann"],
|
78
|
+
["Paul", "Molive"],
|
79
|
+
["Maya", "Didas"]
|
80
|
+
]
|
81
|
+
}
|
82
|
+
|
83
|
+
context "from string" do
|
84
|
+
subject { Parceira::Reader.new(File.read(path), options).process! }
|
85
|
+
it { should eq(expected)}
|
86
|
+
end
|
87
|
+
|
88
|
+
context "from file" do
|
89
|
+
subject { Parceira::Reader.new(path, options).process! }
|
90
|
+
it { should eq(expected)}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
describe :convert_to_hash do
|
97
|
+
let(:header) { [:foo, :bar] }
|
98
|
+
context "reject nil values" do
|
99
|
+
let(:values) { ["Foo", nil] }
|
100
|
+
subject { Parceira::Reader.new('', {reject_nil: true}).send(:convert_to_hash, header, values) }
|
101
|
+
it { should eq({foo:"Foo"})}
|
102
|
+
end
|
103
|
+
|
104
|
+
context "allow nil values" do
|
105
|
+
let(:values) { ["Foo", nil] }
|
106
|
+
subject { Parceira::Reader.new('', {reject_nil: false}).send(:convert_to_hash, header, values) }
|
107
|
+
it { should eq({foo:"Foo",bar:nil})}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
describe :parse_values do
|
113
|
+
it "should strip values" do
|
114
|
+
expect(Parceira::Reader.new('', {reject_blank: false}).send(:parse_values, ['Foo ', nil, ' Bar', ' ', 'Age'])).to eq(["Foo", "", "Bar", "", "Age"])
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "convert_to_numeric true" do
|
118
|
+
subject { Parceira::Reader.new('', {convert_to_numeric: true}).send(:parse_values, values) }
|
119
|
+
context "Fixnum" do
|
120
|
+
let(:values) { ['Foo', '1', 'Bar'] }
|
121
|
+
it { should eq(["Foo", 1, "Bar"])}
|
122
|
+
end
|
123
|
+
|
124
|
+
context "Negative Fixnum" do
|
125
|
+
let(:values) { ['Foo', '-1', 'Bar'] }
|
126
|
+
it { should eq(["Foo", -1, "Bar"])}
|
127
|
+
end
|
128
|
+
|
129
|
+
context "Positive Fixnum" do
|
130
|
+
let(:values) { ['Foo', '+1', 'Bar'] }
|
131
|
+
it { should eq(["Foo", 1, "Bar"])}
|
132
|
+
end
|
133
|
+
|
134
|
+
context "Float" do
|
135
|
+
let(:values) { ['Foo', '1.23', 'Bar'] }
|
136
|
+
it { should eq(["Foo", 1.23, "Bar"])}
|
137
|
+
end
|
138
|
+
|
139
|
+
context "Negative Float" do
|
140
|
+
let(:values) { ['Foo', '-1.23', 'Bar'] }
|
141
|
+
it { should eq(["Foo", -1.23, "Bar"])}
|
142
|
+
end
|
143
|
+
|
144
|
+
context "Positive Float" do
|
145
|
+
let(:values) { ['Foo', '+1.23', 'Bar'] }
|
146
|
+
it { should eq(["Foo", 1.23, "Bar"])}
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "reject_blank" do
|
151
|
+
context "true" do
|
152
|
+
subject { Parceira::Reader.new('', {reject_blank: true}).send(:parse_values, ['Foo', '', 'Bar']) }
|
153
|
+
it { should eq(["Foo", nil, "Bar"])}
|
154
|
+
end
|
155
|
+
|
156
|
+
context "false" do
|
157
|
+
subject { Parceira::Reader.new('', {reject_blank: false}).send(:parse_values, ['Foo', '', 'Bar']) }
|
158
|
+
it { should eq(["Foo", '', "Bar"])}
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "reject_zero" do
|
163
|
+
context "true" do
|
164
|
+
subject { Parceira::Reader.new('', {reject_zero: true}).send(:parse_values, ['Foo', '0', 'Bar', '0.0']) }
|
165
|
+
it { should eq(["Foo", nil, "Bar", nil])}
|
166
|
+
end
|
167
|
+
context "false" do
|
168
|
+
subject { Parceira::Reader.new('', {reject_zero: false}).send(:parse_values, ['Foo', '0', 'Bar', '0.0']) }
|
169
|
+
it { should eq(["Foo", 0, "Bar", 0.0])}
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "reject_matching" do
|
174
|
+
context "match with /^B/" do
|
175
|
+
subject { Parceira::Reader.new('', {reject_matching: /^B/}).send(:parse_values, ['Foo', 'Bar']) }
|
176
|
+
it { should eq(["Foo", nil])}
|
177
|
+
end
|
178
|
+
context "nil" do
|
179
|
+
subject { Parceira::Reader.new('', {reject_matching: nil}).send(:parse_values, ['Foo', 'Bar']) }
|
180
|
+
it { should eq(["Foo", "Bar"])}
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe :parse_header do
|
186
|
+
subject { Parceira::Reader.new('', {}).send(:parse_header, values) }
|
187
|
+
context "with whitespace character" do
|
188
|
+
let(:values) { ['First Name', 'Last Name', 'Age']}
|
189
|
+
it { should eq([:first_name, :last_name, :age])}
|
190
|
+
end
|
191
|
+
|
192
|
+
context "one missing key" do
|
193
|
+
let(:values) { ['First Name', nil, 'Age']}
|
194
|
+
it { should eq([:first_name, :field_2, :age])}
|
195
|
+
end
|
196
|
+
|
197
|
+
context "missing values" do
|
198
|
+
let(:values) { ['', nil, '']}
|
199
|
+
it { should eq([:field_1, :field_2, :field_3])}
|
200
|
+
end
|
201
|
+
|
202
|
+
context "key_mapping" do
|
203
|
+
let(:values) { ['First Name', 'Last Name']}
|
204
|
+
it "overwrite header attributes" do
|
205
|
+
Parceira::Reader.new('', {key_mapping:{first_name: :first}}).send(:parse_header, values).should eq([:first, :last_name])
|
206
|
+
Parceira::Reader.new('', {key_mapping:{last_name: :last}}).send(:parse_header, values).should eq([:first_name, :last])
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
describe :process! do
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
describe :input_file do
|
216
|
+
let(:path) { File.expand_path('./../../../example/contacts-us-ascii.csv', __FILE__) }
|
217
|
+
it { expect(File.exists?(path)).to be_true }
|
218
|
+
|
219
|
+
context "intance of File" do
|
220
|
+
let(:file) { File.open(path) }
|
221
|
+
subject { Parceira::Reader.new(file, {}).send(:input_file) }
|
222
|
+
it { should eq(file)}
|
223
|
+
end
|
224
|
+
|
225
|
+
context "filename" do
|
226
|
+
let(:file) { double('File') }
|
227
|
+
before(:each) do
|
228
|
+
File.should_receive(:open).with(path, 'r:us-ascii').and_return(file)
|
229
|
+
end
|
230
|
+
subject { Parceira::Reader.new(path, {}).send(:input_file) }
|
231
|
+
it { should eq(file)}
|
232
|
+
end
|
233
|
+
|
234
|
+
context "csv string" do
|
235
|
+
subject { Parceira::Reader.new('foo,bar', {}).send(:input_file) }
|
236
|
+
it { should be_nil}
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
|
241
|
+
describe :charset do
|
242
|
+
let(:path) { File.expand_path('./../../../example/contacts-us-ascii.csv', __FILE__) }
|
243
|
+
it { expect(File.exists?(path)).to be_true }
|
244
|
+
|
245
|
+
context ":file_encoding config" do
|
246
|
+
subject { Parceira::Reader.new(path, {file_encoding: 'iso-8859-1'}).send(:charset) }
|
247
|
+
it { should eq('iso-8859-1')}
|
248
|
+
end
|
249
|
+
|
250
|
+
context "instance of File" do
|
251
|
+
subject { Parceira::Reader.new(File.open(path), {}).send(:charset) }
|
252
|
+
it { should eq('us-ascii')}
|
253
|
+
end
|
254
|
+
|
255
|
+
context "filename" do
|
256
|
+
subject { Parceira::Reader.new(path, {}).send(:charset) }
|
257
|
+
it { should eq('us-ascii')}
|
258
|
+
end
|
259
|
+
|
260
|
+
context "csv string" do
|
261
|
+
subject { Parceira::Reader.new("name,age\nFoo Bar,25", {}).send(:charset) }
|
262
|
+
it "returns default_charset value" do
|
263
|
+
should eq('utf-8')
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
describe :csv_options do
|
270
|
+
subject { Parceira::Reader.new('', {}).send(:csv_options) }
|
271
|
+
it "includes only options allowed on CSV.parse method" do
|
272
|
+
should have_key(:col_sep)
|
273
|
+
should have_key(:row_sep)
|
274
|
+
should have_key(:quote_char)
|
275
|
+
should_not have_key(:headers)
|
276
|
+
should_not have_key(:reject_blank)
|
277
|
+
should_not have_key(:reject_nil)
|
278
|
+
should_not have_key(:reject_matching)
|
279
|
+
should_not have_key(:convert_to_numeric)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
|
284
|
+
describe :default_charset do
|
285
|
+
subject { Parceira::Reader.new('/tmp/path', {}).send(:default_charset) }
|
286
|
+
it { should eq('utf-8')}
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
it { expect(Parceira::Reader).to be_const_defined('DEFAULT_OPTIONS') }
|
291
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: parceira
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Marcos G. Zimmermann
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-07-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: guard-rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: i18n
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: active_support
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: Importing of CSV Files as Array(s) of Hashes with featured to process
|
79
|
+
large csv files and better support for file encoding.
|
80
|
+
email:
|
81
|
+
- mgzmaster@gmail.com
|
82
|
+
executables: []
|
83
|
+
extensions: []
|
84
|
+
extra_rdoc_files: []
|
85
|
+
files:
|
86
|
+
- .gitignore
|
87
|
+
- Gemfile
|
88
|
+
- Guardfile
|
89
|
+
- LICENSE
|
90
|
+
- README.md
|
91
|
+
- Rakefile
|
92
|
+
- example/contacts-us-ascii.csv
|
93
|
+
- example/products.csv
|
94
|
+
- lib/parceira.rb
|
95
|
+
- lib/parceira/reader.rb
|
96
|
+
- lib/parceira/version.rb
|
97
|
+
- parceira.gemspec
|
98
|
+
- spec/parceira/reader_spec.rb
|
99
|
+
- spec/parceira/version_spec.rb
|
100
|
+
- spec/spec_helper.rb
|
101
|
+
homepage: http://github.com/marcosgz/parceira
|
102
|
+
licenses: []
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ! '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
requirements: []
|
120
|
+
rubyforge_project:
|
121
|
+
rubygems_version: 1.8.23
|
122
|
+
signing_key:
|
123
|
+
specification_version: 3
|
124
|
+
summary: Importing of CSV Files as Array(s) of Hashes
|
125
|
+
test_files:
|
126
|
+
- spec/parceira/reader_spec.rb
|
127
|
+
- spec/parceira/version_spec.rb
|
128
|
+
- spec/spec_helper.rb
|