Skip to content

Instantly share code, notes, and snippets.

@patrick99e99
Created April 27, 2010 21:46
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 patrick99e99/381384 to your computer and use it in GitHub Desktop.
Save patrick99e99/381384 to your computer and use it in GitHub Desktop.
class Vcard < ActiveRecord::Base
def import
@card = Vpim::Vcard.decode(self.data).first
get_data
find_contact
if @contact
update_contact
else
create_contact
end
process_associations
end
private
def update_contact
@contact.update_attributes(contact_attributes)
end
def contact_attributes
{:url => @url,
:notes => @notes,
:birthday => @birthday}
end
def find_contact
@card = Vpim::Vcard.decode(self.data).first
[find_by_emails, find_by_phones].each do |method|
contact_found = method
return if contact_found
end
end
def find_by_emails
emails = @card.emails.map {|e| remove_newlines(e.to_s.downcase)}
email = Email.find_by_address(emails)
@contact = email.contact if email
end
def find_by_phones
phones = @card.telephones.map {|p| remove_newlines(p)}
phone = Phone.find_by_number(phones)
@contact = phone.contact if phone
end
def create_contact
@contact = Contact.create(contact_attributes.merge(:first_name => @first_name,
:last_name => @last_name))
end
def process_associations
card_emails
card_phones
card_addresses
card_photo
end
def get_data
@first_name = @card.name.given.blank? ? nil : remove_newlines(@card.name.given.capitalize)
@last_name = @card.name.family.blank? ? nil : remove_newlines(@card.name.family.capitalize)
@first_name = @card.name.fullname if (@first_name.nil? && @last_name.nil? && !@card.name.fullname.blank?)
@birthday = @card.birthday.blank? ? nil : @card.birthday
@url = @card.url.blank? ? nil : remove_newlines(@card.url.uri.gsub("\\",""))
@notes = @card.note.blank? ? nil : remove_newlines(@card.note)
end
def card_addresses
street_numbers = @contact.addresses.map(&:street_1).map(&:numbers_only)
@card.addresses.each do |@address|
# don't bother saving the address if there is no region (state)
# assume that if the contact currently has an address with the same numbers that this address is already stored
unless @address.region.blank? || street_numbers.include?(@address.street.numbers_only)
@country = get_country || Country.find_by_name("United States")
region = get_region
next if region.nil?
# labels retrieved from the vcard are only home or work.. custom does not work.
@contact.addresses << Address.create(:country_id => @country.id,
:region_id => region.id,
:street_1 => remove_newlines(@address.street),
:street_2 => remove_newlines(@address.pobox),
:city => remove_newlines(@address.locality),
:postal_code => remove_newlines(@address.postalcode),
:label => get_label(@address))
end
end
end
def get_country
if !@address.country.blank?
card_country = @address.country.gsub(".","")
countries = Country.all
country_attributes = [:name, :official_name, :alpha_2_code, :alpha_3_code]
find_in_list(countries, country_attributes, card_country)
end
end
def get_region
# best way I could deal with nev. => nev
card_region = (@address.region.last == "." ? @address.region.chop : @address.region)
regions_for_country = Region.find_all_by_country_id(@country.id)
region_attributes = [:name, :abbreviation, :abbrev2, :abbrev3]
find_in_list(regions_for_country, region_attributes, card_region)
end
def find_in_list(records, attributes, to_find)
# a better way of doing Country.all.find {|c| [c.name, c.official_name].compact.map(&:downcase).include?(to_find.downcase) }
records.find {|r| attributes.map{|a| r.send(a)}.compact.map(&:downcase).include?(to_find.downcase) }
end
def card_phones
@card.telephones.each do |phone|
# phone is something like: #<Vpim::Vcard::Telephone: "123-456-7890", pref, work
# doing phone.to_s will extract just the number
unless @contact.phones.map(&:number).map(&:numbers_only).include?(phone.to_s.numbers_only)
# labels retrieved from the vcard are only home or work.. custom does not work.
@contact.phones << Phone.create(:label => get_label(phone), :number => remove_newlines(phone.to_s))
end
end
end
def card_emails
@card.emails.each do |email|
# email is something like: #<Vpim::Vcard::Email: "test@yahoo.com", pref, home
# doing email.to_s will extract just the email address
unless @contact.emails.map(&:address).map(&:downcase).include?(email.to_s.downcase)
# labels retrieved from the vcard are only home or work.. custom does not work.
@contact.emails << Email.create(:label => get_label(email), :address => remove_newlines(email.to_s.downcase))
end
end
end
def card_photo
unless @card.photos.size.zero?
if @contact.photo.nil?
photo_album = PhotoAlbum.find_or_create_by_name_with_access_level('users', 'admin')
access = AccessLevel.find_by_name('public')
@contact.photo = Photo.create(:image_file_string => @card.photos.first,
:contact_id => @contact.id,
:name => "#{@contact.first_name} #{@contact.last_name}".strip,
:description => "User photo",
:access_level_id => access.id,
:photo_album_id => photo_album.id,
:server_format => "JPEG")
end
end
end
def get_label(obj)
obj.location.blank? ? nil : remove_newlines(obj.location).gsub("-","").strip
end
def remove_newlines(obj)
obj.to_s.gsub("\n", " ")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment