smarter_csv 1.16.1 → 1.16.3
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 +30 -1
- data/CONTRIBUTORS.md +2 -1
- data/README.md +1 -1
- data/docs/basic_write_api.md +48 -0
- data/docs/options.md +2 -1
- data/docs/releases/1.16.0/changes.md +0 -2
- data/docs/ruby_csv_pitfalls.md +228 -197
- data/ext/smarter_csv/Makefile +14 -17
- data/lib/smarter_csv/hash_transformations.rb +1 -1
- data/lib/smarter_csv/header_transformations.rb +11 -9
- data/lib/smarter_csv/reader.rb +7 -3
- data/lib/smarter_csv/reader_options.rb +223 -0
- data/lib/smarter_csv/version.rb +1 -1
- data/lib/smarter_csv/writer.rb +36 -26
- data/lib/smarter_csv/writer_options.rb +26 -0
- data/lib/smarter_csv.rb +2 -1
- metadata +4 -8
- data/ext/smarter_csv/smarter_csv.bundle +0 -0
- data/ext/smarter_csv/smarter_csv.bundle.dSYM/Contents/Info.plist +0 -20
- data/ext/smarter_csv/smarter_csv.bundle.dSYM/Contents/Resources/DWARF/smarter_csv.bundle +0 -0
- data/ext/smarter_csv/smarter_csv.bundle.dSYM/Contents/Resources/Relocations/aarch64/smarter_csv.bundle.yml +0 -5
- data/ext/smarter_csv/smarter_csv.o +0 -0
- data/lib/smarter_csv/options.rb +0 -229
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b40fb76fef88599d7449691806af6f76a131ffcd41e2ee145d5c87f3554a2006
|
|
4
|
+
data.tar.gz: edb27057973c0a88524579f450dc8ed3ffadbd983de7155a84ff159495c31233
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5b9e2a17ae14a5d7b3dfddd854148f38c8892d67544b51fecba888aa11c540096057460880564b89251194fea513c3e2807c500d93f896826db885daf64271fe
|
|
7
|
+
data.tar.gz: 90b5aa10c6bc36cbc97662de879deaf61c2417a61e4cb5171924aac991a37c762588ff6413a924bfd083ca10c1fa1739049561f3c6e9de6ff196bdba85c7878f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
|
|
2
2
|
# SmarterCSV 1.x Change Log
|
|
3
3
|
|
|
4
|
+
## 1.16.3 (2026-04-14) — New Feature
|
|
5
|
+
|
|
6
|
+
RSpec tests: **1,425 → 1,434** (+9 tests)
|
|
7
|
+
|
|
8
|
+
### New Features
|
|
9
|
+
|
|
10
|
+
* **`write_headers: false`** — new `SmarterCSV::Writer` option to suppress the header line when appending rows to an existing CSV file opened in `'a'` mode.
|
|
11
|
+
Defaults to `true` (existing behavior, fully backwards-compatible).
|
|
12
|
+
|
|
13
|
+
See [Appending to an Existing CSV File](docs/basic_write_api.md#appending-to-an-existing-csv-file).
|
|
14
|
+
|
|
15
|
+
### Other
|
|
16
|
+
* Refactor of internal options handling
|
|
17
|
+
|
|
18
|
+
## 1.16.2 (2026-03-30) — Bug Fixes
|
|
19
|
+
|
|
20
|
+
RSpec tests: **1,410 → 1,425** (+15 tests)
|
|
21
|
+
|
|
22
|
+
### Bug Fixes
|
|
23
|
+
|
|
24
|
+
* Fixed `value_converters` to accept lambdas and Procs in addition to class-based converters.
|
|
25
|
+
Thanks to [Jonas Staškevičius](https://github.com/pirminis) for issue [#329](https://github.com/tilo/smarter_csv/issues/329).
|
|
26
|
+
|
|
27
|
+
* Fixed blank header auto-naming to use **absolute column position**, consistent with extra data column naming.
|
|
28
|
+
`name,,` now produces `column_2`/`column_3` instead of `column_1`/`column_2`.
|
|
29
|
+
⚠️ If your code references auto-generated keys for blank headers, update those to use the absolute column position.
|
|
30
|
+
|
|
31
|
+
* Fixed `Writer`: when both `map_headers:` and `header_converter:` were used together, `map_headers` was silently ignored.
|
|
32
|
+
`map_headers` is now applied first, then `header_converter` on top.
|
|
33
|
+
|
|
4
34
|
## 1.16.1 (2026-03-16) — Bug Fixes & New Features
|
|
5
35
|
|
|
6
36
|
RSpec tests: **1,247 → 1,410** (+163 tests)
|
|
@@ -101,7 +131,6 @@ Measured on 19 benchmark files, Apple M1, Ruby 3.4.7. See [benchmarks](docs/rele
|
|
|
101
131
|
* `remove_values_matching:` → use `nil_values_matching:`
|
|
102
132
|
* `strict:` → use `missing_headers: :raise/:auto`
|
|
103
133
|
* `verbose: true/false` → use `verbose: :debug/:normal`
|
|
104
|
-
* `only_headers:` / `except_headers:` → use `headers: { only: }` / `headers: { except: }`
|
|
105
134
|
|
|
106
135
|
### Bug Fixes
|
|
107
136
|
|
data/CONTRIBUTORS.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# A Big Thank You to all
|
|
1
|
+
# A Big Thank You to all 63 Contributors!!
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
A Big Thank you to everyone who filed issues, sent comments, and who contributed with pull requests:
|
|
@@ -65,3 +65,4 @@ A Big Thank you to everyone who filed issues, sent comments, and who contributed
|
|
|
65
65
|
* [Tophe](https://github.com/tophe)
|
|
66
66
|
* [Dom Lebron](https://github.com/biglebronski)
|
|
67
67
|
* [Paho Lurie-Gregg](https://github.com/paholg)
|
|
68
|
+
* [Jonas Staškevičius](https://github.com/pirminis)
|
data/README.md
CHANGED
|
@@ -249,7 +249,7 @@ For reporting issues, please:
|
|
|
249
249
|
* open a pull-request adding a test that demonstrates the issue
|
|
250
250
|
* mention your version of SmarterCSV, Ruby, Rails
|
|
251
251
|
|
|
252
|
-
# [A Special Thanks to all
|
|
252
|
+
# [A Special Thanks to all 63 Contributors!](CONTRIBUTORS.md) 🎉🎉🎉
|
|
253
253
|
|
|
254
254
|
|
|
255
255
|
## Contributing
|
data/docs/basic_write_api.md
CHANGED
|
@@ -568,6 +568,54 @@ end
|
|
|
568
568
|
> **Note:** Only use `write_bom: true` with UTF-8 output. Adding a UTF-8 BOM to a
|
|
569
569
|
> non-UTF-8 file will corrupt it.
|
|
570
570
|
|
|
571
|
+
## Appending to an Existing CSV File
|
|
572
|
+
|
|
573
|
+
Use `write_headers: false` to suppress the header line when appending rows to an
|
|
574
|
+
existing CSV file. The caller is responsible for opening the file in append mode — the
|
|
575
|
+
Writer writes only what you ask it to write.
|
|
576
|
+
|
|
577
|
+
```ruby
|
|
578
|
+
# First write: create the file with header + first batch of rows
|
|
579
|
+
SmarterCSV.generate('output.csv') do |csv|
|
|
580
|
+
csv << { name: 'Alice', age: 30 }
|
|
581
|
+
end
|
|
582
|
+
# output.csv:
|
|
583
|
+
# name,age
|
|
584
|
+
# Alice,30
|
|
585
|
+
|
|
586
|
+
# Later: append more rows without repeating the header
|
|
587
|
+
File.open('output.csv', 'a') do |f|
|
|
588
|
+
SmarterCSV.generate(f, write_headers: false) do |csv|
|
|
589
|
+
csv << { name: 'Bob', age: 25 }
|
|
590
|
+
end
|
|
591
|
+
end
|
|
592
|
+
# output.csv:
|
|
593
|
+
# name,age
|
|
594
|
+
# Alice,30
|
|
595
|
+
# Bob,25
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
The Writer still uses the hash keys to determine column order, so the appended rows
|
|
599
|
+
will be aligned correctly as long as the same set of keys is used. If you need to
|
|
600
|
+
guarantee column order across both writes, pass `headers:` explicitly:
|
|
601
|
+
|
|
602
|
+
```ruby
|
|
603
|
+
HEADERS = %i[name age]
|
|
604
|
+
|
|
605
|
+
SmarterCSV.generate('output.csv', headers: HEADERS) do |csv|
|
|
606
|
+
csv << { name: 'Alice', age: 30 }
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
File.open('output.csv', 'a') do |f|
|
|
610
|
+
SmarterCSV.generate(f, headers: HEADERS, write_headers: false) do |csv|
|
|
611
|
+
csv << { name: 'Bob', age: 25 }
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
> **Note:** `write_headers: false` only suppresses the header line. All other
|
|
617
|
+
> options (`col_sep:`, `row_sep:`, `value_converters:`, etc.) apply as normal.
|
|
618
|
+
|
|
571
619
|
## More Examples
|
|
572
620
|
|
|
573
621
|
Check out the [RSpec tests](../spec/smarter_csv/writer_spec.rb) for more examples.
|
data/docs/options.md
CHANGED
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
| `:write_nil_value` | `''` | String written in place of `nil` field values. E.g. `write_nil_value: 'N/A'`. |
|
|
46
46
|
| `:write_empty_value` | `''` | String written in place of empty-string field values, including missing keys. E.g. `write_empty_value: 'EMPTY'`. |
|
|
47
47
|
| `:write_bom` | `false` | Prepends a UTF-8 BOM (`\xEF\xBB\xBF`) to the output. Use with `encoding: 'UTF-8'` for Excel compatibility. |
|
|
48
|
+
| `:write_headers` | `true` | When `false`, suppresses the header line entirely. Use when appending rows to an existing CSV file (open the file in `'a'` mode yourself and pass the IO object). |
|
|
48
49
|
|
|
49
50
|
|
|
50
51
|
## CSV Reading
|
|
@@ -119,7 +120,7 @@ See [Parsing Strategy](./parsing_strategy.md) for full details on quote handling
|
|
|
119
120
|
|--------|---------|-------------|
|
|
120
121
|
| `:strip_whitespace` | `true` | Remove whitespace before/after values and headers. |
|
|
121
122
|
| `:convert_values_to_numeric` | `true` | Convert strings containing integers or floats to the appropriate numeric type. Accepts `{except: [:key1, :key2]}` or `{only: :key3}` to limit which columns. |
|
|
122
|
-
| `:value_converters` | `nil` | Hash of `:header =>
|
|
123
|
+
| `:value_converters` | `nil` | Hash of `:header => converter`; converter can be a lambda/Proc or a class implementing `self.convert(value)`. See [Value Converters](./value_converters.md). |
|
|
123
124
|
| `:remove_empty_values` | `true` | Remove key/value pairs where the value is `nil` or an empty string. |
|
|
124
125
|
| `:remove_zero_values` | `false` | Remove key/value pairs where the numeric value equals zero. |
|
|
125
126
|
| `:nil_values_matching` | `nil` | Set matching values to `nil`. Accepts a regular expression matched against the string representation of each value (e.g. `/\ANAN\z/` for NaN, `/\A#VALUE!\z/` for Excel errors). With `remove_empty_values: true` (default), nil-ified values are then removed. With `remove_empty_values: false`, the key is retained with a `nil` value. |
|
|
@@ -195,8 +195,6 @@ See [performance_notes.md](performance_notes.md) and [benchmarks.md](benchmarks.
|
|
|
195
195
|
|
|
196
196
|
**Deprecations:**
|
|
197
197
|
|
|
198
|
-
- `only_headers:` → use `headers: { only: }`
|
|
199
|
-
- `except_headers:` → use `headers: { except: }`
|
|
200
198
|
- `remove_values_matching:` → use `nil_values_matching:`
|
|
201
199
|
- `strict: true` → use `missing_headers: :raise`
|
|
202
200
|
- `strict: false` → use `missing_headers: :auto`
|