1

我有一些代码在继续之前检查用户是否在“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>'

起初我以为 row[1] 有问题,但即使使用字符串文字,它也会以同样的方式中断。我检查以确保 sakai_trained 数组存在并且其中也有数据。我还尝试将其重写为 if 语句,以防除非逻辑有缺陷,但也会返回相同的错误。

如果不清楚,我想在将行添加到 course_list 数组之前检查位于 row[1] 中的用户 ID 是否存在于 sakai_trained 数组中。如果没有,我希望先将“未训练”添加到行中,然后将行添加到数组中。当我删除 unless... 部分时,我能够获得一个完整的 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,鲍勃史密斯,未经训练

2124-4686,吉姆史密斯,未经训练

2124-3560,吉尔史密斯,未经训练

2124-3562,苏史密斯,未经训练

2124-5428,哈里史密斯,未经训练

什么时候应该

2124-5318,stuartademo,未经训练

2124-5320,鲍勃史密斯

2124-4686,吉姆史密斯

2124-3560,吉尔史密斯

2124-3562,苏史密斯

2124-5428,哈里史密斯

4

2 回答 2

2

问题出现在csv.rb标准 Ruby 库中第 478 行的文件中。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 文件的一行。根据上述方法的注释,它应该包含标题和字段。

我建议找出这个字符串"stuartademo"的来源,并弄清楚为什么只有字符串而不是整行被传入。

编辑:

如果sakai_trained从 CSV 填充,则它不是数组而是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
于 2012-04-20T18:43:28.463 回答
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?任何 nil 但当你使用to_s它时可能会将它变成""返回 false 的。

于 2012-04-20T19:32:53.650 回答