Ruby 光谱问题

Ruby 光谱问题,ruby,rspec,Ruby,Rspec,以下是一些我知道有效的代码: require 'csv' class Motorcycle attr_reader :name, :weight @@count = 0 def self.find (name) found = nil ObjectSpace.each_object(Motorcycle) { |o| found = o if o.name == name } return found end def self

以下是一些我知道有效的代码:

require 'csv'

class Motorcycle
  attr_reader :name, :weight
  @@count = 0

  def self.find (name)
    found = nil
    ObjectSpace.each_object(Motorcycle) { |o|
      found = o if o.name == name
    }
    return found
  end

  def self.create
    File.new('motorcycles.csv').readlines[1..-1].map{ |line|
        Motorcycle.new( *line.split( ',' )  )
    }
  end

  def initialize (name, weight)
    @name = name
    @weight = weight
    self.class.count += 1
  end

  def self.count
    return @@count
  end

  def self.count=( count ) 
    @@count = count 
  end

  def available_colors

    colors=[]
    colorsFile = File.read('colors.csv').split("\n").map { |line| line.split(',') }
    for i in (0..colorsFile.flatten.length) do
        if (colorsFile.flatten[i].to_s == self.name.to_s)
            colors.push(colorsFile.flatten[i+1])
        end
    end

    return colors
  end

  def contains (name,color)
    if(self.name.to_s == name)
    else
        return color
    end
  end

  def has_abs?
    File.open( 'abs.txt' ) do |io|
    io.each {|line| line.chomp! ; return true if line.include? self.name.to_s}
    end

    return false
  end

end

Motorcycle.create
代码必须通过rspec上的以下测试:

describe Motorcycle do
  describe "loading the motorcycle list" do
    it "should load 2 motorcycles from the CSV" do
      Motorcycle.count.should == 2
    end
  end

  describe "finding a motorcycle by name" do
    it "should return an instance of the Motorcycle class" do
      Motorcycle.find("1200 RT").should be_a Motorcycle
    end    
  end

  describe "#weight" do
    it "should have a weight of 800 pounds for the 1200 RT" do
      Motorcycle.find("1200 RT").weight.should == '800 pounds'
    end

    it "should have a weight of 500 pounds for the 600 GS" do
      Motorcycle.find("600 GS").weight.should == '500 pounds'
    end
  end

  describe "#available colors" do
    it "should find 'red' and 'black' as available colors for the BMW 1200 RT" do
      Motorcycle.find("1200 RT").available_colors.should == [ 'red', 'black' ]
    end

    it "should find 'green' and 'blue' as available colors for the BMW 600 GS" do
      Motorcycle.find("600 GS").available_colors.should == [ 'green', 'blue' ]
        end    
  end

  describe "#has_abs?" do
    it "should be true for a motorcycle that appears in abs_motorcycles.txt" do
      Motorcycle.find("1200 RT").has_abs?.should be_true
    end

    it "should be false for a motorcycle that does not appear in abs_motorcycles.txt" do
      Motorcycle.find("600 GS").has_abs?.should be_false
    end
  end
end
问题是,在第一次测试之后(计算motrocicle实例的数量),每个实例都是零,也就是说,除了第一次测试之外,所有测试都失败了。以下是输出日志:

Failures:

  1) Motorcycle finding a motorcycle by name should return an instance of the Motorcycle class
     Failure/Error: Unable to find matching line from backtrace
       expected nil to be a kind of Motorcycle
     # ./motoapp.rb:76

  2) Motorcycle#weight should have a weight of 800 pounds for the 1200 RT
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `weight' for nil:NilClass
     # ./motoapp.rb:82

  3) Motorcycle#weight should have a weight of 500 pounds for the 600 GS
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `weight' for nil:NilClass
     # ./motoapp.rb:86

  4) Motorcycle#available colors should find 'red' and 'black' as available colors for the BMW 1200 RT
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `available_colors' for nil:NilClass
     # ./motoapp.rb:92

  5) Motorcycle#available colors should find 'green' and 'blue' as available colors for the BMW 600 GS
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `available_colors' for nil:NilClass
     # ./motoapp.rb:96

  6) Motorcycle#has_abs? should be true for a motorcycle that appears in abs_motorcycles.txt
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `has_abs?' for nil:NilClass
     # ./motoapp.rb:102

  7) Motorcycle#has_abs? should be false for a motorcycle that does not appear in abs_motorcycles.txt
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `has_abs?' for nil:NilClass
     # ./motoapp.rb:106

Finished in 0.01223 seconds
8     examples, 7 failures
我一直倾向于认为这是某种bug或其他原因,因为我的手动测试结果如下:

puts Motorcycle.count
puts Motorcycle.find("1200 RT")
puts Motorcycle.find("1200 RT").weight
puts Motorcycle.find("600 GS").weight
puts Motorcycle.find("1200 RT").available_colors
puts Motorcycle.find("600 GS").available_colors
puts Motorcycle.find("1200 RT").has_abs?
puts Motorcycle.find("600 GS").has_abs?
这给了我这个输出:

2
#<Motorcycle:0x7fd8bffcfd88>
800 pounds
500 pounds
red
black
green
blue
true
false
2
#
800英镑
500英镑
红色
黑色
绿色
蓝色
真的
假的

所以我真的几乎走到了死胡同,有人知道会发生什么吗?

在我看来,在执行create调用时,您没有将MOTORY对象存储在任何地方,因此如果GC被调用,实例就会消失。加载更多ruby代码(rspec)可能会导致GC调用更快


为什么不将实例存储在类级别的
集合中呢?(例如,用
实例替换count调用好的,我必须说我对ruby没有太多经验,我是一个新手,所以如果你能提供一个更清晰的例子,我会更容易理解(很抱歉,搜索类级实例不会返回太多结果).哦,好的,我想我明白你的意思了,我应该创建一个名为实例的集合,对于每个创建的实例,我应该准确地执行实例,而不是使用计数器使用集合(
要求“集合”
)然后把东西放进去。或者更好,因为你要按名称查找对象,所以使用一个
散列
,在那里你将使用名称作为键,对象作为值来存储摩托车。我编辑了我的答案,以展示一个例子。嗯,听起来它可以工作,我会尝试一下,但似乎我必须重写一些代码才能做到这一点不管怎么说,它正在工作,我将开始工作并发布我的发现。@Q_ro,这是一个链接,可以解释GC在ruby中的工作方式您的对象没有活动引用(根)以及垃圾收集何时开始(可能在第一次测试之后)您在irb中看不到这个结果,因为RSpec本身会消耗额外的内存,从而触发GC.start。“rspect”是“RSpec”的拼写错误吗?
Class Motorcycle
 # use a constant, this will always point to the same object even though
 # the content of the object changes. 
 # Using @@instances would also be ok
 Instances = Set.new # or you can use Instances = Hash.new
 def initialize (name, weight)
   @name = name
   @weight = weight
   # 
   Instances << self # or store the name/instance mapping Instances[name] = self
 end