grackkle
grackkle

Reputation: 796

Calling a module function in a ruby module

I want to call a module function to define a constant in a utility module in ruby. However, when I try this I get an error message. Here comes the code and the error:

module M
  ABC = fun

  module_function

  def self.fun
    "works"
  end
end

Error message:

NameError: undefined local variable or method `fun' for M:Module

Any ideas? I also tried it without self and with M.fun but no success...

Upvotes: 1

Views: 3601

Answers (2)

spickermann
spickermann

Reputation: 107142

It is just that the method is not defined when you assign fun to ABC. Just change the order:

module M
  def self.fun
    "works"
  end

  ABC = fun
end

M::ABC
#=> "works"

If you dislike the order (constants below methods), you might want to consider to have the method itself to memorize its return value. A common pattern looks like:

module M
  def self.fun
    @cached_fun ||= begin
      sleep 4     # complex calculation
      Time.now    # return value
    end
  end
end

M.fun
# returns after 4 seconds => 2017-03-03 23:48:57 +0100
M.fun
# returns immediately => 2017-03-03 23:48:57 +0100

Upvotes: 7

Test this in you irb console:

$ irb 
2.3.3 :001 > module M
2.3.3 :002?>   def self.fun
2.3.3 :003?>     "worked"
2.3.3 :004?>   end
2.3.3 :005?>   
2.3.3 :006 >   ABC = fun
2.3.3 :007?> end
 => "worked" 
2.3.3 :008 > M
 => M 
2.3.3 :009 > M::ABC
 => "worked" 
2.3.3 :010 > 

The fact is that now you defined self.fun before using it.

In your code you used the method before defining it.

Upvotes: 2

Related Questions