module Spider; module Model module Synchronized def self.extended(model) model.extend(ClassMethods) end def self.included(model) model.extend(ClassMethods) end module ClassMethods def synchronizing(name=nil) return @synchronizing unless name @synchronizing = name with_mapper do def before_save(obj, mode) return super unless @model.synchronizing obj = get_synchronized(obj) super(obj, mode) end def get_synchronized(obj) @model.elements_array.select{ |el| obj.element_has_value?(el) && obj.model.mapper.have_references?(el) && el.model? && el.model.is_a?(Synchronized) && el.model.synchronizing == @model.synchronizing }.each do |el| el_objects = obj.get(el) el_objects = [el_objects] unless (el_objects.is_a?(Enumerable)) new_el_objects = [] el_objects.each do |el_object| cond = Condition.new el.model.primary_keys.each do |k| cond[el.model.synchronization_key(@model.synchronizing, k)] = el_object.get(k) end res = el.model.find(cond) raise SynchronizationException, "The synchronized object was not unique" if res.length > 1 if (res.length == 1) el.model.primary_keys.each do |k| new_el_objects << res[0] end end end if !el.multiple? obj.set(el, new_el_objects[0]) else obj.set(el, new_el_objects) end end @model.primary_keys.each do |k| if (k.autogenerated? && !k.attributes[:no_sync_map]) obj.set(@model.synchronization_key(@model.synchronizing, k), obj.get(k)) obj.set(k.name, nil) end end return obj end end end def synchronization(name) @synchronizations ||= [] @synchronizations << name self.primary_keys.each do |k| element(synchronization_key(name, k), k.type) if k.autogenerated? && !k.attributes[:no_sync_map] end end def synchronization_key(synchronization, key) return key.name unless key.autogenerated? && !key.attributes[:no_sync_map] return :"sync_#{synchronization}_#{key.name}" end end class SynchronizationException < RuntimeError end end end; end