Reputation: 11
I am building client for Asterisk Manager (AMI), which sending back "events" (strings in key-value format). Depending on event type the keys are different. Some known would be defined similar as a property
, but I also want to access everything else similar way (I need only getter).
Below is example and I am confused about forward_missing_to
, to fetch hash value (i.e. e.foo => e.data["foo"]
and e.foo? => e.data["foo"]?
class Event
@data = Hash(String,String).new
def initialize(data : Hash(String, String))
@data.merge! data
end
# known field (event), here I could apply various validations etc.
def event=(@name : String)
@data["name"] = @name
end
def event : String
@data["name"].not_nil!
end
# Confusing about this:
forward_missing_to @data
end
Example of usage:
e = Event.new({"event" => "Test", "foo" => "bar"})
p e.event # => "Test" (only this works)
p e.foo # => expecting to get "bar"
p e.unknown # => should throw Unhandled exception: Missing hash key: "unknown" (KeyError)
p e.unknown? # => nil
Upvotes: 1
Views: 85
Reputation: 2926
forward_missing_to
just means this:
e = Event.new({"event" => "Test", "foo" => "bar"})
# Same as invoking `foo` on the @data instance variable
# because you said forward_missing_to @data
e.foo
It doesn't mean invoking ["foo"]
on @data
.
You can do it like this:
macro method_missing(call)
{% if call.args.empty? && !call.named_args %}
@data[{{call.name.stringify}}]
{% else %}
{% raise "undefined method '#{call.name}' for #{@type}" %}
{% end %}
end
However, I wouldn't advise using method_missing
, mainly because it might be eventually removed from the language (together with forward_missing_to
).
Upvotes: 4