Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby global scope

Tags:

scope

ruby

When answering another question, I realized that the following program does not quite do what I thought it does.

puts "test"
self.puts "test"  # => private method `puts' called for main:Object (NoMethodError)

The exception surprises me, as I always thought that top-level method calls would be resolved by the main object instance, but this doesn't seem to be the case.

Who's the actual receiver of the first call and how is it resolved? Is this a special rule that only applies to method calls at the top-level scope?

like image 543
Niklas B. Avatar asked Mar 28 '12 16:03

Niklas B.


People also ask

What is the scope of Ruby?

Ruby has four types of variable scope, local, global, instance and class. In addition, Ruby has one constant type. Each variable type is declared by using a special character at the start of the variable name as outlined in the following table. In addition, Ruby has two pseudo-variables which cannot be assigned values.

Does Ruby have global variables?

Global Variable has global scope and accessible from anywhere in the program. Assigning to global variables from any point in the program has global implications. Global variable are always prefixed with a dollar sign ($).

What is the scope of a class variable in Ruby?

Scope refers to what variables are available at any given point in time. Different kind of variables have different scopes. A scope can be very narrow (local variables) or very wide (global variables). You want to use the narrowest scope possible to avoid problems with state mutation & name collision.

How do you access global variables in Ruby?

Assignments to global variables can be made from anywhere in the program. Global variables are always prefixed with a dollar sign. It is necessary to define a global variable to have a variable that is available across classes. When a global variable is uninitialized, it has no value by default and its use is nil.


1 Answers

Here is a good discussion that talks about this question.

The top level methods, which are provided by Kernel, are automatically included to the Object class. This means the Kernel methods will appear in everything.

The error private method 'puts' called for main:Object (NoMethodError) is just stating that puts exists but is privately scoped.

ree-1.8.7-2011.03 :001 > puts "test"
test
ree-1.8.7-2011.03 :004 > self.send(:puts, "hi" )
hi

UPDATE

There is no magic for Kernel methods. There is no scope hopping or anything. I think the confusion lines in what the scope is when using self. You do not have access to private methods using self.

class PutsTest

  def success_puts
    private_puts
  end

  def failed_puts
    # trying to access a private method from self
    self.private_puts
  end

  private

  def private_puts
   puts 'hi'
  end
end

By using self, you are changing the scope from calling the method inside of PutsTest to calling from the outside of PutsTest

ree-1.8.7-2011.03 :095 > test = PutsTest.new
ree-1.8.7-2011.03 :096 > test.success_puts
hi
ree-1.8.7-2011.03 :097 > test.failed_puts
NoMethodError: private method `private_puts' called for #<PutsTest:0xd62c48>
like image 114
mguymon Avatar answered Sep 29 '22 18:09

mguymon