xis
xis

Reputation: 24850

Why function in same module is not accessable in ruby?

Let's say we have code looks like this

module TM
  def aa
    puts "aa"
  end

  def bb
    TM::aa
  end

  module_function :bb
end

TM.bb

Why bb cannot access aa by no matter "TM::aa", "self.aa" or "TM.aa"? They are in the same module. What is the benefit of setting such restriction and how do I solve the "undefined method" error?

Upvotes: 0

Views: 103

Answers (4)

bglusman
bglusman

Reputation: 43

I think you may be confused about the functionality of the call to module_function, as this method actually creates a copy of the method and makes the original method private, and mixes the copy into the meta-class (or eigenclass, in any case one step up on the method lookup chain). This is so it can be overridden without effecting internal use of the method, i.e. to make it safe for private use while also being publicly usable OR publicly overrideable. It's only the copy that's mixed into the meta-class that can't access aa, and that's because aa doesn't exist above it in the lookup chain. If both methods were passed into module function then you won't get the undefined method error.

Upvotes: 1

ayckoster
ayckoster

Reputation: 6827

This does not work because you are defining an instance method (def aa) instead of a module method (def self.aa).

Check out the documentation:

A Module is a collection of methods and constants. The methods in a module may be instance methods or module methods. Instance methods appear as methods in a class when the module is included, module methods do not. Conversely, module methods may be called without creating an encapsulating object, while instance methods may not. (See Module#module_function)

So what you want might be:

module TM
  def self.aa
    puts "aa"
  end

  def bb
    TM::aa
  end

  module_function :bb
end

TM.bb

Upvotes: 1

Chowlett
Chowlett

Reputation: 46667

Because aa is a instance function. If you add it to the module_function list (or use one of the many other methods of declaring module methods), everything works. Personally, I prefer:

module TM
  def self.aa
    puts "aa"
  end

  def self.bb
    TM::aa
  end

end

TM.bb

Upvotes: 1

Victor Moroz
Victor Moroz

Reputation: 9225

Did you mean something like this?

module TM
  class << self
    def aa
      puts "aa"
    end

    def bb
      TM::aa
    end
  end
end

TM.bb

UPDATE: methods as you defined them will be accessible as instance methods when you include your module or class methods if you extend your class

module TM
  def aa
    puts "aa"
  end

  def bb
    aa
  end
end

class A
  include TM
end

class B
  extend TM
end

A.new.bb

B.bb

Upvotes: 4

Related Questions