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!
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.
Access module method directly without operator ('.' or '::')
Try running it like this
module Example
def do_something
puts 'foo!'
end
end
include Example
do_something #=> foo!
Modules and Accessing Variables from Modules (Ruby Language)
When writing a module the convention is to declare constants like this:
module Week
FIRST_DAY = 'Sunday'
end
Note that they're in ALL_CAPS
. Anything that begins with a capital letter is treated as a constant. Lower-case names of that sort are treated as local variables.
Generally it's bad form to access the constants of another module, it limits your ability to refactor how those are stored. Instead define a public accessor method:
module Week
def first_day
FIRST_DAY
end
end
Now you can call that externally:
Week.first_day
Note you can also change how that's implemented:
module Week
DAYS = %w[
Sunday
Monday
Tuesday
...
Saturday
]
def first_day
DAYS.first
end
extend self # Makes methods callable like Week.first_day
end
The nice thing about that is the first_day
method does exactly the same thing, no other code has to change. This makes refactoring significantly easier. Imagine if you had to track down and replace all those instances to Week::FIRST_DAY
.
There's some other things to note here. The first is that any time you call include
on a module
then you get the methods and constants loaded in locally. The second thing is when you define a mix-in module, be careful with your names to avoid potential conflict with the target class.
Since you've mixed it in, you don't need the namespace prefix, just calling first_day
should do it.
Access class variables in a modules class and instance methods
When inside MyModule::ClassMethods
, you're not inside MyModule
and don't have access to @@a_class_variable
. Here's a related question.
With an accessor, your code works fine :
module MyModule
@@a_class_variable = "lorem ipsum"
def self.a_class_variable
@@a_class_variable
end
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def a_class_method
MyModule.a_class_variable << " abc1"
end
end
# Use it in constructor
def initialize
@@a_class_variable << " abc2"
end
def an_instance_method
@@a_class_variable << " abc3"
end
end
class MyObject
include MyModule
end
my_object = MyObject.new
MyObject.a_class_method
p my_object.an_instance_method
#=> "lorem ipsum abc2 abc1 abc3"
As you noted in the comments, it exposes @@a_class_variable
to the public.
Setting the method as private
or protected
wouldn't work in the above example, since ClassMethods
and MyModule
aren't related.
It might not be the cleanest solution, but you could use send
to access the private method :
module MyModule
@@a_class_variable = 'lorem ipsum'
module ClassMethods
def a_class_method
MyModule.send(:__a_class_variable) << ' abc1'
end
end
# Use it in constructor
def initialize
@@a_class_variable << ' abc2'
end
def an_instance_method
@@a_class_variable << ' abc3'
end
class << self
def included(base)
base.extend ClassMethods
end
private
def __a_class_variable
@@a_class_variable
end
end
end
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
Related Topics
Remove a Tag But Keep the Text
Find Both Pattern and Position of Multiple Regex Matches in Ruby
Can't All or Most Cases of 'Each' Be Replaced with 'Map'
Arbitrary Precision Arithmetic with Ruby
Error: "Fatal: I Don't Handle Protocol ''Git' When Using Bundle Install
Mongodb Group Using Ruby Driver
How to Specify a Struct as the Return Value of a Function in Rubyffi
Google Analytics API Error "Selected Dimensions and Metrics Cannot Be Queried Together."
Why Does Ruby Hash a Fixnum N to 2N+1
Issues with Installing Ruby 2.0.0 on MACos Catalina
Why Does Ruby Release Memory Only Sometimes
Floating Point Precision in Ruby on Rails Model Validations
In Ruby How to Tell If a String Input Is in Uppercase or Lowercase
Rails Routing - Custom Routes for Resources
State MAChine, Model Validations and Rspec
Encoding Issues in JavaScript Files Using Rails Asset Pipeline