csv-importer 0.2.0 → 0.3.0
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 +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
|