Martin DeMello <martindemello@gmail.com> writes:
---------------------------------------------
before.rb, working:
def helper_fn
puts "Hello from helper"
end
class Foo
def self.bar
helper_fn
end
end
Foo.bar
---------------------------------------------
This works, because the method #helper_fn is defined implicitely as an
instance method in the Object class:
irb(main):001:0> def help_fn
irb(main):002:1> puts "Hello from helper"
irb(main):003:1> end
=> :help_fn
irb(main):004:0> method(:help_fn)
=> #<Method: Object#help_fn>
That makes it available everywhere. To make your second example work,
you need to do one of the following:
1)
module Namespace
def self.helper_fn
puts "Hello from helper"
end
class Foo
def self.bar
Namespace.helper_fn
end
end
end
This defines Namespace.helper_fn as a module-level function on the
Namespace module, in contrast to the definition as an instance method as
your second example contained it. As such, it needs to be called with
the Namespace module as the receiver then in Namespace::Foo.bar.
2)
module Namespace
def helper_fn
puts "Hello from helper"
end
class Foo
extend Namespace
def self.bar
helper_fn
end
end
end
This keeps the definition of "helper_fn" as an instance method in the
Namespace module, but by means of the #extend method the Namespace
module is injected into the method resolution chain of the
Namespace::Foo class object itself.
There’s also a third option, that however requires more coding effort:
module Namespace
module Helpers
def helper_fn
puts "Hello from helper"
end
module_function :helper_fn
end
class Foo
extend Helpers
def self.bar
helper_fn
end
end
end
This extracts the helper function into its own module, and utilises the
#module_function method to make it both a module-level and
instance-level method of the Helpers module. In Namespace::Foo you can
then choose between using #extend and calling "helper_fn" without
explicit receiver (as shown above) or using
Namespace::Helpers.helper_fn. Both ways work simultaneously.
I’m sure there are even more ways to solve the problem, but I don’t
think there’s a problem with Rubys namespacing mechanism here. The
concept of instance methods on modules being only available when you mix
in the module is just a different way to do things.
Ruby makes no difference between a module used for namespacing and one
used for mixin purposes only. It is possible to even intermix both
concepts (Ruby’s own Math module for example does this), which can be
used for creating procedural-like APIs where full OO capability is not
required.
Greetings
Marvin
···
--
#!/sbin/quintus
Blog: http://www.guelkerdev.de
GnuPG key: F1D8799FBCC8BC4F