Content | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11

Official Ruby FAQ

If you wish to report errors or suggest improvements for this FAQ, please go to our GitHub repository and open an issue or pull request.

Methods

How does Ruby choose which method to invoke?

Ruby binds all messages to methods dynamically. It searches first for singleton methods in the receiver, then for methods defined in the receiver’s own class, and finally for methods defined in the receiver’s superclasses (including any modules which may have been mixed in). You can see the order of searching by displaying ClassName.ancestors, which shows the ancestor classes and modules of ClassName.

If after searching the alternatives a matching method could not be found, Ruby tries to invoke a method called method_missing, repeating the same search procedure to find it. This allows you to handle messages to unknown methods, and is often used to provide dynamic interfaces to classes.

module Emphasizable
  def emphasize
    "**#{self}**"
  end
end

class String
  include Emphasizable
end

String.ancestors
  # => [String, Emphasizable, Comparable, Object, Kernel, BasicObject]

"Wow!".emphasize  # => "**Wow!**"

When the method emphasize is searched for, it is not found in class String, so Ruby searches next in the module Emphasizable.

In order to override a method that already exists in the receiver’s class, e.g. String#capitalize, you need to insert the module into the ancestor chain in front of that class, by using prepend:

module PrettyCapitalize
  def capitalize
    "**#{super}**"
  end
end

class String
  prepend PrettyCapitalize
end

String.ancestors
  # => [PrettyCapitalize, String, Comparable, Object, Kernel, BasicObject]

"hello".capitalize  # => "**Hello**"

Are +, -, *, … operators?

+, -, and the like are not operators but method calls. They can, therefore, be overloaded by new definitions.

class MyString < String
  def -(other)
    self[0...other.size]  # self truncated to other's size
  end
end

However, the following are built-in control structures, not methods, which cannot be overridden:

=, .., ..., not, ||, &&, and, or, ::

To overload or to define the unary + and - operators, you need to use +@ and -@ as the method names.

= is used to define a method to set an attribute of the object:

class Test
  def attribute=(val)
    @attribute = val
  end
end

t = Test.new
t.attribute = 1

If operators such as + and - are defined, Ruby automatically handles the self assignment forms (+=, -=, and so on).

Where are ++ and -- ?

Ruby does not have the autoincrement and autodecrement operators. You can use += 1 and -= 1 instead.

What is a singleton method?

A singleton method is an instance method associated with one specific object.

You create a singleton method by including the object in the definition:

class Foo; end

foo = Foo.new
bar = Foo.new

def foo.hello
  puts "Hello"
end

foo.hello
bar.hello

Produces:

Hello
prog.rb:11:in `<main>': undefined method `hello' for #<Foo:0x000000010f5a40> (NoMethodError)

Singleton methods are useful when you want to add a method to an object and creating a new subclass is not appropriate.

All these objects are fine, but does Ruby have any simple functions?

Yes and no. Ruby has methods that look like functions in languages such as C or Perl:

def hello(name)
  puts "Hello, #{name}!"
end

hello("World")

Produces:

Hello, World!

However, they are actually method calls with the receiver omitted. In this case, Ruby assumes the receiver is self.

So, hello resembles a function but it’s actually a method belonging to class Object and sent as a message to the hidden receiver self. Ruby is a pure object-oriented language.

Of course you can use such methods as if they were functions.

So where do all these function-like methods come from?

Almost all classes in Ruby are derived from class Object. The definition of class Object mixes in the methods defined in the Kernel module. These methods are therefore available within every object in the system.

Even if you are writing a simple Ruby program without classes, you are actually working inside class Object.

Can I access an object’s instance variables?

An object’s instance variables (those variables starting with @) are not directly accessible outside the object. This promotes good encapsulation. However, Ruby makes it easy for you to define accessors to these instance variables in such a way that users of your class can treat instance variables just like attributes. Just use one or more of attr_reader, attr_writer, or attr_accessor.

class Person
  attr_reader   :name           # read only
  attr_accessor :wearing_a_hat  # read/write

  def initialize(name)
    @name = name
  end
end

p = Person.new("Dave")
p.name           # => "Dave"
p.wearing_a_hat  # => nil
p.wearing_a_hat = true
p.wearing_a_hat  # => true

