12

I have a ruby import to DB process that checks header titles against an array called headers. As it stands right now, those headers must be typed exactly the same as they appear in the array. I would like for them to be accepted regardless if they are upper or lowercase.

CSV.foreach(FILE, encoding:'iso-8859-1:utf-8', headers: true, skip_blanks: true) do |row| 

# check the header row, make sure all are acceptable
if count == 0
  row.headers.each do |header|
    if (!headers.include? header) and !header.nil? and header != ""
      log.error "#{header} is not a valid header"
       exit
    end
  end
 end

Currently accepts: "Ast_A" But does not accept: "ast_a" I have tried code from Convert hash keys to lowercase -- Ruby Beginner to no avail. My question is how do I make the .csv import header row case insensitive during the import?

Stinga B
  • 123
  • 1
  • 4
  • 2
    It looks like [the most upvoted answer](https://stackoverflow.com/a/15789635/179125) on the linked question answers your question precisely. It supplies a header converter lambda that will automatically convert all headers to lowercase. – Jordan Running Feb 20 '18 at 21:52
  • I tried the upvoted count (21) answer and got this error: 'undefined method 'try' for "x_id:String(NoMethod Error) – Stinga B Feb 20 '18 at 22:45
  • `Object#try` is a [method supplied by ActiveSupport](http://api.rubyonrails.org/classes/Object.html#method-i-try). Read the [Active Support Core Extensions guide](http://guides.rubyonrails.org/active_support_core_extensions.html) for more information. – Jordan Running Feb 20 '18 at 22:50

1 Answers1

15

You can provide a header_converter object that respond to the call method and receive the header string as an argument, such as a lambda or a proc:

converter = lambda { |header| header.downcase }
CSV.foreach([...], headers: true, header_converters: converter, [...]) do |row|

With this, all headers will be parsed in lower case. You can then compare it to a lower case version of your local variable headers.

MrYoshiji
  • 54,334
  • 13
  • 124
  • 117
  • I am very new to ruby and I am not sure how to 'compare it to a downcased version of my local variable' ({|h| h.downcase})? – Stinga B Feb 20 '18 at 21:57
  • you have a local variable called `headers` that you use to compare the header found in the CSV against it. This `headers` variable is probably an array of strings, you have to make sure they contain only downcased string – MrYoshiji Feb 20 '18 at 22:17
  • So I should also downcase the array? like 'headers.downcase = ["...", ...]` ? – Stinga B Feb 20 '18 at 22:46
  • no, you have somewhere in your code something like `headers = ['some', 'strings']` before you do the `CSV.foreach` call (I assume that because you have a line using it: `if (!headers.include? header)`). This `headers` variable seems to be an array of String. Make sure that you only have downcased string there. *before* the `CSV.foreach` block, you can do a simple `headers = headers.map(&:downcase)` (assuming that `headers` contains Strings only) – MrYoshiji Feb 20 '18 at 22:49
  • I get an undfined map error when using headers = headers.map(&:downcase) – Stinga B Feb 23 '18 at 16:14