lib/syncify/sync.rb in syncify-0.1.5 vs lib/syncify/sync.rb in syncify-0.1.6

- old
+ new

@@ -9,16 +9,18 @@ object :callback, class: Proc, default: nil symbol :remote_database attr_accessor :identified_records + attr_accessor :has_and_belongs_to_many_associations validate :id_xor_where_present? def execute puts 'Identifying records to sync...' @identified_records = Set[] + @has_and_belongs_to_many_associations = {} remote do initial_query.each do |root_record| identify_associated_records(root_record, normalized_associations(association)) end @@ -92,21 +94,62 @@ identified_records.merge records print_status records.each do |record| associations.each do |association, nested_associations| - traverse_associations(record.__send__(association), nested_associations) + if is_through_association?(record, association) + traverse_associations( + record.__send__( + record.class.reflect_on_association(association).through_reflection.name + ), + associations + ) + else + associated_records = record.__send__(association) + + if is_has_and_belongs_to_many_association?(record, association) + cache_has_and_belongs_to_many_association(record, association, associated_records) + end + + traverse_associations(associated_records, nested_associations) + end end end end + def cache_has_and_belongs_to_many_association(record, association, associated_records) + has_and_belongs_to_many_associations[record] ||= {} + has_and_belongs_to_many_associations[record][association] = Array(associated_records) + end + + def is_has_and_belongs_to_many_association?(record, association) + record.class.reflect_on_association(association).class == + ActiveRecord::Reflection::HasAndBelongsToManyReflection + end + + def is_through_association?(record, association) + record.class.reflect_on_association(association).class == + ActiveRecord::Reflection::ThroughReflection + end + def sync_records ActiveRecord::Base.connection.disable_referential_integrity do classify_identified_instances.each do |class_name, new_instances| puts "Syncing #{new_instances.size} #{class_name} objects" clazz = Object.const_get(class_name) clazz.where(id: new_instances.map(&:id)).delete_all clazz.import(new_instances, validate: false) + end + + has_and_belongs_to_many_associations.each do |record, associations| + associations.each do |association, associated_records| + local_record = record.class.find(record.id) + local_associated_records = associated_records.map do |associated_record| + associated_record.class.find(associated_record.id) + end + local_record.__send__(association) << local_associated_records + local_record.save + end end end end def classify_identified_instances