module RubyInterface::ClassMethods
Public Instance Methods
defines(*args)
click to toggle source
# File lib/ruby_interface.rb, line 19 def defines(*args) @methods_to_define ||= [] @methods_to_define += args end
track_required_methods(child)
click to toggle source
# File lib/ruby_interface.rb, line 24 def track_required_methods(child) missing_methods = @methods_to_define - child.instance_methods(false) return if missing_methods.empty? raise_class_definition_error child, missing_methods end
Private Instance Methods
anonymous_class_definition(child)
click to toggle source
# File lib/ruby_interface.rb, line 48 def anonymous_class_definition(child) define_class_hook child redefine_eval_and_exec child end
define_class_hook(child)
click to toggle source
# File lib/ruby_interface.rb, line 53 def define_class_hook(child) klass = self child.define_singleton_method :anonymous_class_defined do klass.track_required_methods(child) revert_eval_and_exec end end
named_class_definition(child)
click to toggle source
# File lib/ruby_interface.rb, line 83 def named_class_definition(child) trace = TracePoint.new(:end) do |point| next unless point.self == child trace.disable track_required_methods child end trace.enable end
raise_class_definition_error(child, missing_methods)
click to toggle source
# File lib/ruby_interface.rb, line 34 def raise_class_definition_error(child, missing_methods) message = "Expected #{child.name || 'anonymous class'} to define " message << missing_methods.map { |method| "##{method}" }.join(', ') raise NotImplementedError, message rescue NotImplementedError => exception directory = File.dirname(__FILE__) better_backtrace = exception.backtrace.drop_while do |element| element.include? directory end exception.set_backtrace better_backtrace raise exception end
redefine_eval_and_exec(child)
click to toggle source
# File lib/ruby_interface.rb, line 61 def redefine_eval_and_exec(child) klass = self [:class_exec, :class_eval].each do |method| old_method = "_old_#{method}".to_sym child.singleton_class.send(:alias_method, old_method, method) child.define_singleton_method method do |*args, &block| send old_method, *args, &block klass.track_required_methods(child) revert_eval_and_exec end end end
revert_eval_and_exec()
click to toggle source
# File lib/ruby_interface.rb, line 76 def revert_eval_and_exec [:class_exec, :class_eval].each do |method| old_method = "_old_#{method}".to_sym singleton_class.send(:alias_method, method, old_method) end end