Last active
July 25, 2018 16:35
-
-
Save we4tech/cf4ebd7963183153dfd78570f7ae52a6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'byebug' | |
module MethodMetadata | |
def self.included(base) | |
base.extend ClassMethods | |
end | |
module ClassMethods | |
def method_advice(data = {}) | |
lineno = caller_locations(1, 1).first.lineno | |
register(lineno, data) | |
end | |
def register(lineno, data) | |
method_metadata[lineno] = data | |
end | |
def method_metadata_at(lineno) | |
method_metadata[lineno] | |
end | |
def method_metadata | |
@method_metadata ||= {} | |
end | |
def method_advices | |
@method_advices ||= {} | |
end | |
def execute_with_advice(advice) | |
puts "Executing advices #{advice}" | |
## | |
# Implement your advices here | |
# | |
advice.each do |advice_type, args| | |
case advice_type | |
when :required_envvar | |
args.each { |key| ENV.fetch(key) } | |
end | |
end | |
yield | |
end | |
def attach_advice_with_singleton_method(method_name, advice) | |
method_advices[method_name] = advice | |
class_eval(<<-CODE, __FILE__, __LINE__ + 1) | |
class << self | |
alias_method :#{method_name}_without_advice, :#{method_name} | |
def #{method_name}(*args) | |
advice = method_advices.fetch(:#{method_name}, nil) | |
execute_with_advice(advice) { #{method_name}_without_advice(*args) } if advice | |
end | |
end | |
CODE | |
end | |
# FYI: Needs to implement method_added in order to support instance methods | |
def singleton_method_added(method_name) | |
return if method_name.to_s.match(/_without_advice$/) | |
advice = method_metadata_at(method(method_name).source_location.last - 1) | |
attach_advice_with_singleton_method(method_name, advice) if advice | |
end | |
end | |
end | |
module Hello | |
include MethodMetadata | |
# FYI, currently it has to be just before the method name, but you can extend this method implementation to setup | |
# as per your desire range - :singleton_method_added | |
# | |
method_advice required_envvar: %w[HELLO WORLD] | |
def self.connection(arg1, arg2) | |
puts 'Connection' | |
puts method_metadata.inspect | |
end | |
def self.hi_there | |
puts 'Hi there' | |
end | |
def hello | |
end | |
end | |
Hello.connection(1, 2) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment