The reason this is happening is that, per the docs, CSV.table
is:
A shortcut for:
CSV.read( path, { headers: true,
converters: :numeric,
header_converters: :symbol }.merge(options) )
Note converters: :numeric
, which tells it to automatically (attempt to) convert numeric-looking fields to Numbers. Phone numbers, of course, aren't really numbers, but rather strings of digits.
If you don't want any converstions, you could pass converters: nil
as an option to CSV.table
.
Assuming you do want the :numeric
converter to still operate on the other fields, though, you need to define your own converter. A converter is a Proc that takes two arguments: A field value and an (optional) FieldInfo object. Your converter might look like this:
NUMERIC_EXCEPT_PHONE_CONVERTER = lambda do |value, field_info|
if field_info.header == :phone
value
else
CSV::Converters[:float].call(
CSV::Converters[:integer].call(value))
end
end
Then you would use it by passing it to CSV.table
as the converters:
option, which will override the default converters: :numeric
:
rooms_table = CSV.table("data.csv", encoding: "UTF-8", converters: NUMERIC_EXCEPT_PHONE_CONVERTER)
p rooms_table[0]
# => #<CSV::Row longitude:139.7113134 latitude:35.56712836 phone:"0311112222">
As you can see, the phone
value is now a string with the leading 0
.
You can see this code in action on repl.it: https://repl.it/@jrunning/WellmadeFarflungCron
Aside
Why, you might ask, is this bit so ugly?
CSV::Converters[:float].call(
CSV::Converters[:integer].call(value))
It's because the CSV module defines CSV::Converters thusly:
Converters = {
integer: lambda { |f|
Integer(f.encode(ConverterEncoding)) rescue f
},
float: lambda { |f|
Float(f.encode(ConverterEncoding)) rescue f
},
numeric: [:integer, :float],
# ...
}
Since the :numeric
converter is not specified as a lambda, but rather an array that indicates that it's really just a "chain" of the :integer
and :float
converters, we can't just do CSV::Converters[:numeric].call(value)
; we have to call the two converters manually. (If anybody knows something I'm missing, please leave a comment.)