Skip to content

Instantly share code, notes, and snippets.

@seven1m
Last active March 22, 2016 01:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seven1m/1cd2a73652a68bdb83a1 to your computer and use it in GitHub Desktop.
Save seven1m/1cd2a73652a68bdb83a1 to your computer and use it in GitHub Desktop.
Terminal script to sync data with OneBody using a CSV file
#!/usr/bin/env ruby
#
# NOTE: Your version of OneBody must be 3.5.0 or higher for this to work.
#
# This is a very simple script you can use to automate syncing of data with OneBody.
# To use, first:
#
# gem install rest-client
#
# Then, edit the USER_EMAIL, USER_KEY, and URL constants just below. To get your USER_KEY,
# you'll need to set a 50-character key on your OneBody Person record like this:
#
# ssh server
# cd /var/www/onebody
# bundle exec rails console
# p = Person.find(1) # your id goes here
# p.api_key = SecureRandom.hex(25) # 25 hex digits equals 50 characters
# p.save
#
# Finally, run the script:
#
# ruby onebody_import.rb path/to/file.csv
#
# Make sure your CSV has headings that EXACTLY match the attributes that OneBody expects.
# To see a list of those attributes, start a CSV import from the UI and take note of the
# attributes available for matching there.
#
# It is highly recommended you use the legacy_id and legacy_family_id columns for matching.
# Doing this will ensure records are always matched properly and make your life much simpler.
USER_EMAIL = 'you@example.com'
USER_KEY = 'abcdef1234567890abcdef1234567890abcdef1234567890ab'
URL = 'http://members.mychurch.com'
IMPORT_SETTINGS = {
match_strategy: 'by_id_only', # other options are by_name, by_contact_info, by_name_or_contact_info
create_as_active: '0', # assuming you'll use a column in your CSV called "status" to set this
overwrite_changed_emails: '0' # set to '1' if you want to always blow away changed email addresses
}
require 'rest-client'
require 'cgi'
require 'csv'
require 'json'
def full_url(url, path = '')
url.sub(/https?:\/\//, "\\0#{CGI.escape(USER_EMAIL)}:#{USER_KEY}@") + path
end
unless (filename = ARGV.first)
puts "You must specify the path to your csv file"
exit(1)
end
data = File.read(filename, encoding: 'ASCII-8BIT')
headings = CSV.parse(data)[0]
puts 'uploading file'
RestClient.post(full_url(URL, '/admin/imports'), { file: File.open(filename) }) do |response|
location = full_url(response.headers[:location]) rescue fail(response)
puts 'parsing file'
begin
sleep 1
resp = JSON.parse(RestClient.get(location + '.json'))
print " #{resp['row_progress']}%\r"
end while %w(pending parsing).include?(resp['status'])
fail resp['error_message'] if resp['status'] == 'errored'
puts 'executing import'
settings = IMPORT_SETTINGS.merge(
mappings: headings.each_with_object({}) { |k, h| h[k] = k }
)
RestClient.patch(location, status: 'matched', import: settings, dont_preview: '1') do |response|
fail response unless response.headers[:location]
location = full_url(response.headers[:location]) + '.json'
begin
sleep 1
resp = JSON.parse(RestClient.get(location))
print " #{resp['row_progress']}%\r"
end while %w(previewed active).include?(resp['status'])
fail resp['error_message'] if resp['status'] == 'errored'
puts ' 100%'
puts response.headers[:location]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment