Constants in modules

Hello,

I need to do something like this (this is a simplified version of some
other code, of course, but I don't want to get you lost in details
unrelated to the problem):

module M

  CONST_A = { 'k1' => 'v1', 'k2' => 'v2' }
  CONST_B = invert_hash(CONST_A)

  def method1
    # Do something with CONST_A
    puts CONST_A
  end

  def method2
    # Do something with CONST_B
    puts CONST_B
  end

  def invert_hash(h)
    inverted = {}
    h.each_pair { |k, v| inverted[v] = k }
    inverted
  end

end

My intention is to be able to calculate CONST_B by invoking a method in
the module itself... but I get this error message:

tests.rb:4: undefined method `invert_hash' for M:Module (NoMethodError)
  from tests.rb:1

I have tried lots of combinations by prefixing the module name, using
::, using module_function, etc., but nothing has worked.

Is there a way to do this? Of course I know there are obvious
workarounds such as defining the method outside the module, but that
would be quite ugly... and there should be a way to use code in my own
module from my own module!!!

Thanks in advance for your help,

    Luis.

···

--
Posted via http://www.ruby-forum.com/.

Two things - firstly, Ruby is interpreted, so invert_hash needs to be declared *before* you use it. Then, your methods need to be module methods - just put a "self." before each one, and it should work.

Luis Crespo wrote:

···

Hello,

I need to do something like this (this is a simplified version of some
other code, of course, but I don't want to get you lost in details
unrelated to the problem):

module M

  CONST_A = { 'k1' => 'v1', 'k2' => 'v2' }
  CONST_B = invert_hash(CONST_A)

  def method1
    # Do something with CONST_A
    puts CONST_A
  end

  def method2
    # Do something with CONST_B
    puts CONST_B
  end

  def invert_hash(h)
    inverted = {}
    h.each_pair { |k, v| inverted[v] = k }
    inverted
  end

end

My intention is to be able to calculate CONST_B by invoking a method in
the module itself... but I get this error message:

tests.rb:4: undefined method `invert_hash' for M:Module (NoMethodError)
  from tests.rb:1

I have tried lots of combinations by prefixing the module name, using
::, using module_function, etc., but nothing has worked.

Is there a way to do this? Of course I know there are obvious
workarounds such as defining the method outside the module, but that
would be quite ugly... and there should be a way to use code in my own
module from my own module!!!

Thanks in advance for your help,

    Luis.

Bryan JJ Buckley wrote:

Two things - firstly, Ruby is interpreted, so invert_hash needs to be
declared *before* you use it. Then, your methods need to be module
methods - just put a "self." before each one, and it should work.

Yes, it works!!

I already tried defining the method as a module method by prepending the
module name to the method name, which AFAIK it is totally equivalent to
prepending self.

...But I did not realize that the constant code is executed when reading
the module, so I had to define the method before.

Thank you!

    Luis.

···

--
Posted via http://www.ruby-forum.com/\.

Luis Crespo wrote:

...But I did not realize that the constant code is executed when reading
the module, so I had to define the method before.

Yes, this is a common gotcha.

Personally I like to have the main program at the top of my code, but
Ruby wants me to put it at the bottom, so it's seen all the function
definitions before I try to call them. You can get around it like this:

def main
  # ...
end

def function1
  # ...
end

def function2
  # ...
end

main

Defining a "main" function comes naturally to C programmers, but in Ruby
you actually have to call it at the bottom. :wink:

···

--
Posted via http://www.ruby-forum.com/\.