nil的未定义方法`id':对象集合的NilClass

时间:2015-01-13 22:54:16

标签: ruby

这是我的代码:

class Train
  attr_accessor :id, :person_id, :movie_id, :eval
  def initialize(id, person_id, movie_id, eval)
    @id = id
    @person_id = person_id
    @movie_id = movie_id
    @eval = eval
  end
end

trains = Array.new
CSV.open('train.csv', encoding: "BOM|UTF-16LE:UTF-8", row_sep: :auto, col_sep: ';') do    |csv|
  csv.each do |id, person_id, movie_id, eval|
    trains[id.to_i] = Train.new(id.to_i, person_id.to_i, movie_id.to_i, eval.to_i)
  end
end

trains.each do |t|
  puts t.id
end

它只是从CSV文件创建一个对象数组,并打印对象的ID,但我收到一个错误:

undefined method `id' for nil:NilClass

当我使用t打印对象时,为什么puts t为零。

1 个答案:

答案 0 :(得分:0)

您正在初始化数组,但随后通过指定索引添加到train数组。如果来自csv的id从1(或101)开始,则索引0到第一个将初始化为nil。

尝试使用trains <<代替trains[id.to_i]来填充数组。

编辑:

鉴于你的评论,我建议改用哈希。它们仍然是可枚举的,但通过这种方式,您可以自由迭代并使用id作为可访问的索引(键)。

trains = Hash.new
CSV.open('train.csv', encoding: "BOM|UTF-16LE:UTF-8", row_sep: :auto, col_sep: ';') do |csv|
  csv.each do |id, person_id, movie_id, eval|
    trains[id.to_i] = Train.new(id.to_i, person_id.to_i, movie_id.to_i, eval.to_i)
  end
end

所以现在你有一个列车的哈希,火车ID作为钥匙。访问它仍然看起来像一个数组,但它会返回该对象。因此trains[5]将返回id为5的Train对象。

我认为这比使用带有一堆nils的数组更好。但是,如果你出于某些原因,只需在你的迭代中使用一个条件后的条件(虽然这真的很尴尬):

trains.each do |t|
  puts t.id if t
end

在Ruby中,只有false和nil是“falsey”,意思是评估为false,这样就可以得到你想要的东西。但为了方便起见,我真的建议你去哈希路线。