Reputation: 6064
Please consider the below code
class Execute
def self.inherited(klass)
puts "Class Inherited: #{klass}"
klass.run
end
def self.run
puts "Running Instance Methods"
instance_methods(false).each do |m|
if m.to_s.start_with?("test_")
puts "Executing Method: #{m}"
new.send(m)
end
end
end
end
puts "Before class definition"
class Raja < Execute
def test_1
puts 'test_1'
end
def test_2
puts 'test_2'
end
def test_3
puts 'test_3'
end
end
puts "After class definition"
I am currently making an attempt to access the test_1, test_2, and test_3 methods by instantiating an object from the parent class. Upon examination of the program, one may comprehend the actions I am performing. Nonetheless, the issue arises as the invocation of the instance_methods method returns an empty array, contrary to its expected behavior of providing the names of the instance methods, i.e., test_1, test_2, and test_3. I am at a loss as to why this discrepancy is occurring and would greatly appreciate any assistance in resolving this issue
Upvotes: 1
Views: 101
Reputation: 29598
Class#inherited
is called at the moment of inheritance.
At this point no instance_methods
(non-inherited instance methods since you used false
) have been defined.
class Raja < Execute #inherited is called here
# methods are defined here
end
It would be similar to the following
class Raja;end
Raja.instance_methods(false) #=> []
class Raja
def test_1 = 'test1'
end
You could possibly look into Module#method_added
instead however I am unclear on what the reasoning behind this code is so all I can do is answer the question of Why you are experiencing what you you are experiencing.
Update
Based on OP comments looking for an auto run mechanism similar to test-unit
:
As a very simplified Example:
class Tracker
@@runner = {}
def self.runner
@@runner
end
def self.inherited(klass)
runner[klass] = []
end
def self.method_added(method_name)
runner[self] << method_name if method_name.match?(/test_/)
end
end
class Runner
def self.run
Tracker.runner.each do |klass,tests|
tests.each do |m|
klass.new.send(m)
end
end
end
end
# Run the Runner before the program exits
at_exit { Runner.run}
Then (foo.rb)
require 'runner_tracker'
class Foo < Tracker
def test_1
puts 'test_1'
end
def test_2
puts 'test_2'
end
def test_3
puts 'test_3'
end
end
Output
> ruby foo.rb
test_1
test_2
test_3
Upvotes: 3