Skip to content

Instantly share code, notes, and snippets.

@jaymcgavren
Last active February 5, 2024 05:03
Show Gist options
  • Save jaymcgavren/d0159038f7de3d353e9ac6311e7d9ae3 to your computer and use it in GitHub Desktop.
Save jaymcgavren/d0159038f7de3d353e9ac6311e7d9ae3 to your computer and use it in GitHub Desktop.
A Ruby example of prepending a proxy module to a class to intercept method calls.
module MethodBroadcaster
def broadcast_calls_to(*method_names)
proxy = Module.new
method_names.each do |method_name|
proxy.define_method(method_name) do |*args, **kwargs, &block|
arg_strings = args.map(&:inspect)
kwarg_strings = kwargs.map{|k, v| "#{k}: #{v.inspect}" }
all_arg_strings = arg_strings + kwarg_strings
puts "#{method_name}(#{all_arg_strings.join(', ')})"
super(*args, **kwargs, &block)
end
end
self.prepend proxy
end
end
class Foo
extend MethodBroadcaster
def positional_arguments(arg1, arg2)
p [arg1, arg2]
end
def keyword_arguments(foo:, bar: "bar!")
p [foo, bar]
end
def positional_and_keyword_arguments(arg1, arg2, foo:, bar: "bar!")
p [arg1, arg2, foo, bar]
puts yield("block arg") if block_given?
end
broadcast_calls_to :positional_arguments, :keyword_arguments, :positional_and_keyword_arguments
end
foo = Foo.new
foo.positional_arguments("arg1!", "arg2!")
# => positional_arguments("arg1!", "arg2!")
# => ["arg1!", "arg2!"]
foo.keyword_arguments(foo: "foo!")
# => keyword_arguments(foo: "foo!")
# => ["foo!", "bar!"]
foo.positional_and_keyword_arguments("arg1!", "arg2!", foo: "foo!", bar: "bar!!")
# => positional_and_keyword_arguments("arg1!", "arg2!", foo: "foo!", bar: "bar!!")
# => ["arg1!", "arg2!", "foo!", "bar!!"]
foo.positional_and_keyword_arguments("arg1!", "arg2!", foo: "foo!") { |block_arg| "block got #{block_arg}!" }
# => positional_and_keyword_arguments("arg1!", "arg2!", foo: "foo!")
# => ["arg1!", "arg2!", "foo!", "bar!"]
# => block got block arg!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment