Let's study classes and methods in Ruby.

Write this in a file:

class Greeting
  def to(name)
    puts "Hi #{name.capitalize}"
  end
end

greeting = Greeting.new
greeting.to("John")

When you run:

$ ruby MyDef.rb
Hi John

Notice that we are creating a new object of the Greeting and after that calling the method to.

initialize

When you initialize an instance of a class it is possible to pass parameters to that object. The next example we are passing the name to use it in other methods.

class Greeting
  def initialize name
    @name = name
  end

  def hi
    puts "Hi #{@name.capitalize}"
  end

  def bye
    puts "Bye #{@name.capitalize}"
  end
end

greeting = Greeting.new "John"
greeting.hi
greeting.bye

The output is:

Hi John
Bye John

Notice that now we are saying the name only once, but both methods have access to it.

Methods using ? e !

It is not mandatory, but in Ruby it is common to use ? at the end of a method when it returns true or false.

For example, let's set name as optional:

class Greeting
  def initialize name = ''
    @name = name
  end

  def hi
    if name?
      puts "Hi #{@name.capitalize}"
    else
      puts "Hi you"
    end
  end

  def bye
    if name?
      puts "Bye #{@name.capitalize}"
    else
      puts "Bye you"
    end
  end

  def name
    @name
  end

  def name?
    @name != ''
  end
end

greeting = Greeting.new "John"
puts greeting.name
puts greeting.name?
puts greeting.hi

greeting = Greeting.new
puts greeting.name
puts greeting.name?
puts greeting.hi

Let's see the output:

$ ruby my.rb
John
true
Hi John

false
Hi you

With respect of ! it is a common sense use it for methods that change the data itself. It may or may not return the object changed. Let's take a look in an example:

class Greeting
  def initialize name
    @name = name
  end

  def hi
    if name?
      puts "Hi #{@name.capitalize}"
    else
      puts "Hi you"
    end
  end

  def bye
    if name?
      puts "Bye #{@name.capitalize}"
    else
      puts "Bye you"
    end
  end

  def name
    @name
  end

  def upcase
    @name.upcase
  end

  def upcase!
    @name = @name.upcase
  end
end

greeting = Greeting.new "John"

puts greeting.upcase
puts greeting.name
greeting.hi

puts greeting.upcase!
puts greeting.name
greeting.hi

The output of this one is:

$ ruby my.rb
JOHN
John
Hi John
JOHN
JOHN
Hi JOHN

First we called name with upcase but the data in name was not changed. When we called with upcase! the data changed to JOHN.

Another common sense is to have a method without ! and another with it.

The method without ! does not change the data of the object, it just return the change. It is up to you to keep it or discard it.

The method with ! usually returns the change and change the object. Sometimes when it is not possible to do that change this method also returns an exception.