8

I was working on a simple Pi Generator while learning Ruby, but I kept getting NoMethodError on RubyMine 6.3.3, so I decided to make a new project and new class with as simple as possible, and I STILL get NoMethodError. Any reason?

class Methods
  def hello (player)
    print "Hello, " << player
  end
  hello ("Annie")
end

And the error I get is:

C:/Users/Annie the Eagle/Documents/Coding/Ruby/Learning Environment/methods.rb:5:in `<class:Methods>': undefined method `hello' for Methods:Class (NoMethodError)
Annie the Eagle
  • 135
  • 1
  • 1
  • 8
  • 1
    you're calling the method inside the class definition. I'm unsure its intended. – Tensibai Oct 14 '14 at 10:07
  • I'm not sure of your background / level of experience in OO programming, so just to check: do you understand the difference between classes and instances (and class methods and instance methods)? The answer assumes you do... – joshua.paling Oct 14 '14 at 10:16

4 Answers4

9

You have defined an instance method and are trying to call it as a method of a class. Thus you need to make the method hello a class method, not an instance method of the class Methods.

class Methods
  def self.hello(player)
    print "Hello, " << player
  end
  hello("Annie")
end

Or, if you want to define it as instance method then call it as below :

class Methods
  def hello(player)
    print "Hello, " << player
  end
end
Methods.new.hello("Annie")
VaVa
  • 303
  • 1
  • 13
Arup Rakshit
  • 109,389
  • 25
  • 234
  • 293
3

You're trying to call an instance method as a class method.

Here's some code that illustrates the difference between the two in ruby:

class Person

  # This is a class method - note it's prefixed by self
  # (which in this context refers to the Person class)
  def self.species
    puts 'Human'
    # Note: species is OK as a class method because it's the same 
    # for all instances of the person class - ie, 'Bob', 'Mary', 
    # 'Peggy-Sue', and whoever else, are ALL Human.
  end

  # The methods below aren't prefixed with self., and are
  # therefore instance methods

  # This is the construct, called automatically when
  # a new object is created
  def initialize(name)
    # @name is an instance variable
    @name = name
  end

  def say_hello
    puts "Hello from #{@name}"
  end

end

And now try it out, calling the methods...

# Call a class method...
# We're not referring to any one 'instance' of Person,
Person.species #=> 'Human'

# Create an instance
bob = Person.new('Bob')

# Call a method on the 'Bob' instance
bob.say_hello #=> 'Hello from Bob'

# Call a method on the Person class, going through the bob instance
bob.class.species #=> 'Human'

# Try to call the class method directly on the instance
bob.species #=> NoMethodError

# Try to call the instance method on the class
# (this is the error you are getting)
Person.say_hello #=> NoMethodError
joshua.paling
  • 12,854
  • 3
  • 38
  • 57
1

You've created an instance method, but you're calling a class method. In order to call hello("Annie"), you have to make an instance of Methods. For instance:

class Methods
  def self.hello(player)
      print "Hello, " << player
  end
end

my_method = Methods.new
my_method.hello("Annie")

This would output Hello, Annie

cetinajero
  • 137
  • 1
  • 2
  • 10
Sara Tibbetts
  • 4,408
  • 6
  • 35
  • 69
0

By defining a method with def method_name args you are defining a instance method that will be included in every object of that class, but not in the class itself.

On the other hand, by def self.method_name args you will get a class method that will be directly in the class, without the need of instanciate an object from it.

So If you have this:

Class Test
   def self.bar
   end

   def foo
   end

end

You can execute the instance method this way:

a = Test.new
a.foo

And as for the class one should be:

Test.foo
sz23
  • 36
  • 3