I have a background in Node Js and I am new to Ruby, Pardon me If this question is a noob. I have 3 classes like this.
class Babylon::Metric::Counter < Babylon::Metric
protected
def record
# some code here
end
end
class Babylon::Metric::Gauge < Babylon::Metric
protected
def record
# some code here
end
end
and the parent class of these is
class Babylon::Metric
class ArgumentError < ArgumentError; end
def initialize name, category, amount
@name = name
@category = category
@amount = amount
end
def self.call name:, category:, amount:
new(name, category, amount).()
end
# What is it doing here exactly is it calling Counter or Gauge record method from here,
# based on valid method returns true or false?
def call
valid? ? record : notify
rescue => e
begin
raise Babylon::Error, e.inspect
rescue Babylon::Error => e
Babylon::Event.(event: "babylon.error", error: e)
end
end
def valid?
# do validation
end
def notify
# do some stuff
end
end
I think that the call method is able to in turn call Counter class and Gauge class record methods If the valid method returns true, But I don't know how it can call as these are protected members ?.
CodePudding user response:
If you initialize the parent class and call the call
or record
method on it, you will get a NoMethodError
as you would expect. The trick is, that all of the methods of the parent are available in the children as well.
That means that if you initiate a child class and call record
on it, the record method on the child class is called exactly as expected.
But also, if you call the call
method on the child class, it will use the implementation from the parent, but in the context of the child class, meaning that the record method called in it, will be available and no error is raised.
CodePudding user response:
In Ruby, protected
methods can only be called with either:
- An implicit receiver (i.e.
say_hello
instead of e.g.self.say_hello
) - An explicit receiver in the same object family (self and descendants)
In the parent class, you can see that record
is called with an implicit receiver, which means that the method can be either public, protected, or private.
For example:
class Foo
def say_hello
whisper_hello # implicit receiver
end
end
class Bar < Foo
private # protected would work as well in this example
def whisper_hello
puts "(hello)"
end
end
In this example, Foo.new.say_hello
will fail because whisper_hello
isn't defined in the parent class (in other words you could say that Foo
is an abstract class); but Bar.new.say_hello
will work just fine.