csv-importer 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -2
- data/README.md +18 -4
- data/lib/csv_importer/csv_reader.rb +3 -3
- data/lib/csv_importer/report.rb +2 -0
- data/lib/csv_importer/row.rb +6 -1
- data/lib/csv_importer/runner.rb +11 -3
- data/lib/csv_importer/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 07b837a8650d40afb4feb4be4b9d1679d4f7a41a
|
4
|
+
data.tar.gz: f74a63d0b1c65c647ca8ccd102151a2c542f1212
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b3453bf9dc18bc3dcd66b04b7901c5e68d9c66afa362d4e0ae9965dc82745a9380dd53e8d5fbdcc42cc7ab4b3501f3d1debfe2894e013b9fa08a7dc90012dcb
|
7
|
+
data.tar.gz: 633f1f1e78cb60a1dd911349ab5651d498acfb0a1ff8983f88e144a4d429de17a43d3e2bd43e12538a1a31c15edf327ccca290c908f727f06811253dc8aaf8d5
|
data/CHANGELOG.md
CHANGED
@@ -2,7 +2,31 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
|
5
|
-
##
|
5
|
+
## [0.3.0] - 2016-02-05
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
* Empty cells are now empty strings. You don't have to check for a nil
|
10
|
+
value when applying a transformation anymore.
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
# Prior to 0.3, an empty cell turns into `nil`
|
14
|
+
column :email, to: ->(email) { email.downcase unless email.nil? }
|
15
|
+
|
16
|
+
# From 0.3, an empty cell turns into `""`
|
17
|
+
column :email, to: ->(email) { email.downcase }
|
18
|
+
```
|
19
|
+
|
20
|
+
* You can now skip an import in the `after_build` callback:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
UserImport.new(file: csv_file) do
|
24
|
+
# Skip existing records
|
25
|
+
after_build do |user|
|
26
|
+
skip! if user.persisted?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
```
|
6
30
|
|
7
31
|
## [0.2.0] - 2015-07-24
|
8
32
|
|
@@ -41,7 +65,7 @@ UserImport.new(file: csv_file, quote_char: "'")
|
|
41
65
|
|
42
66
|
```ruby
|
43
67
|
UserImport.new(file: csv_file) do
|
44
|
-
after_build do
|
68
|
+
after_build do |user|
|
45
69
|
user.import_by_user = current_user
|
46
70
|
end
|
47
71
|
end
|
data/README.md
CHANGED
@@ -169,7 +169,7 @@ Now, email could also be spelled "e-mail", or "mail", or even "courriel"
|
|
169
169
|
Nice, emails should be downcased though, so let's do this.
|
170
170
|
|
171
171
|
```ruby
|
172
|
-
column :email, as: [/e.?mail/i, "courriel"], to: ->(email) { email.downcase
|
172
|
+
column :email, as: [/e.?mail/i, "courriel"], to: ->(email) { email.downcase }
|
173
173
|
```
|
174
174
|
|
175
175
|
If you need to do more advanced stuff, you've got access to the model:
|
@@ -209,7 +209,7 @@ class ImportUserCSV
|
|
209
209
|
|
210
210
|
model User
|
211
211
|
|
212
|
-
column :email, to: ->(email) { email.downcase
|
212
|
+
column :email, to: ->(email) { email.downcase }
|
213
213
|
|
214
214
|
identifier :email
|
215
215
|
end
|
@@ -236,7 +236,7 @@ class ImportUserCSV
|
|
236
236
|
|
237
237
|
model User
|
238
238
|
|
239
|
-
column :email, to: ->(email) { email.downcase
|
239
|
+
column :email, to: ->(email) { email.downcase }
|
240
240
|
|
241
241
|
on_error :abort
|
242
242
|
end
|
@@ -287,7 +287,7 @@ class ImportUserCSV
|
|
287
287
|
column :email
|
288
288
|
|
289
289
|
after_build do |user|
|
290
|
-
user.name = email.split('@').first
|
290
|
+
user.name = email.split('@').first
|
291
291
|
end
|
292
292
|
end
|
293
293
|
|
@@ -314,6 +314,20 @@ UserImport.new(file: my_file) do
|
|
314
314
|
end
|
315
315
|
```
|
316
316
|
|
317
|
+
### Skip import
|
318
|
+
|
319
|
+
You can skip the import of a model by calling `skip!` in an
|
320
|
+
`after_build` block:
|
321
|
+
|
322
|
+
```ruby
|
323
|
+
UserImport.new(file: csv_file) do
|
324
|
+
# Skip existing records
|
325
|
+
after_build do |user|
|
326
|
+
skip! if user.persisted?
|
327
|
+
end
|
328
|
+
end
|
329
|
+
```
|
330
|
+
|
317
331
|
|
318
332
|
### Validate the header
|
319
333
|
|
@@ -13,7 +13,7 @@ module CSVImporter
|
|
13
13
|
@csv_rows ||= begin
|
14
14
|
sane_content = sanitize_content(read_content)
|
15
15
|
separator = detect_separator(sane_content)
|
16
|
-
cells = CSV.parse(sane_content, col_sep: separator, quote_char: quote_char)
|
16
|
+
cells = CSV.parse(sane_content, col_sep: separator, quote_char: quote_char, skip_blanks: true)
|
17
17
|
sanitize_cells(cells)
|
18
18
|
end
|
19
19
|
end
|
@@ -54,11 +54,11 @@ module CSVImporter
|
|
54
54
|
SEPARATORS.sort_by { |separator| csv_content.count(separator) }.last
|
55
55
|
end
|
56
56
|
|
57
|
-
#
|
57
|
+
# Remove trailing white spaces and ensure we always return a string
|
58
58
|
def sanitize_cells(rows)
|
59
59
|
rows.map do |cells|
|
60
60
|
cells.map do |cell|
|
61
|
-
cell.strip
|
61
|
+
cell ? cell.strip : ""
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
data/lib/csv_importer/report.rb
CHANGED
@@ -21,6 +21,8 @@ module CSVImporter
|
|
21
21
|
attribute :updated_rows, Array[Row], default: proc { [] }
|
22
22
|
attribute :failed_to_create_rows, Array[Row], default: proc { [] }
|
23
23
|
attribute :failed_to_update_rows, Array[Row], default: proc { [] }
|
24
|
+
attribute :create_skipped_rows, Array[Row], default: proc { [] }
|
25
|
+
attribute :update_skipped_rows, Array[Row], default: proc { [] }
|
24
26
|
|
25
27
|
attribute :message_generator, Class, default: proc { ReportMessage }
|
26
28
|
|
data/lib/csv_importer/row.rb
CHANGED
@@ -11,6 +11,7 @@ module CSVImporter
|
|
11
11
|
attribute :model_klass
|
12
12
|
attribute :identifiers, Array[Symbol]
|
13
13
|
attribute :after_build_blocks, Array[Proc], default: []
|
14
|
+
attribute :skip, Boolean, default: false
|
14
15
|
|
15
16
|
# The model to be persisted
|
16
17
|
def model
|
@@ -42,7 +43,7 @@ module CSVImporter
|
|
42
43
|
set_attribute(model, column_definition, value)
|
43
44
|
end
|
44
45
|
|
45
|
-
after_build_blocks.each { |block|
|
46
|
+
after_build_blocks.each { |block| instance_exec(model, &block) }
|
46
47
|
|
47
48
|
model
|
48
49
|
end
|
@@ -99,5 +100,9 @@ module CSVImporter
|
|
99
100
|
def build_model
|
100
101
|
model_klass.new
|
101
102
|
end
|
103
|
+
|
104
|
+
def skip!
|
105
|
+
self.skip = true
|
106
|
+
end
|
102
107
|
end
|
103
108
|
end
|
data/lib/csv_importer/runner.rb
CHANGED
@@ -52,10 +52,14 @@ module CSVImporter
|
|
52
52
|
tags << :create
|
53
53
|
end
|
54
54
|
|
55
|
-
if row.
|
56
|
-
tags << :
|
55
|
+
if row.skip?
|
56
|
+
tags << :skip
|
57
57
|
else
|
58
|
-
|
58
|
+
if row.model.save
|
59
|
+
tags << :success
|
60
|
+
else
|
61
|
+
tags << :failure
|
62
|
+
end
|
59
63
|
end
|
60
64
|
|
61
65
|
add_to_report(row, tags)
|
@@ -74,6 +78,10 @@ module CSVImporter
|
|
74
78
|
report.updated_rows
|
75
79
|
when [ :update, :failure ]
|
76
80
|
report.failed_to_update_rows
|
81
|
+
when [ :create, :skip ]
|
82
|
+
report.create_skipped_rows
|
83
|
+
when [ :update, :skip ]
|
84
|
+
report.update_skipped_rows
|
77
85
|
else
|
78
86
|
raise "Invalid tags #{tags.inspect}"
|
79
87
|
end
|
data/lib/csv_importer/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csv-importer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Philippe Creux
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-02-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: virtus
|
@@ -105,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
105
|
version: '0'
|
106
106
|
requirements: []
|
107
107
|
rubyforge_project:
|
108
|
-
rubygems_version: 2.4.5
|
108
|
+
rubygems_version: 2.4.5.1
|
109
109
|
signing_key:
|
110
110
|
specification_version: 4
|
111
111
|
summary: CSV Import for humans
|