Jose
Jose

Reputation: 3558

Method call before method in Ruby?

I am new to Ruby and I saw methods defined like:

def method_one
  puts "method 1"
end

class MyClass
  method_one
  def method_two
    puts "method 2"
  end
end

The way method_one is used reminds me of Python decorators.The output of

c = MyClass.new
c.method_two

is

method 1

method 2

I have been trying to search for more information about this syntax/language feature in the Ruby documentation on the web but I don't know what keywords to search for.

What this is thing called?

Upvotes: 0

Views: 895

Answers (2)

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84443

TL;DR

This code doesn't do what you think it does. Don't do stuff like this.

Ruby's Top-Level Object

Ruby lets you define methods outside a class. These methods exist on a top-level object, which you can (generally) treat as a sort of catch-all namespace. You can see various posts like What is the Ruby Top-Level? for more details, but you shouldn't really need to care.

In your original post, method_one is just a method defined in the top-level. It is therefore available to classes and methods nested within the top-level, such as MyClass.

Methods in Classes

Despite what you think, the following doesn't actually declare a :method_one class or instance method on MyClass:

class MyClass
  method_one
  def method_two; end
end

Instead, Ruby calls the top-level ::method_one during the definition of the class, but it never becomes a class method (e.g. MyClass::method_one) or an instance method (e.g. MyClass.new.method_one). There might be a few use cases for doing this (e.g. printing debugging information, test injection, etc.) but it's confusing, error-prone, and generally to be avoided unless you have a really strong use case for it.

Better Options

In general, when you see something like this outside an academic lesson, the programmer probably meant to do one of the following:

  1. Extend a class.
  2. Add a singleton method to a class.
  3. Include a module in a class.
  4. Set up a closure during class definition.

The last gets into murky areas of metaprogramming, at which point you should probably be looking at updating your class initializer, or passing Proc or lambda objects around instead. Ruby lets you do all sorts of weird and wonderful things, but that doesn't mean you should.

Upvotes: 2

user3720516
user3720516

Reputation:

I think you're a little mislead; the output of:

c = MyClass.new
c.method_two

is

#<MyClass:0x007feda41acf18>
"method 2"

You're not going to see method one until the class is loaded or if you're in IRB you enter the last end statement.

I would suggest looking into ruby's initialize method.

Upvotes: 1

Related Questions