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