I have a bit of code that checks if a user is in the "sakai_trained" array before proceeding. For some reason when I run this code:
CSV.foreach(activation_csv, {:headers => true}) do |row|
if sakai_trained
row << 'Untrained' unless sakai_trained.include?(row[1])
end
course_list << row
end
I get this error
C:/Ruby193/lib/ruby/1.9.1/csv.rb:478:in `==': undefined method `row' for "stuartademo":String (NoMethodError)
from activate-courses.rb:42:in `include?'
from activate-courses.rb:42:in `block in <main>'
from C:/Ruby193/lib/ruby/1.9.1/csv.rb:1792:in `each'
from C:/Ruby193/lib/ruby/1.9.1/csv.rb:1208:in `block in foreach'
from C:/Ruby193/lib/ruby/1.9.1/csv.rb:1354:in `open'
from C:/Ruby193/lib/ruby/1.9.1/csv.rb:1207:in `foreach'
from activate-courses.rb:40:in `<main>'
I thought at first it was having a problem with the row[1] but it breaks the same way even with a string literal. I checked to make sure the sakai_trained array exists AND has data in it as well. I also tried rewriting it as an if statement in case the unless logic was flawed but that also returns the same error.
In case it’s unclear, I want to check that the userid located in row[1] exists in the sakai_trained array before adding the row to the course_list array. If it doesn’t, I want ‘Untrained’ added to the row first, then the row added to the array. When I removed the unless… part I was able to get a complete course_list array, but as expected, every row has "untrained". The problem appears to be with the
unless sakai_trained.include?(row[1])
part but I just can’t see it.
Update:
sakai_trained = []
CSV.foreach(training_csv, {:headers => true}) do |trained|
sakai_trained << trained
end
Should I #map! each item with .to_s to make them into strings then?
Update 2:
I changed
sakai_trained << trained
to
sakai_trained << trained.to_s
and it’s removed the error, but the output still isn’t quite right.
Update 3:
ALMOST. WORKING. You guys are all incredibly awesome, and as frustrating as this is I have learned some new and interesting things.
Code:
course_list = []
if options[:verify]
sakai_trained = []
CSV.foreach(training_csv, {:headers => true}) do |trained|
sakai_trained << trained.to_s
end
end
CSV.foreach(activation_csv, {:headers => true}) do |row|
if sakai_trained && !sakai_trained.include?(row[1])
row << 'Untrained'
end
course_list << row
end
Yields:
2124-5318,stuartademo,Untrained
2124-5320,bobsmith,Untrained
2124-4686,jimsmith,Untrained
2124-3560,jillsmith,Untrained
2124-3562,suesmith,Untrained
2124-5428,harrysmith,Untrained
When it should be
2124-5318,stuartademo,Untrained
2124-5320,bobsmith
2124-4686,jimsmith
2124-3560,jillsmith
2124-3562,suesmith
2124-5428,harrysmith
The problem is occurring inside the
csv.rbfile in the standard Ruby library on line 478. Here’s theCSVcode that is causing the problem for you:From the looks of your error message, the String
"stuartademo"is being passed into this method and, of course, there is noString#row. It looks likeothershould be a row of a csv file. According to the comments on the above method, it should contain headers and fields.I would suggest finding where this String
"stuartademo"is coming from and figure out why only the String is getting passed in instead of the entire row.EDIT:
If
sakai_trainedis populated from a CSV, then it is not an array but ratherCSV:Rowtype. In this case, when you callCSV::Row#include?then the==(other)is getting called. Hence, what you are passing into is,row[1]is a String. It should not be a String.Instead of using
include?, try usingfield?(data)orfields.include?.