./lib/common/class_callbacks.rb in lux-fw-0.2.3 vs ./lib/common/class_callbacks.rb in lux-fw-0.5.32

- old
+ new

@@ -1,64 +1,47 @@ -# frozen_string_literal: true +# Rails style callbacks -# in some class -# ClassCallbacks.define self, :before, :after -# -# then to execute -# instance_object = SomeClass.new -# ClassCallbacks.execute(instance_object, :before) -# +# for controllers, execute from AppController to MainController +# class_callback :before # before do -# ... +# ... # end -# -# logic is very simple, keep all pointers to all blocks in one class, resolve and execute as needed -# we keep methods and ponters in different hashes to allow hot reload while development +# before :method_name +# instance = new +# instance.class_callback :before, +# instance.class_callback :before, arg -module ClassCallbacks - extend self - - @@methods = {} - @@pointers = {} - - def add klass, unique_id, action, method - klass = klass.to_s - key = Crypt.sha1(unique_id) - - @@pointers[key] = method - - @@methods[klass] ||= {} - @@methods[klass][action] ||= [] - @@methods[klass][action].tap { |it| it.push(key) unless it.include?(key) } +class Object + def class_callback name, arg=nil + Object.class_callback name, self, arg end - def execute instance_object, action, object=nil - object ? instance_object.send(action, object) : instance_object.send(action) + def self.class_callback name, context=nil, arg=nil + ivar = "@ccallbacks_#{name}" - # execute for self and parents - instance_object.class.ancestors.reverse.map(&:to_s).each do |name| - next if name == 'Object' - next unless actions = @@methods.dig(name, action) + unless context + define_singleton_method(name) do |method_name=nil, &block| + ref = caller[0].split(':in ').first - for el in actions.map { |o| @@pointers[o] } - if el.kind_of?(Symbol) - object ? instance_object.send(el, object) : instance_object.send(el) - else - object ? instance_object.instance_exec(object, &el) : instance_object.instance_exec(&el) - end + self.instance_variable_set(ivar, {}) unless instance_variable_defined?(ivar) + self.instance_variable_get(ivar)[ref] = method_name || block end - end - end - def define(klass, *args) - args.each do |action| - klass.class_eval %[ - def #{action}(duck=nil) - end + else + list = context.respond_to?(:const_missing) ? context.ancestors : context.class.ancestors + list = list.slice 0, list.index(Object) if list.index(Object) - def self.#{action}(proc=nil, &block) - ClassCallbacks.add(self, caller[0], :#{action}, proc || block) + list.reverse.each do |klass| + if klass.instance_variable_defined?(ivar) + mlist = klass.instance_variable_get(ivar).values + mlist.each do |m| + if m.is_a?(Symbol) + context.send m + else + context.instance_exec arg, &m + end + end end - ] + end end end end