我有一些代码可以在继续之前检查用户是否在“sakai_trained”数组中。出于某种原因,当我运行此代码时:
CSV.foreach(activation_csv, {:headers => true}) do |row|
if sakai_trained
row << 'Untrained' unless sakai_trained.include?(row[1])
end
course_list << row
end
我收到此错误
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>'
我首先想到的是行[1]存在问题,但即使使用字符串文字也会出现相同的问题。我检查确保sakai_trained数组存在并且其中也包含数据。我也尝试将其重写为if语句,以防除非逻辑存在缺陷,但也会返回相同的错误。
如果不清楚,我想在将该行添加到course_list数组之前检查位于行[1]中的用户标识是否存在于sakai_trained数组中。如果没有,我希望首先将“未经训练”添加到行中,然后将行添加到数组中。当我删除除非...部分我能够得到一个完整的course_list数组,但正如预期的那样,每一行都有“未经训练”。问题似乎与
有关unless sakai_trained.include?(row[1])
部分但我看不到它。
更新
sakai_trained = []
CSV.foreach(training_csv, {:headers => true}) do |trained|
sakai_trained << trained
end
我应该#map!每个带有.to_s的项目,然后将它们变成字符串?
更新2:
我改变了
sakai_trained << trained
到
sakai_trained << trained.to_s
它删除了错误,但输出仍然不正确。
更新3: 差不多。工作。你们都非常棒,而且令人沮丧的是,我学到了一些新的有趣的东西。
代码:
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
收率:
2124-5318,stuartademo,未经训练
2124-5320,bobsmith,未经训练
2124-4686,jimsmith,未经训练
2124-3560,jillsmith,未经训练
2124-3562,suesmith,未经训练
2124-5428,harrysmith,未经训练
什么时候应该
2124-5318,stuartademo,未经训练
2124-5320,bobsmith
2124-4686,jimsmith
2124-3560,jillsmith
2124-3562,suesmith
2124-5428,harrysmith
答案 0 :(得分:2)
问题发生在第478行的标准Ruby库中的csv.rb
文件中。以下是导致问题的CSV
代码:
#
# Returns +true+ if this row contains the same headers and fields in the
# same order as +other+.
#
def ==(other)
@row == other.row
end
从错误消息的外观中,字符串"stuartademo"
正在传递给此方法,当然,没有String#row
。看起来other
应该是csv文件的一行。根据上述方法的评论,它应该包含标题和字段。
我建议找到这个String "stuartademo"
的来源,并找出为什么只传递String而不是整行。
编辑:
如果从CSV填充sakai_trained
,则它不是数组,而是CSV:Row
类型。在这种情况下,当您致电CSV::Row#include?
时,==(other)
即被调用。因此,您要传递的是row[1]
是一个字符串。它不应该是一个字符串。
请尝试使用include?
或field?(data)
,而不是fields.include?
。
CSV.foreach(activation_csv, {:headers => true}) do |row|
if sakai_trained
row << 'Untrained' unless sakai_trained.field?(row[1])
end
course_list << row
end
答案 1 :(得分:1)
我认为这会简化逻辑,并可能帮助您以不同的方式追踪您的问题。
CSV.foreach(activation_csv, {:headers => true}) do |row|
if sakai_trained && !sakai_trained.include?(row[1])
row << 'Untrained'
end
course_list << row
end
更新:
尝试将其分解为部分并让我们知道所有输出是什么:
CSV.foreach(activation_csv, {:headers => true}) do |row|
puts row #=> 2124-5318,stuartademo
puts row.class #=> CSV::Row
puts row[1] #=> stuartademo
puts row[1].class #=> String
puts sakai_trained #=> I'm assuming nil because it is of NilClass
puts sakai_trained.class #=> NilClass
end
我认为你的sakai_trained实际上是nil
,这解释了为什么sakai_trained.to_s
摆脱了错误。您无法在任何内容上调用include?
,但在使用to_s
时,可能会将其转换为""
,这将返回false。