Skip to content

Instantly share code, notes, and snippets.

@yasaichi
Last active May 21, 2016 04:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yasaichi/6aa3b1a9f4de353c4605a0202ba64df8 to your computer and use it in GitHub Desktop.
Save yasaichi/6aa3b1a9f4de353c4605a0202ba64df8 to your computer and use it in GitHub Desktop.
draft of okuribito
require "yaml"
require "active_support"
require "active_support/core_ext"
config = YAML.load_file("okuribito.yml")
class Okuribito
CLASS_METHOD_SYMBOL = "."
INSTANCE_METHOD_SYMBOL = "#"
PATTERN = /\A(?<symbol>[#{CLASS_METHOD_SYMBOL}#{INSTANCE_METHOD_SYMBOL}])(?<method_name>.+)\z/
module PrependedModule
def prepended(klass)
klass.singleton_class.class_exec(module_for_class_methods) { |mod| prepend(mod) }
end
def module_for_class_methods
@module_for_class_methods ||= Module.new
end
end
PrependedModule.freeze
def initialize(klass, &block)
raise unless block_given?
@klass = klass
@block = block
@prepended_module = Module.new.extend(PrependedModule)
end
def apply
@klass.prepend(@prepended_module)
end
def check(target_method)
return unless md = PATTERN.match(target_method)
symbol, method_name = md[:symbol], md[:method_name].to_sym
case symbol
when CLASS_METHOD_SYMBOL
return unless @klass.respond_to?(method_name)
check_class_method(method_name)
when INSTANCE_METHOD_SYMBOL
return unless @klass.instance_methods.include?(method_name)
check_instance_method(method_name)
end
end
private
def add_check_method_to_module(method_name, mod)
mod.module_exec(@block) do |block|
define_method(method_name) do |*args|
super(*args)
block.call
end
end
end
def check_class_method(method_name)
add_check_method_to_module(method_name, @prepended_module.module_for_class_methods)
end
def check_instance_method(method_name)
add_check_method_to_module(method_name, @prepended_module)
end
end
class Foo
def self.bar(a, b = 1, *args, c: 2)
puts ".bar"
end
def baz
puts "#baz"
end
end
config.each do |class_name, target_methods|
okuribito = Okuribito.new(class_name.constantize) do
puts "logging"
end
target_methods.each do |target_method|
okuribito.check(target_method)
end
okuribito.apply
end
Foo.bar(0)
Foo.new.baz
p Foo.instance_methods - Object.instance_methods
p Foo.singleton_class.instance_methods - Class.instance_methods
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment