2

I have .csv file with rows of which every row represents one call with certain duration, number etc. I need to create array of Call objects - every Call.new expects Hash of parameters, so it's easy - it just takes rows from CSV. But for some reason it doesn't work - when I invoke Call.new(raw_call) it's nil. It's also impossible for me to see any output - I placed puts in various places in code (inside blocks etc) and it simply doesn't show anything. I obviously have another class - Call, which holds initialize for Call etc.

require 'csv'
class CSVCallParser
  attr_accessor :io

  def initialize(io)
    self.io = io
  end

  NAMES = {
    a: :date,
    b: :service,
    c: :phone_number,
    d: :duration,
    e: :unit,
    f: :cost
  }

  def run
    parse do |raw_call| 
    parse_call(raw_call)
    end
  end

  private

  def parse_call(raw_call) 
    NAMES.each_with_object({}) do |name, title, memo|
      memo[name] = raw_call[title.to_s]
    end
  end

  def parse(&block) 
    CSV.parse(io, headers: true, header_converters: :symbol, &block)
  end

end

CSVCallParser.new(ARGV[0]).run

Small sample of my .csv file: headers and one row:

"a","b","c","d","e","f"
"01.09.2016 08:49","International","48627843111","0:29","","0,00"
2
  • can you provide a small sample of the csv file you are working with? So I can try to reproduce your code and see what's happening Commented Oct 5, 2016 at 15:23
  • Sure, I've edited my post :) Commented Oct 5, 2016 at 15:39

2 Answers 2

2

I noticed a few things that isn't going as expected. In the parse_call method,

def parse_call(raw_call) 
  NAMES.each_with_object({}) do |name, title, memo|
    memo[name] = raw_call[title.to_s]
  end
end

I tried to print name, title, and memo. I expected to get :a, :date, and {}, but what I actually got was [:a,:date],{}, and nil.

Also, raw_call headers are :a,:b,:c..., not :date, :service..., so you should be using raw_call[name], and converting that to string will not help, since the key is a symbol in the raw_call.

So I modified the function to

def parse_call(raw_call) 
  NAMES.each_with_object({}) do |name_title, memo|
    memo[name_title[1]] = raw_call[name_title[0]]
  end
end

name_title[1] returns the title (:date, :service, etc)

name_title[0] returns the name (:a, :b, etc)

Also, in this method

def run
  parse do |raw_call| 
    parse_call(raw_call)
  end
end

You are not returning any results you get, so you are getting nil,

So, I changed it to

  def run
    res = []
    parse do |raw_call| 
      res << parse_call(raw_call)
    end
    res 
  end

Now, if I output the line

p CSVCallParser.new(File.read("file1.csv")).run

I get (I added two more lines to the csv sample)

[{:date=>"01.09.2016 08:49", :service=>"International", :phone_number=>"48627843111", :duration=>"0:29", :unit=>"", :cost=>"0,00"},
 {:date=>"02.09.2016 08:49", :service=>"International", :phone_number=>"48622454111", :duration=>"1:29", :unit=>"", :cost=>"0,00"}, 
 {:date=>"03.09.2016 08:49", :service=>"Domestic", :phone_number=>"48627843111", :duration=>"0:29", :unit=>"", :cost=>"0,00"}]

If you want to run this program from the terminal like so

ruby csv_call_parser.rb calls.csv

(In this case, calls.csv is passed in as an argument to ARGV)

You can do so by modifying the last line of the ruby file.

p CSVCallParser.new(File.read(ARGV[0])).run

This will also return the array with hashes like before.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very very much, your modifications are getting me closer to full understanding of a problem. There's one more thing, I wanted to run program like this: ruby csv_call_parser.rb calls.csv, so I can get my results like this: CSVCallParser.new(ARGV[0]).run or CSVCallParser.new(File.read(ARGV[0]).run, but none of this work
See my update. What I did seems to be similar to what you have in your comment, but I was able to print out the hash array to the terminal.
Thank you very much, you have no idea how you helped me! So the main problem was using name and title? Using them as name_title[0] and [1] made all the difference?
0
csv = CSV.parse(csv_text, :headers => true)
puts csv.map(&:to_h)

outputs:

[{a:1, b:1}, {a:2, b:2}]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.