require 'securerandom' module PopulateMe module DocumentMixins module Callbacks def exec_callback name name = name.to_sym return self if self.class.callbacks[name].nil? self.class.callbacks[name].each do |job| if job.respond_to?(:call) self.instance_exec name, &job else meth = self.method(job) meth.arity==1 ? meth.call(name) : meth.call end end self end def recurse_callback name nested_docs.each do |d| d.exec_callback name end end def ensure_id if self.id.nil? self.id = SecureRandom.hex end self end def ensure_not_new; self._is_new = false; end def ensure_position self.class.fields.each do |k,v| if v[:type]==:position return unless self.__send__(k).nil? values = if v[:scope].nil? self.class.admin_distinct k else self.class.admin_distinct(k, query: { v[:scope] => self.__send__(v[:scope]) }) end val = values.empty? ? 0 : (values.max + 1) self.set k => val end end self end def ensure_delete_related self.class.relationships.each do |k,v| if v[:dependent] klass = WebUtils.resolve_class_name v[:class_name] next if klass.nil? klass.admin_find(query: {v[:foreign_key]=>self.id}).each do |d| d.delete end end end end def ensure_delete_attachments self.class.fields.each do |k,v| if v[:type]==:attachment self.attachment(k).delete_all end end end def ensure_new; self._is_new = true; end def self.included(base) base.extend(ClassMethods) base.class_eval do [:save,:create,:update,:delete].each do |cb| before cb, :recurse_callback after cb, :recurse_callback end before :create, :ensure_id before :create, :ensure_position after :create, :ensure_not_new after :save, :snapshot before :delete, :ensure_delete_related before :delete, :ensure_delete_attachments after :delete, :ensure_new end end module ClassMethods attr_accessor :callbacks def register_callback name, item=nil, options={}, &block name = name.to_sym if block_given? options = item || {} item = block end self.callbacks ||= {} self.callbacks[name] ||= [] if options[:prepend] self.callbacks[name].unshift item else self.callbacks[name] << item end end def before name, item=nil, options={}, &block register_callback "before_#{name}", item, options, &block end def after name, item=nil, options={}, &block register_callback "after_#{name}", item, options, &block end end end end end