tushortz
tushortz

Reputation: 5025

error with ruby module and classes

I want to make a Ruby package to be available on the rubygems.org but my problem is in the file where I want to write the actual code, I'm confused. I watched some tutorials and saw something like this:

suppose the folder is

Mygem
  |__ lib
      |__ Mygem
         |__ Mygem.rb
         |__ version.rb

Inside the mygem.rb is the code:

class Sample
  "all codes"
end

module Somemodule
  class Someclass
  "somecodes"
  end

  def add(a,b)
    a+b
  end
end

Which of the two codes are necessary in the package and how can an instance of the module be called. Say for example I want to use the add method of the module.

I tried doing:

Somemodule::add.new(5,7)

but I get a undefined method 'add' for Somemodule:Module (nomethod error.)


I managed to get it working by adding changing add to self.add and methods should not have a .new I guess. maybe for only classes. AND I also tried Mymodule.add(4,7) and it worked.

Upvotes: 0

Views: 77

Answers (1)

Cary Swoveland
Cary Swoveland

Reputation: 110675

Somemodule#add is an instance method of the module, which means that you can only invoke it on an instance of a class that has Module#includeed the module or on a module (including classes) that has Object#extended the module (invoked, in the latter case, MyMod.add(5,7) or MyClass.add(5,7)).

To use add as a module method (sometimes called a module "function"), you must define self.add in the module (or extend the module on itself--see below). A module method m of module M is invoked M.m, not M::m. :: is used to reference classes and modules within M. include M and extend M disregard M's module methods (if it has any).

Lastly, add has nothing to do with the classes Sample and Somemodule::Someclass, so it boils down to this:

module Somemodule
  def self.add(a,b)
    a+b
  end
end

Somemodule.methods(false)          #=> [:add]     
Somemodule.instance_methods(false) #=> []     
Somemodule.add(5,7)                #=>12

As I metioned above, you could alternatively write:

module Somemodule
  def add(a,b)
    a+b
  end
  extend(self)
end

to create both a module and instance method :add:

Somemodule.instance_methods(false) #=> [:add]     
Somemodule.methods(false)          #=> []
Somemodule.methods.include?(:add)  #=> true     
Somemodule.method(:add).owner      #=> Somemodule
Somemodule.add(5,7)                #=> 12

Here extend could instead be invoked after the module has been defined:

module Somemodule
  def add(a,b)
    a+b
  end
end

Somemodule.extend(Somemodule)

Somemodule.instance_methods(false) #=> [:add]     
Somemodule.methods.include?(:add)  #=> true     
Somemodule.add(5,7)                #=>12

Upvotes: 1

Related Questions