I have ruby code like this:
module Hello
class Hi
def initialize()
puts self.module.name //Should print "Hello"
end
end
end
How can I get the name of the module the class is included in?
Thanks
You can do this with Module::nesting method:
nesting → array
Returns the list of Modules nested at the point of call.
module M
class C
Module.nesting[1] # => M
end
end
If you want to get this value from the instance methods, you can assign it to class variable:
module Hello
class Hi
##parent = Module.nesting[1]
def initialize()
puts ##parent # => Hello
end
end
end
Related
How do I pass processor_pool to the method inside the module?
class Dummy
def initialize
processor_pool = Concurrent::FixedThreadPool.new(10)
#threadpool = Module.new do
extend Concurrent::Promises::FactoryMethods
def self.default_executor
return processor_pool # this cannot find the processor_pool variable
end
end
end
end
I get the same error even if I make it an instance variable like #processor_pool
Something like this (I simplified your class a bit to get rid of dependencies for the sake of example, but its structure is the same):
class Dummy
attr_reader :threadpool
def initialize
processor_pool = "It works"
#threadpool = Module.new do
define_method :default_executor do
return processor_pool
end
module_function :default_executor
end
end
end
Dummy.new.threadpool.default_executor # => "It works"
I have 2 modules and 1 class:
module B
def hi
say 'hi'
end
end
module C
def say(message)
puts "#{message} from ???"
end
end
class A
include B
include C
end
A.new.hi
#=> hi from ???"
How i can get message as hi from B?
You could use caller_locations to determine the calling method's name, and use that information to retrieve the method's owner:
module C
def say(message)
method_name = caller_locations(1, 1)[0].base_label
method_owner = method(method_name).owner
puts "#{message} from #{method_owner}"
end
end
But this is very brittle. It would be much easier to simply pass the calling module, e.g.:
module B
def hi
say 'hi', B
end
end
module C
def say(message, mod)
puts "#{message} from #{mod}"
end
end
You can use Kenel#__method__ with Method#owner:
module C
def say(message)
puts "#{message} from #{method(__method__).owner }"
end
end
class A
include C
end
A.new.say('hello')
#=> hello from C
Kenel#__method__:
Returns the name at the definition of the current method as a Symbol.
If called outside of a method, it returns nil.
Method#owner:
Returns the class or module that defines the method.
Okay, I have a question about how to do something in ruby. I have a python example to show what I'm going for, so here it goes.
class TestScript:
def say(word):
pass
def x():
self.say("hello") #right now it will pass
So lets Say that module was called "tester.py" but now, in another module we can do this now:
import tester
class doScript(tester.TestScript):
def say(word):
return word #now its overrided so in this current module it will return it rather pass it
Now the previous say def that was passed is voided by the new one so now if something gets passed to say it will return it rather pass it. Is there any way to do this in ruby? thanks
Here is an example with three files: animal.rb, dog.rb, and script.rb.
# animal.rb
# Our base class.
class Animal
def speak
puts 'click-click'
end
def eat
puts 'chomp-chomp'
end
end
# dog.rb
# Dog inherits from Animal, but we override the speak() method.
require 'animal'
class Dog < Animal
def speak
puts 'woof-woof'
end
end
# script.rb
# Demo script.
require 'dog'
d = Dog.new
d.speak
d.eat
You can always inherit from other class:
class BasicSay
def say(text)
puts prepare_text(text)
end
def prepare_text(text)
do_something_with(text)
end
end
class HtmlSay < BasicSay
def say(text)
"<p>" + prepare_text(text) + "</p>"
end
end
I want to call instance_eval on this class:
class A
attr_reader :att
end
passing this method b:
class B
def b(*args)
att
end
end
but this is happening:
a = A.new
bb = B.new
a.instance_eval(&bb.method(:b)) # NameError: undefined local variable or method `att' for #<B:0x007fb39ad0d568>
When b is a block it works, but b as a method isn't working. How can I make it work?
It's not clear exactly what you goal is. You can easily share methods between classes by defining them in a module and including the module in each class
module ABCommon
def a
'a'
end
end
class A
include ABCommon
end
Anything = Hash
class B < Anything
include ABCommon
def b(*args)
a
end
def run
puts b
end
end
This answer does not use a real method as asked, but I didn't need to return a Proc or change A. This is a DSL, def_b should have a meaningful name to the domain, like configure, and it is more likely to be defined in a module or base class.
class B
class << self
def def_b(&block)
(#b_blocks ||= []) << block
end
def run
return if #b_blocks.nil?
a = A.new
#b_blocks.each { |block| a.instance_eval(&block) }
end
end
def_b do
a
end
end
And it accepts multiple definitions. It could be made accept only a single definition like this:
class B
class << self
def def_b(&block)
raise "b defined twice!" unless #b_block.nil?
#b_block = block
end
def run
A.new.instance_eval(&#b_block) unless #b_block.nil?
end
end
def_b do
a
end
end
The following code prints nothing, I was expecting welcomeBack. Please explain.
class Hello
#instanceHello = "welcomeBack"
def printHello
print(#instanceHello)
end
Hello.new().printHello();
end
I just started to lean ruby, so please forgive if the question looks dumb.
If you could memorize only one thing about defining methods and setting variables, it's this: always ask yourself, what is self at this point?
class Hello
# This ivar belongs to Hello class object, not instance of Hello.
# `self` is Hello class object.
#instanceHello = "welcomeBack"
def printHello
# Hello##instanceHello hasn't been assigned a value. It's nil at this point.
# `self` is an instance of Hello class
print #instanceHello
end
def self.printSelfHello
# Now this is Hello.#instanceHello. This is the var that you assigned value to.
# `self` is Hello class object
print #instanceHello
end
end
Hello.new.printHello # >>
Hello.printSelfHello # >> welcomeBack
If you want to set a default value for an ivar, do it in the constructor:
class Hello
def initialize
#instanceHello = "welcomeBack"
end
def printHello
print #instanceHello
end
end
Hello.new.printHello # >> welcomeBack
In Ruby, instance variables are defined and used in instance methods. So you need to put your assignment in the initialize method:
class Hello
def initialize
#instanceHello = "welcomeBack"
end
def printHello
print(#instanceHello)
end
end
Hello.new.printHello();
Also, note that I moved the printHello call outside of the class definition. This is because the class isn't actually defined until after it is closed the first time; that is, after the last end.
class Hello
#instanceHello = "welcomeBack"
def printHello
puts self.class.instance_variable_get(:#instanceHello)
end
Hello.new.printHello; #=> welcomeBack
end
This is not good programming, but just to illustrate that a class (which is an instance of the class Class) can also have instance variables, like any other instance. They are called "class instance variables" and are preferred to class variables. The following example illustrates how a counter could be defined at the class level :
class Hello
#counter = 0
class << self # access methods for class instance variables must be
# defined in the singleton class
attr_accessor :counter
end
def printHello
self.class.counter += 1
puts "Hello #{self.class.counter}"
end
end
Hello.new.printHello; #=> Hello 1
Hello.new.printHello; #=> Hello 2
p Hello.singleton_methods #=> ["counter=", "counter"]
change #instanceHello to self.class.instance_variable_get(:#instanceHello)
#instanceHello is a class instance variant
the code is this:
class Hello
#instanceHello = "welcomeBack"
##classHello = "greeting!"
def printHello
print(self.class.instance_variable_get(:#instanceHello))
print(self.class.class_variable_get(:##classHello))
end
end
Hello.new().printHello();