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
Can't Use Compass After Installing It
How to Load a Spec_Helper.Rb Automatically in Rspec 2
Rails Console - Find Where Created at = Certain Day
How to Install Ruby Gems When Using Rvm
Rails 3 Initializes Extremely Slow on Ruby 1.9.2
How to Test 'Create' Controller Actions
How to Dynamically Call Routes Helper in Rails
How to Create Database from Schema.Rb Without Initializing Rails
Rails Routing (Root :To => ...)
How to Use Capybara in Pure Ruby (Without Rails)
Unit Test in Rails - Model with Paperclip
Convert JSON String to JSON Array in Rails
"Require File.Dirname(_File_)" -- How to Safely Undo Filesystem Dependency