- Introduction
- Migrating from Ruby CSV
- Ruby CSV Pitfalls
- Parsing Strategy
- The Basic Read API
- The Basic Write API
- Batch Processing
- Configuration Options
- Row and Column Separators
- Header Transformations
- Header Validations
- Column Selection
- Data Transformations
- Value Converters
- Bad Row Quarantine
- Warnings
- Instrumentation Hooks
- Examples
- Real-World CSV Files
- SmarterCSV over the Years
- Release Notes
SmarterCSV records auto-detection and configuration warnings into a structured collection on the Reader, in addition to emitting them to a log sink. This lets you inspect warnings programmatically (e.g. surface them in dashboards, fail deploys on unexpected codes) without parsing stderr text.
reader = SmarterCSV::Reader.new('data.csv')
reader.process
reader.warnings
# => [
# { type: :config, code: :chunk_size_default, severity: :warn,
# message: "chunk_size not set, defaulting to 100. ...", count: 1 },
# ...
# ]Mirrors SmarterCSV.errors. Returns the warnings from the most recent call to
process, parse, each, or each_chunk on the current thread. Cleared at
the start of each new call.
SmarterCSV.process('data.csv')
SmarterCSV.warnings.each do |w|
logger.warn("[#{w[:type]}/#{w[:code]}] #{w[:message]} (×#{w[:count]})")
endNote:
SmarterCSV.warningsis per-thread (usesThread.current). It is safe in multi-threaded environments (Puma, Sidekiq), but not fiber-safe. If you process CSV files concurrently in fibers (e.g. withAsync,Falcon, or manualFiberscheduling), useSmarterCSV::Readerdirectly so warnings are scoped to the reader instance.
| Field | Description |
|---|---|
type |
Coarse semantic grouping. Currently: :config, :deprecation, :encoding, :row_sep. |
code |
Unique identifier for the specific warning. |
severity |
Log level: :debug / :info / :warn / :error / :fatal. |
message |
Human-readable description. |
count |
Number of times this (type, code) was triggered during the run. |
Repeated warnings of the same (type, code) are deduped — count tracks
occurrences. The message is the first one emitted.
| Code | Type | Severity | Triggered when |
|---|---|---|---|
:chunk_size_default |
:config |
:warn |
each_chunk is called without chunk_size: and the default of 100 is used. |
:header_a_method |
:deprecation |
:warn |
The deprecated Reader#headerA accessor is called. |
:utf8_missing_binary_mode |
:encoding |
:warn |
UTF-8 input is being processed but the IO was not opened with "b:utf-8". |
:no_clear_row_sep |
:row_sep |
:error |
Auto-detection found a true tie between separators after scanning 64KB. Falls back to "\n" — silent miss-parse risk. |
:no_row_sep_found |
:row_sep |
:error |
No known row separator was found in the first 64KB. Falls back to "\n". Likely an exotic separator like \u2028. |
When the warning is emitted, the sink is selected at Reader construction time:
- Rails.logger present — the warning is routed through
Rails.loggerat the declaredseverity.Rails.logger.warn(...),Rails.logger.error(...), etc. - No Rails.logger — falls back to
Kernel#warn(writes to$stderr).
Detection is one-shot at construct time, so there is no per-call overhead.
No setup needed. SmarterCSV detects Rails.logger automatically, and warnings appear in your Rails log at their declared severity:
SmarterCSV.process('data.csv')
# In log/development.log:
# [WARN] SmarterCSV: chunk_size not set, defaulting to 100. ...Falls back to Kernel#warn, which writes to $stderr:
SmarterCSV.process('data.csv')
# stderr:
# SmarterCSV: chunk_size not set, defaulting to 100. ...The programmatic reader.warnings / SmarterCSV.warnings collection is identical in both modes — you can always inspect warnings without parsing log output.
Pass verbose: :quiet to suppress both the recording and the log emission of
all warnings. Currently this affects every code listed above.
SmarterCSV.process('data.csv', verbose: :quiet)
SmarterCSV.warnings # => []
⚠️ Suppressing:row_sepwarnings hides genuine silent miss-parse risk on ambiguous files. Prefer passingrow_sep:explicitly over silencing.
PREVIOUS: Bad Row Quarantine | NEXT: Instrumentation Hooks | UP: README