#!/usr/bin/env ruby
# usage:
# sync [options] CONNECTOR [connector_args]
# examples:
# script/sync csv /path/to/people.csv /path/to/families.csv
# script/sync coms /path/to/comsdata
# multisite example:
# script/sync -s "Site 1" csv /path/to/people.csv /path/to/families.csv
MAX_ERRORS = 10
require 'optparse'
options = {}
parser = OptionParser.new do |opts|
connectors = Dir[File.join(File.dirname(__FILE__), '../lib/connectors/*.rb')].to_a.map { |f| File.split(f).last.split('.').first }.select { |c| !%w(base test example).include? c }
opts.banner = "Usage: script/sync [options] CONNECTOR [connector_args]\nAvailable Connectors: #{connectors.join(', ')}"
opts.on("-s", '--site "Site Name"', "specify site name (if multisite enabled)") do |val|
options[:site] = val
end
opts.on("-e", '--environment production', "specify environment (development, production)") do |val|
options[:environment] = val
end
end
parser.parse!
unless connector_name = ARGV[0]
puts parser.help
exit
end
args = ARGV[1..-1]
RAILS_ENV = options[:environment]
require File.dirname(__FILE__) + '/../config/environment'
require RAILS_ROOT + "/lib/connectors/#{connector_name}"
logger = RAILS_DEFAULT_LOGGER
logger.info "Initializing Sync..."
connector = eval(connector_name.capitalize+'Connector').new(*args)
unless last_update = Date.parse(ActiveRecord::Base.connection.select_one("SELECT last_update FROM sync_info")['last_update']).to_time rescue nil
ActiveRecord::Base.connection.delete("DELETE FROM sync_info")
ActiveRecord::Base.connection.insert("INSERT INTO sync_info (last_update) values (NULL)")
last_update = Date.new(1970, 1, 1).to_time
end
update_time = Time.now.strftime '%Y-%m-%d %H:%M'
error_count = 0
if Setting.get(:features, :multisite)
Site.current = Site.find_by_name(options[:site])
else
Site.current = Site.find(1)
end
logger.info "Syncing people data..."
connector.each_person(last_update) do |person|
begin
p = Person.find_by_legacy_id(person[:legacy_id]) || Person.new(:legacy_id => person[:legacy_id])
if p.email_changed?
if person[:email] != p.email
person.delete(:email)
else
person[:email_changed] = false
end
end
[:mobile_phone, :work_phone, :fax].each { |a| person[a] = person[a] ? person[a].to_s.scan(/\d/).join('').to_i : nil }
p.update_attributes!(person)
rescue => e
logger.error e
error_count += 1
if error_count > MAX_ERRORS
raise "Too many errors. Check the log. Last error was:\n#{e}"
end
end
end
logger.info "Syncing family data..."
connector.each_family(last_update) do |family|
begin
f = Family.find_by_legacy_id(family[:legacy_id]) || Family.new(:legacy_id => family[:legacy_id])
family[:home_phone] = family[:home_phone] ? family[:home_phone].to_s.scan(/\d/).join('').to_i : nil
f.update_attributes!(family)
Person.update_all "family_id = #{f.id}", "legacy_family_id = #{f.legacy_id}"
rescue => e
logger.error e
error_count += 1
if error_count > MAX_ERRORS
raise "Too many errors. Check the log. Last error was:\n#{e}"
end
end
end
logger.info "Purging data..."
Person.destroy_all "legacy_id not in (#{connector.people_ids.join(',')})"
Family.destroy_all "legacy_id not in (#{connector.family_ids.join(',')})"
Person.destroy_all "(select count(*) from families where id=people.family_id) = 0"
logger.info "Recording update details..."
ActiveRecord::Base.connection.update("UPDATE sync_info SET last_update = '#{update_time}'")
logger.info "Finished Sync."