How to Access a Ruby Module Method

Access module functions in Ruby

You demonstrated the complete misunderstanding of OOP concepts. And, BTW, the method names in Ruby are not to be started with capital letter.

One can not just call an arbitrary method somewhere in the class hierarchy. Whether this was possible, the whole OOP would make absolutely no sense.

One might call the super method from within this method:

module Base
def hello
puts "Hello"
end
end

class Top
include Base

def initialize p
@p = p
end
def hello
if @p == 1
puts "hello from top"
else
super
end
end
def hi
hello
end
end

Top.new(1).hi
#⇒ hello from top
Top.new(2).hi
#⇒ Hello

or, one might declare the module function, a.k.a. static function and call it from everywhere:

module Base
def self.hello
puts "Hello"
end
end

class Top
# NOT NEEDED include Base
def hello
puts "hello from top"
end

def hi
if p == 1
hello
else
Base.hello
end
end
end

How to access method defined in a module inside another module in Ruby?

Assuming you don't want class level methods, you can also include the module into a class, instantiate an object of that class and call whoa:

class C
include A::B
end

c = C.new
c.whoa
# Whoa!

Can I invoke an instance method on a Ruby module without including it?

If a method on a module is turned into a module function you can simply call it off of Mods as if it had been declared as

module Mods
def self.foo
puts "Mods.foo(self)"
end
end

The module_function approach below will avoid breaking any classes which include all of Mods.

module Mods
def foo
puts "Mods.foo"
end
end

class Includer
include Mods
end

Includer.new.foo

Mods.module_eval do
module_function(:foo)
public :foo
end

Includer.new.foo # this would break without public :foo above

class Thing
def bar
Mods.foo
end
end

Thing.new.bar

However, I'm curious why a set of unrelated functions are all contained within the same module in the first place?

Edited to show that includes still work if public :foo is called after module_function :foo

How to access class method from the included hook of a Ruby module

There'a a method_added callback you could use:

module MyModule
def self.included(includer)
def includer.method_added(name)
puts "Method added #{name.inspect}"
end
end
end

class MyClass
include MyModule

def foo ; end
end

Output:

Method added :foo

If you want to track both, existing and future methods, you might need something like this:

module MyModule
def self.on_method(name)
puts "Method #{name.inspect}"
end

def self.included(includer)
includer.instance_methods(false).each do |name|
on_method(name)
end

def includer.method_added(name)
MyModule.on_method(name)
end
end
end

Example:

class MyClass
def foo ; end

include MyModule

def bar; end
end

# Method :foo
# Method :bar

Ruby: Use module method inside a class method

By including the module, you make module_method is an instance method on TestClass, meaning you need to invoke it on an instance of the class, not the class itself.

If you want to make it a method on the class itself, you need to extend TestModule, not include it.

module TestModule
def module_method
"module"
end
end

class TestClass
extend TestModule # extend, not include

def self.testSelfMethod
str = module_method
puts str
end
TestClass.testSelfMethod # "method"
end

Access a Ruby module's method within same module

What do I misunderstand?

1) An @variable is private, so you always need to provide an accessor method to access it (or use instance_variable_get() to violate privacy):

module CommonStuff
def common_thing
@x = second_thing # --> should access method in same module. Doesn't work.
end

def second_thing
10
end
end

class MyController
include CommonStuff

attr_accessor :x
end

obj = MyController.new
obj.common_thing
puts obj.x

--output:--
10

2) You can't include a module's class methods:

module CommonStuff
def self.common_thing
puts 'hello'
@x = second_thing # --> should access method in same module. Doesn't work.
end

def self.second_thing
10
end
end

class MyController
include CommonStuff
end

CommonStuff.common_thing
MyController.common_thing

--output:--
hello

1.rb:21:in `<main>': undefined method `common_thing' for MyController:Class (NoMethodError)

#obj = MyController.new
#obj.common_thing #Same error here

If you want to inject some class methods into MyController, you need to rework your CommonStuff module:

module CommonStuff
def self.included(includer) #Advanced 'hook' method
includer.extend ClassMethods
end

module ClassMethods
def common_thing
puts 'hello'
@x = second_thing # --> should access method in same module. Doesn't work.
end

def second_thing
10
end
end
end

class MyController
include CommonStuff
y = common_thing
puts y

puts instance_variable_get(:@x)
end

--output:--
10
10

The hook method is called whenever the module is included by another class/module, and the method is passed the including class/module as an argument.

Response to commment:

Only a controller's instance variables are made available in a view, e.g.:

class MyController

def do_stuff
@x = 10 #instance variable
end

end

but @variables created inside class methods are not the controller's instance variables:

class MyController

def self.do_stuff
@x = 10
end

end

Therefore, @variables created inside class methods will not be available in the view.

Why can't my Ruby module method access my module class variable?

The first @main_menu_options is not the same as the @main_menu_options referenced in the mixin method. The second method operates in the context of whatever called include.

If you want these both on the same page you'll need to redefine that method to be in the same scope:

module UserInterface
@main_menu_options = {
1 => "Display Task List",
2 => "Add New Task",
3 => "Edit A Task",
4 => "Delete A Task",
"Q" => "Quit"
}

# Module-level method has access to module-level defined variables
def self.main_menu(string = "")
@main_menu_options.each_value { |v| puts v }

if @main_menu_options == nil then puts "NOTHING THERE" end
end
end

This misses the bigger problem. Since those options never change you really should be defining this as a constant:

module UserInterface
MAIN_MENU_OPTIONS = {
1 => "Display Task List",
2 => "Add New Task",
3 => "Edit A Task",
4 => "Delete A Task",
"Q" => "Quit"
}

def main_menu(string = "")
MAIN_MENU_OPTIONS.each_value { |v| puts v }

if MAIN_MENU_OPTIONS == nil then puts "NOTHING THERE" end
end
end

You'll need to fix your if since that's not really functional code. When writing Ruby try to avoid one-liners like that, skip the then to avoid clutter.

Calling a method on a Ruby module

Simple method:

module MyModule
def self.my_method(*args)
MyModule::MyClass.my_method(*args)
end
end

Harder method:

Use metaprogramming to write a function for all cases (like attr_accessor).

How to access parent/sibling module methods

Constants are looked up first in the lexically enclosing module(s) and then up the inheritance chain.

module Foo
module Bar
module Baz
class Qux
def self.qux_method
Baz.baz_method
end
end
def self.baz_method
end
end
end
end

This will work, because the constant Baz will be first looked up in the lexically enclosing module (class) Qux, where it isn't found. The lookup continues in the lexically enclosing module Baz, where it also isn't found. Therefore, it will next be looked up in the lexically enclosing module Bar, where it is found and the search stops.

Note: you write in your title:

Ruby, Access parent/sibling module methods

This is wrong. These modules are neither parents nor siblings. There is no inheritance here. There is, in fact, no relationship between the modules at all. There is only a relationship between the constants and the modules: constants belong to modules.

The module declarations are lexically nested, but the modules themselves aren't.



Related Topics



Leave a reply



Submit