SoSimple
SoSimple

Reputation: 701

Test to check if attribute is assigned fails

I'm trying out some of the exercises over on exercism. Each exercise comes with a set of pre-written tests that we need to make pass. The problem I'm currently working on asks us to write a Robot class. Each robot should come with a method called name that sets a default name. I'm doing that like this:

class Robot
  attr_accessor :name

  def self.name
    @name = DateTime.now.strftime("%y%^b%k%M%S")
    @name
  end
end

The problem is that the first test (I'm skipping over the rest for now) keeps failing. Here's the test:

  def test_has_name
    # rubocop:disable Lint/AmbiguousRegexpLiteral
    assert_match /^[A-Z]{2}\d{3}$/, Robot.new.name
    # rubocop:enable Lint/AmbiguousRegexpLiteral
  end

I'm not using the rubocop gem so I've left the commented lines as is. The test fails with this error:

  1) Failure:
RobotTest#test_has_name [robot-name/robot_name_test.rb:7]:
Expected /^[A-Z]{2}\d{3}$/ to match nil.

I suppose the biggest problem is that I don't really understand the error and I don't know if I need to install rubocop and uncomment those lines above or of my code is just plain wrong. Any help at all with this would be much appreciated.

Upvotes: 0

Views: 69

Answers (3)

user2536065
user2536065

Reputation:

Your method is a class method. Which means that Robot.name will give you the name, while Robot.new.name is nil.

You want to use:

def name
  #code
end

Instead of self.name.

You can also set name in the initialize method:

def initialize 
  @name = 'RB123'
end

Upvotes: 1

Andrey Deineko
Andrey Deineko

Reputation: 52357

There is number of issues with your code.

First, you define accessor :name, but you don't have initialize method.

What you have defined, is a class method name, which would work if you call Robot.name.

To make your class work, it should look like this:

class Robot

  def initialize
    @name = DateTime.now.strftime("%y%^b%k%M%S")
  end

end

Robot.new.name
#=> "15MAY150035"

Or You would do

class Robot

  def name
    DateTime.now.strftime("%y%^b%k%M%S")
  end

end

Robot.new.name
#=> "15MAY150649"

Also, in Ruby last line in method is already what would be returned, so you don't have to write @name here:

  def self.name
    @name = DateTime.now.strftime("%y%^b%k%M%S")
    @name # useless
  end

Furthermore, variable @name is useless here, since method name either way will return DateTime object.

You have to make sure you understand what is what in Ruby.

Upvotes: 1

Chowlett
Chowlett

Reputation: 46667

Your code defines name to be a method on the Robot class (that's what the self indicates; and @name here will be setting a member variable on the class object). You need to provide a way for each instance to have a name.

As a secondary concern, your method changes the name everytime name is called. You probably want to set it once (when the robot is initialized, probably!), then return that each time.

Upvotes: 1

Related Questions