Reputation: 79
I have set up two classes as shown below
class Parent
def self.inherited(child)
child.custom_class_method
end
def self.custom_class_method
raise "You haven't implemented me yet!"
end
end
class Child < Parent
def self.custom_class_method
"hello world"
end
end
It seems that when the inheritence Child < Parent
is evaluated, it calls self.inherited
, which in turn raises the Parent
's version of self.custom_class_method
instead of the Child
's. This is a problem because instead of getting an expected "hello world"
I get an error raised saying "You haven't implemented me yet!"
Does Child
's self.custom_class_method
not get evaluated until after Parent
's self.inherited
is finished evaluating? And if so is there perhaps a work around this? Should I just not put a raise
check on the Parent class?
Upvotes: 4
Views: 2938
Reputation: 3858
You have to wrap self.inherited
in Thread.new
Example:
class Foo
def self.inherited klass
begin
puts klass::BAZ
rescue => error
# Can't find and autoload module/class "BAZ".
puts error.message
end
Thread.new do
# 123
puts klass::BAZ
end
end
end
class Bar < Foo
BAZ = 123
end
Upvotes: 0
Reputation: 967
The template pattern/lazy initialization may help solve your problem. The code assumes what is different between the children classes is the database connection information, perhaps just a table name or perhaps completely different databases. The parent class has all the code for creating and maintaining the connection, leaving the children only the responsibility of providing what is different.
class Parent
def connection
@connection ||= make_connection
end
def make_connection
puts "code for making connection to database #{database_connection_info}"
return :the_connection
end
def database_connection_info
raise "subclass responsibility"
end
end
class Child1 < Parent
def database_connection_info
{host: '1'}
end
end
class Child2 < Parent
def database_connection_info
{host: '2'}
end
end
child1 = Child1.new
child1.connection # => makes the connection with host: 1
child1.connection # => uses existing connection
Child2.new.connection # => makes connection with host: 2
Upvotes: 3
Reputation: 198304
I think this should clarify:
class Parent
def self.inherited(child)
puts "Inherited"
end
end
class Child < Parent
puts "Starting to define methods"
def self.stuff; end
end
Output makes it clear that .inherited
gets called the moment you open the new class, not when you close it. Thus, as you guessed, Child.custom_class_method
does not exist at the point when you are trying to call it - all .inherited
sees is a blank slate.
(As to how to get around it... I can't say without more insight into what you are trying to do, unfortunately.)
Upvotes: 5