# Calling a Class Method on a Module

I have a module (in file dialect.rb) defined as such:

require 'dialect/generators/elements'

module Dialect
def self.included(caller)
caller.extend Dialect::Generator::Element
end

def self.version
"Dialect v#{Dialect::VERSION}"
end
end


Then I have the file dialect/generators/elements.rb, which looks like this:

module Dialect
module Generator
module Element

puts Dialect.version

end
end
end


If I run my app, I get:

/lib/dialect/generators/elements.rb:7:in <module:Element>':
undefined method version' for Dialect:Module (NoMethodError)


My question/problem is: I didn't understand why the Element module could not find the version method here.

How I call Dialect is like this:

require 'dialect'

class PageTest
include Dialect
end


So you can see Dialect is mixed-in to an existing class. It's when this class is instantiated that I get the error above.

When I try a simple IRB session doing what appears to be this same logic, this all seems to work:

irb(main):001:0> module Dialect
irb(main):002:1>   def self.version
irb(main):003:2>     puts "Version number"
irb(main):004:2>   end
irb(main):005:1> end
=> nil
irb(main):006:0> module Dialect
irb(main):007:1>   module Generator
irb(main):008:2>     module Element
irb(main):009:3>       puts Dialect.version
irb(main):010:3>     end
irb(main):011:2>   end
irb(main):012:1> end
Version number


Here I get the "Version number" text back, which tells me (I think?) that Dialect::Generator::Element can call the method version on Dialect.

The issue ended up being corrected by simply moving my require statement to the end, like this:

module Dialect
def self.included(caller)
caller.extend Dialect::Generator::Element
end

def self.version
"Dialect v#{Dialect::VERSION}"
end
end

require 'dialect/generators/elements'


Having the require statement at the end solves the problem I was having.

The question then becomes: is this a good way to do this? I feel like making my logic depend on where the require statement goes seems like a bad idea.

The require line in the first file means that ruby runs the second file before the first file, which is before the version method is declared...

Doing it the other way around will work, since only when included is called is the module Element is required.

dialect/dialect.rb:

module Dialect
def self.included(caller)
caller.extend Dialect::Generator::Element
end

def self.version
"Dialect v#{Dialect::VERSION}"
end
end


dialect/generators/elements.rb:

require 'dialect/dialect'

module Dialect
module Generator
module Element

puts Dialect.version

end
end
end


Alternatively, you could also write a file declaring only the version:

dialect/version.rb:

module Dialect
def self.version
"Dialect v#{Dialect::VERSION}"
end
end


Edit

To answer your question - this is not a good way to do this. The problem you encountered with the require hints to circular dependency - Dialect calls Element, which uses Dialect on its creation.

The correct resolution is to break this dependency by using my version.rb suggestion above, so the code will look like this:

dialect/version.rb:

module Dialect
def self.version
"Dialect v#{Dialect::VERSION}"
end
end


dialect/generators/elements.rb:

require 'dialect/version'

module Dialect
module Generator
module Element

puts Dialect.version

end
end
end


dialect/dialect.rb:

require 'dialect/version'
require 'dialect/generators/elements'

module Dialect
def self.included(caller)
caller.extend Dialect::Generator::Element
end
end