rspec未定义的方法`title ='

时间:2018-07-21 20:17:27

标签: ruby rspec

当我运行bundle exec rspec时,出现此错误“ rspec未定义方法`title =”。请注意,在规格文件中,其名为“ title”而不是“ title =“的ive搜索了整个规格文件,以查看是否可以找到一个错字,但没有运气。 这是它给我的错误:

    Book
  title
    should capitalize the first letter (FAILED - 1)

Failures:

  1) Book title should capitalize the first letter
     Failure/Error: @book.title = "inferno"
     NoMethodError:
       undefined method `title=' for #<Book:0x007fec2b140450>

这是规格文件中停在以下位置的部分:

require '08_book_titles'

describe Book do
  before do
    @book = Book.new
  end

  describe "title" do
    it "should capitalize the first letter" do
        @book.title = "inferno"
        expect(@book.title).to eq("Inferno")
    end

据我所知,尝试之后,它混淆了“ @ book.title =” inferno“”中的标题为“ title =”(我将标题更改为另一个单词,并将该单词与等于结尾处)。我不确定为什么它在方法的末尾添加了一个相等的数字。

(我注释掉了所有我自己的代码,以确保错误来自规范文件)

1 个答案:

答案 0 :(得分:4)

tl; dr : 在"should capitalize the first letter"示例中,您设置了书名,但该类未实现该方法。


NoMethodError: undefined method `title=' for #<Book:0x007fec2b140450>

不言自明,但也可能造成混淆。任何NoMethodError表示尚未定义要在接收方上尝试访问的方法。

在一个很小的类Car中,用一个实例方法返回车轮总数:

class Car
  def initialize
    @wheels = '4 big wheels'
  end
  def wheels
    @wheels
  end
end

yaris = Car.new
p yaris.wheels # "4 big wheels"
p yaris.doors # `<main>': undefined method `doors' for #<Car:0x0000558d18cfbd68 (NoMethodError)

访问wheels方法将返回预期的结果,但是尝试访问doors方法将引发NoMethodError。 Car类中没有定义方法门。

该示例中的两个方法都称为“ getter”方法,它们返回您在类实现上某些时候可能需要的值。但是,由于有“ getter”方法,也有“ setter”方法,它们使用=符号定义。

在示例类中,我们在initialize方法中定义@wheels实例变量,然后通过wheels方法访问它们。但是如果您想重新定义车轮呢?也许是您撞坏了汽车,现在它只有3个车轮,所以,您需要一种方法来设置@wheels的值。

让我们尝试设置它们:

yaris = Car.new
p yaris.wheels # "4 big wheels"
yaris.wheels = '3 working wheels' # undefined method `wheels=' for #<Car:0x000055755ad933c8 @wheels="4 big wheels"> (NoMethodError)

现在您不能了,因为没有wheels=方法,因此不能那样更改@wheels的值。所以,不是,请定义它:

...
  def wheels=(value)
    @wheels = value
  end
end

yaris = Car.new
p yaris.wheels # "4 working wheels"
yaris.wheels = '3 working wheels'
p yaris.wheels # "3 working wheels"

就是这样,您现在就可以从任何Car实例获取并设置车轮。

大多数时候,您不会看到像wheels=这样的方法。由于Ruby具有让您定义类的属性访问器的能力。您可以使用attr_reader:wheels定义类,这将为您提供@wheels的值:

class Car
  attr_reader :wheels
  def initialize
    @wheels = '4 big wheels'
  end
end

yaris = Car.new
p yaris.wheels # "4 working wheels"

它的工作方式相同,但是同样,您无法定义@wheels的值,因为只有一个read属性,如果您愿意,则可以添加attr_reader的兄弟attr_writer:

class Car
  attr_reader :wheels
  attr_writer :wheels
  def initialize
    @wheels = '4 big wheels'
  end
end

现在完成了,您可以读取和设置@wheels值,但是为什么还要麻烦地一一写入读写器属性。您可以在作为参数传递的特定属性上使用attr_accessor,它在您的类上同时实现wheelswheels=方法。

class Car
  attr_accessor :wheels
  ...
end

p Car.instance_methods(false) # [:wheels=, :wheels]

为什么这么无聊?因为如果您能够知道这些方法的来源,那么您将能够知道它们为什么会出现或为什么不在应该出现的地方。不管使用什么框架,DSL,无论您使用什么其他框架,都是Ruby。

Module#instance_methods上。