Skip to content

Instantly share code, notes, and snippets.

@dsalahutdinov
Last active August 29, 2015 14:02
Show Gist options
  • Save dsalahutdinov/21a7260657ea4f4fe5dd to your computer and use it in GitHub Desktop.
Save dsalahutdinov/21a7260657ea4f4fe5dd to your computer and use it in GitHub Desktop.
Wrapper оборачивает вызовы методов вызовами before- и after-методов
# wrap_method оборачивает вызовы методов вызовами before- и after-методов
# Возможно множественная обертка, в ходе которой образуется method-chain
module Wrappable
class WrapperOptions
attr_reader :before_callback, :after_callback
def initialize(&block)
instance_eval(&block)
end
def before(method_name)
@before_callback = method_name
end
def after(method_name)
@after_callback = method_name
end
end
def wrap_method(method_name, &block)
@wrap_count = @wrap_count.nil? ? 0 : @wrap_count + 1
old_method_name = "#{method_name}_wrappable_#{@wrap_count}"
wrapper_options_hash = instance_variable_get("@wrapper_options")
instance_variable_set("@wrapper_options", wrapper_options_hash = {}) if (wrapper_options_hash.nil?)
wrapper_options_hash[old_method_name] = WrapperOptions.new(&block)
alias_method old_method_name, method_name
define_method(method_name) do
wrapper_options = self.class.instance_variable_get("@wrapper_options")[old_method_name]
send(wrapper_options.before_callback) unless wrapper_options.before_callback.nil?
send(old_method_name)
send(wrapper_options.after_callback) unless wrapper_options.after_callback.nil?
end
end
end
class My
extend(Wrappable)
def target_method
puts "puts target_method"
end
def before1
puts "before1"
end
def before2
puts "before2"
end
def after1
puts "after1"
end
def after2
puts "after2"
end
wrap_method :target_method do
before :before1
after :after1
end
wrap_method :target_method do
before :before2
after :after2
end
end
My.new.target_method
# => before2
# => before1
# => puts target_method
# => after1
# => after2
# злоумышленники случайно или нет перезаписали локальную переменную
My.instance_variable_set("@wrapper_options", nil)
My.new.target_method
# NoMethodError: undefined method `[]' for nil:NilClass
@dsalahutdinov
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment