user2851669
user2851669

Reputation:

Access module functions in Ruby

I am trying to access a module function that I have overriden in the class.

module Base
    def Hello
        puts "Hello"
    end
end

class Top

  include Base

  def Hello
    puts "hello from top"
  end

  def Hi
    if p == 1
        Hello
    else
        Base::Hello
    end
  end
end

But I get the following error -

Error:  undefined method `Hello' for Base:Module

Is there any way I can access the module function without using self.Hello in function definition.

Upvotes: 1

Views: 1382

Answers (4)

trust_nickol
trust_nickol

Reputation: 2114

If you are overwriting a instance method of a module within your class, you can call this method using super.

module Base
  def Hello
    puts "Hello"
  end
end 

class Top
    include Base

   def Hello
     if p == 1
       puts "hello from top"
     else
       super
     end
   end
 end

 t = Top.new
 t.Hello # => "Hello"

Upvotes: 0

kunashir
kunashir

Reputation: 949

You didn't understand meaning of include! When you include a module to a class methods from a module add to a object inheritance chain. In this way You can call that methods like own.

module A
 def hello
   p 'Hello from A'
 end
end
class MyClass
 include A
end

2.2.2 :010 > mm = MyClass.new
=> #<MyClass:0x00000000ecaa68> 
2.2.2 :011 > mm.hello
"Hello from A"

You can use next in your case:

module B
 def self.hello
   p 'Hello from B'
 end
end
class MyClass
 def my_hello
  B.hello #direct call from module B
 end
end

And one more note: Don't use capitalized name for a method

Upvotes: 0

Keith Bennett
Keith Bennett

Reputation: 4970

One way you can do this is to make the module's method a module method rather than an instance method. If you precede the method definition with module_function, then both a module and an instance method will be created. This will enable you to access the module method using the module's name (in this case, BaseModule.hello). I've trimmed your question code to the essentials and illustrated how that would work:

#!/usr/bin/env ruby

module BaseModule

    module_function

    def hello
        puts 'Hello from BaseModule'
    end
end


class MyClass
  include BaseModule

  def hello
    puts 'Hello from MyClass'
  end

  def module_hello
    BaseModule.hello
  end
end

MyClass.new.hello         # Hello from MyClass
MyClass.new.module_hello  # Hello from BaseModule

Upvotes: 1

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

You demonstrated the complete misunderstanding of OOP concepts. And, BTW, the method names in Ruby are not to be started with capital letter.

One can not just call an arbitrary method somewhere in the class hierarchy. Whether this was possible, the whole OOP would make absolutely no sense.

One might call the super method from within this method:

module Base
  def hello
    puts "Hello"
  end 
end

class Top 
  include Base

  def initialize p
    @p = p 
  end 
  def hello
    if @p == 1
      puts "hello from top"
    else
      super
    end 
  end 
  def hi
    hello
  end 
end

Top.new(1).hi
#⇒ hello from top
Top.new(2).hi
#⇒ Hello

or, one might declare the module function, a.k.a. static function and call it from everywhere:

module Base
  def self.hello
    puts "Hello"
  end
end

class Top
  # NOT NEEDED include Base
  def hello
    puts "hello from top"
  end

  def hi
    if p == 1
      hello
    else
      Base.hello
    end
  end
end

Upvotes: 3

Related Questions