You can also define your own accessor functions (perhaps to perform validation, or to handle derived attributes). The read accessor is simply a method that takes no parameters, and the assignment accessor is a method name ending in = that takes a single parameter. Although there can be no space between the method name and the = in the method definition, you can insert spaces there when you call the method, making it look like any other assignment. You can also utilize self assignments such as += and -=, as long as the corresponding + or - methods are defined.

What’s the difference between private and protected?

The visibility keyword private makes a method callable only in a function form, without an explicit receiver, and so it can only have self as its receiver. A private method is callable only within the class in which the method was defined or in its subclasses.

class Test
  def foo
    99
  end

  def test(other)
    p foo
    p other.foo
  end
end

t1 = Test.new
t2 = Test.new

t1.test(t2)

# Now make `foo' private

class Test
  private :foo
end

t1.test(t2)

Produces:

99
99
99
prog.rb:8:in `test': private method `foo' called for #<Test:0x00000000b57a48> (NoMethodError)
        from prog.rb:23:in `<main>'

Protected methods are also callable only from within their own class or its subclasses, but they can be called both in function form and using a receiver. For example:

def <=>(other)
  age <=> other.age
end

Will compile if age is a protected method, but not if it is private.

These features help you control access to your class’s internals.

How can I change the visibility of a method?

You change the visibility of methods using private, protected, and public. When used without parameters during a class definition, they affect the visibility of subsequent methods. When used with parameters, they change the visibility of the named methods.

class Foo
  def test
    puts "hello"
  end
  private :test
end

foo = Foo.new
foo.test

Produces:

prog.rb:9:in `<main>': private method `test' called for #<Foo:0x0000000284dda0> (NoMethodError)

You can make a class method private using private_class_method.

class Foo
  def self.test
    puts "hello"
  end
  private_class_method :test
end

Foo.test

Produces:

prog.rb:8:in `<main>': private method `test' called for Foo:Class (NoMethodError)

The default visibility for the methods defined in a class is public. The exception is the instance initializing method, initialize.

Methods defined at the toplevel are also public by default.

Can an identifier beginning with a capital letter be a method name?

Yes, it can, but we don’t do it lightly! If Ruby sees a capitalized name followed by a space, it will probably (depending on the context) assume it’s a constant, not a method name. So, if you use capitalized method names, always remember to put parameter lists in parentheses, and always put the parentheses next to the method name with no intervening spaces. (This last suggestion is a good idea anyway!)

Calling super gives an ArgumentError.

Invoking super with no parameters in a method passes all the arguments of that method to a method of the same name in a superclass. If the number of arguments to the original method disagrees with that of the higher-level method, an ArgumentError is raised. To get around this, simply call super and pass a suitable number of arguments.

How can I call the method of the same name two levels up?

super invokes the same named method one level up. If you are overloading a method in a more distant ancestor, use alias to give it a new name before masking it with your method definition. You can then call it using that aliased name.

How can I invoke an original built-in method after redefining it?

Within the method definition, you can use super. You can also use alias to give it an alternative name. Finally, you can call the original method as a singleton method of Kernel.

What is a destructive method?

A destructive method is one which alters the state of an object. String, Array, Hash, and others have such methods. Often there are two versions of a method, one with a plain name, the other with the same name, but followed by !. The plain version creates a copy of the receiver, makes its change to it, and returns the copy. The “bang” version (with the !) modifies the receiver in place.

Beware, however, that there are a fair number of destructive methods that do not have an !, including assignment methods (name=), array assignment ([]=), and methods such as Array.delete.

Why can destructive methods be dangerous?

Remember that assignment in most cases just copies object references, and that parameter passing is equivalent to assignment. This means you can end up with multiple variables referencing the same object. If one of those variables is used to invoke a destructive method, the object referenced by all of them will be changed.

def foo(str)
  str.sub!(/foo/, "baz")
end

obj = "foo"
foo(obj)     # => "baz"
obj          # => "baz"

In this case the actual argument is altered.

Can I return multiple values from a method?

Yes and no.

def m1
  return 1, 2, 3
end

def m2
  [1, 2, 3]
end

m1  # => [1, 2, 3]
m2  # => [1, 2, 3]

So, only one thing is returned, but that thing can be an arbitrarily complex object. In the case of arrays, you can use multiple assignment to get the effect of multiple return values. For example:

def foo
  [20, 4, 17]
end

a, b, c = foo
a              # => 20
b              # => 4
c              # => 17