contact_sport 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in contact_sport.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Andy Stewart
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # ContactSport
2
+
3
+ Simple importing of contacts from Outlook and vCard.
4
+
5
+ `ContactSport` provides a simple way to read contacts exported from Outlook or vCard files. It came about because I needed to enable users of a webapp to import contacts from their existing desktop address books and email clients.
6
+
7
+ Outlook contacts should be exported as [Comma Separated Values (Windows)][outlook].
8
+
9
+ vCards can be exported from most other address books or email clients. Here are [instructions for Apple's Address Book][osx].
10
+
11
+
12
+ ## Usage
13
+
14
+ There is precisely one method in the API:
15
+
16
+ Assuming `contacts_file` is the name and path of your contacts file:
17
+
18
+ ```ruby
19
+ ContactSport.contacts(contacts_file)
20
+ ```
21
+
22
+ This returns an array of contacts, where a contact is an object responding to:
23
+
24
+ ```ruby
25
+ :first_name
26
+ :last_name
27
+ :name
28
+ :email
29
+ :url
30
+ :office_phone
31
+ :mobile_phone
32
+ :fax
33
+ :company
34
+ :address1
35
+ :address2
36
+ :city
37
+ :region
38
+ :postcode
39
+ :country
40
+ ```
41
+
42
+ All responses are strings. If a value is not set (e.g. a contact has no fax number) an empty string is returned.
43
+
44
+ Where there are work and home values, e.g. a work phone and a home phone, `ContactSport` will prefer the work phone.
45
+
46
+
47
+ ## Installation
48
+
49
+ $ gem install contact_sport
50
+
51
+ The code requires Ruby 1.9.
52
+
53
+
54
+ ## Intellectual Property
55
+
56
+ Copyright [Andrew Stewart][boss], AirBlade Software Ltd.
57
+
58
+ Released under the MIT licence.
59
+
60
+
61
+ [outlook]: http://office.microsoft.com/en-us/outlook-help/export-contacts-HA101870639.aspx
62
+ [osx]: http://support.apple.com/kb/PH4655
63
+ [contact_csv]: https://github.com/mwhuss/contact_csv
64
+ [contactgems]: https://rubygems.org/search?query=contact
65
+ [boss]: mailto:boss@airbladesoftware.com
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'lib' << 'test'
6
+ t.test_files = FileList['test/*_test.rb']
7
+ t.verbose = true
8
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'contact_sport/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "contact_sport"
8
+ gem.version = ContactSport::VERSION
9
+ gem.authors = ["Andy Stewart"]
10
+ gem.email = ["boss@airbladesoftware.com"]
11
+ gem.description = 'Simple importing of contacts from Outlook and vCard.'
12
+ gem.summary = gem.description
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency 'vcard', '~> 0.2'
21
+
22
+ gem.add_development_dependency 'rake', '~> 0.9.2'
23
+ end
@@ -0,0 +1,8 @@
1
+ require 'ostruct'
2
+
3
+ module ContactSport
4
+
5
+ class Contact < OpenStruct
6
+ end
7
+
8
+ end
@@ -0,0 +1,25 @@
1
+ module ContactSport
2
+ module Encoding
3
+
4
+ # https://github.com/Manfred/Ensure-encoding/blob/master/lib/ensure/encoding.rb
5
+ # https://github.com/oleander/rchardet/blob/master/lib/rchardet/universaldetector.rb
6
+ BYTE_ORDER_MARKS = {
7
+ ::Encoding::UTF_32BE => [0x00, 0x00, 0xfe, 0xff],
8
+ ::Encoding::UTF_32LE => [0xff, 0xfe, 0x00, 0x00],
9
+ ::Encoding::UTF_8 => [0xef, 0xbb, 0xbf],
10
+ ::Encoding::UTF_16BE => [0xfe, 0xff],
11
+ ::Encoding::UTF_16LE => [0xff, 0xfe],
12
+ }
13
+
14
+ FALLBACK_ENCODING = ::Encoding::ISO_8859_1
15
+
16
+ # Guesses the encoding of the given file.
17
+ def self.guess_encoding(file)
18
+ # First look for a byte order mark (BOM).
19
+ first_bytes = IO.read(file, 4).bytes.to_a
20
+ bom = BYTE_ORDER_MARKS.detect { |encoding, bytes| first_bytes[0...bytes.length] == bytes }
21
+ bom ? bom.first : FALLBACK_ENCODING
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,145 @@
1
+ require 'csv'
2
+ require 'contact_sport/contact'
3
+ require 'contact_sport/encoding'
4
+
5
+ module ContactSport
6
+
7
+ # To read an Outlook "Comma Separated Values (Windows)" file we need to guess:
8
+ #
9
+ # * the file's encoding
10
+ # * the column separator
11
+ # * the column headings
12
+ #
13
+ # These all vary by Outlook version, platform, and phase of the moon.
14
+ #
15
+ # Some example contact headings are given here:
16
+ #
17
+ # * http://stackoverflow.com/questions/4847596/what-are-the-csv-headers-in-outlook-contact-export
18
+ # * http://lists.lrug.org/pipermail/chat-lrug.org/2013-February/008474.html
19
+ class OutlookReader
20
+ attr_reader :file, :file_encoding, :column_separator
21
+
22
+ def initialize(file)
23
+ @file = file
24
+ @file_encoding = ContactSport::Encoding.guess_encoding file
25
+ @column_separator = guess_column_separator
26
+ end
27
+
28
+ def contacts
29
+ begin
30
+ @contacts ||= begin
31
+ results = []
32
+ CSV.foreach(file, headers: true,
33
+ col_sep: column_separator,
34
+ encoding: "#{file_encoding.to_s}:UTF-8") do |row|
35
+ # Headers:
36
+ results << Contact.new(
37
+ first_name: first_name(row),
38
+ last_name: last_name(row),
39
+ name: name(row),
40
+
41
+ email: email(row),
42
+ url: web_page(row),
43
+
44
+ company: company(row),
45
+ office_phone: office_phone(row),
46
+ mobile_phone: mobile_phone(row),
47
+ fax: fax(row),
48
+
49
+ address1: street(row),
50
+ address2: street2(row),
51
+ city: city(row),
52
+ region: state(row),
53
+ postcode: postcode(row),
54
+ country: country(row)
55
+ )
56
+ end
57
+ results
58
+ end
59
+ rescue EncodingError => e
60
+ raise ContactSport::EncodingError, e.message
61
+ rescue StandardError => e
62
+ raise ContactSport::FormatError, e.message
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def guess_column_separator
69
+ first_line = File.open file, encoding: "#{file_encoding.to_s}:UTF-8", &:readline
70
+ comma_count = first_line.count ','
71
+ tab_count = first_line.count '\t'
72
+ comma_count > tab_count ? ',' : "\t"
73
+ end
74
+
75
+ def find_first(row, *fields)
76
+ fields.each do |field|
77
+ if result = row[field]
78
+ return result
79
+ end
80
+ end
81
+ EMPTY_FIELD
82
+ end
83
+
84
+ def first_name(row)
85
+ find_first row, 'First Name'
86
+ end
87
+
88
+ def last_name(row)
89
+ find_first row, 'Last Name'
90
+ end
91
+
92
+ def street(row)
93
+ find_first row, 'Business Street', 'Home Street', 'Work Street Address', 'Home Street Address'
94
+ end
95
+
96
+ def street2(row)
97
+ find_first row, 'Business Street 2', 'Home Street 2', 'Work Street Address 2', 'Home Street Address 2'
98
+ end
99
+
100
+ def city(row)
101
+ find_first row, 'Business City', 'Home City', 'Work City'
102
+ end
103
+
104
+ def state(row)
105
+ find_first row, 'Business State', 'Home State', 'Work State'
106
+ end
107
+
108
+ def postcode(row)
109
+ find_first row, 'Business Postal Code', 'Home Postal Code', 'Work Zip', 'Home Zip'
110
+ end
111
+
112
+ def country(row)
113
+ find_first row, 'Business Country', 'Home Country', 'Business Country/Region', 'Work Country/Region', 'Home Country/Region'
114
+ end
115
+
116
+ def fax(row)
117
+ find_first row, 'Business Fax', 'Work Fax', 'Home Fax'
118
+ end
119
+
120
+ def web_page(row)
121
+ find_first row, 'Web Page'
122
+ end
123
+
124
+ def email(row)
125
+ find_first row, 'E-mail Address', 'Email Address 1'
126
+ end
127
+
128
+ def office_phone(row)
129
+ find_first row, 'Work Phone 1', 'Home Phone 1', 'Business Phone', 'Home Phone'
130
+ end
131
+
132
+ def mobile_phone(row)
133
+ find_first row, 'Mobile Phone'
134
+ end
135
+
136
+ def company(row)
137
+ find_first row, 'Company'
138
+ end
139
+
140
+ def name(row)
141
+ [ row['First Name'], row['Last Name'] ].compact.join(' ') || EMPTY_FIELD
142
+ end
143
+ end
144
+
145
+ end
@@ -0,0 +1,97 @@
1
+ require 'vcard'
2
+ require 'contact_sport/contact'
3
+
4
+ module ContactSport
5
+
6
+ class VcardReader
7
+ attr_reader :file
8
+
9
+ def initialize(file)
10
+ @file = file
11
+ end
12
+
13
+ def contacts
14
+ begin
15
+ @contacts ||= Vcard::Vcard.decode(contents).map do |card|
16
+ Contact.new(
17
+ first_name: card.name.given,
18
+ last_name: card.name.family,
19
+ name: card.name.fullname,
20
+
21
+ email: email(card),
22
+ url: url(card),
23
+
24
+ company: company(card),
25
+ office_phone: work_phone(card),
26
+ mobile_phone: mobile_phone(card),
27
+ fax: fax(card),
28
+
29
+ address1: address_first_line(card),
30
+ address2: address_second_line(card),
31
+ city: address(:locality, card),
32
+ region: address(:region, card),
33
+ postcode: address(:postalcode, card),
34
+ country: address(:country, card)
35
+ )
36
+ end
37
+ rescue Vcard::InvalidEncodingError, Vcard::UnsupportedError, Vcard::Unencodeable => e
38
+ raise ContactSport::FormatError, e.message
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def contents
45
+ File.read file
46
+ end
47
+
48
+ def company(card)
49
+ card.org ? card.org.first : EMPTY_FIELD
50
+ end
51
+
52
+ def address(field, card)
53
+ card.address ? card.address.send(field) : EMPTY_FIELD
54
+ end
55
+
56
+ def address_first_line(card)
57
+ if card.address && card.address.street
58
+ card.address.street.split("\n").first
59
+ else
60
+ EMPTY_FIELD
61
+ end
62
+ end
63
+
64
+ def address_second_line(card)
65
+ if card.address && card.address.street
66
+ card.address.street.split("\n")[1..-1].join "\n"
67
+ else
68
+ EMPTY_FIELD
69
+ end
70
+ end
71
+
72
+ def email(card)
73
+ card.email ? card.email.to_s : EMPTY_FIELD
74
+ end
75
+
76
+ def url(card)
77
+ card.url ? card.url.uri.sub('http\\','http') : EMPTY_FIELD
78
+ end
79
+
80
+ def work_phone(card)
81
+ tel = card.telephones.detect { |t| t.location.any? { |l| l =~ /work/i } } || card.telephone
82
+ tel ? tel.to_s : EMPTY_FIELD
83
+ end
84
+
85
+ def mobile_phone(card)
86
+ tel = card.telephones.detect { |t| t.location.any? { |l| l =~ /cell/i } }
87
+ tel ? tel.to_s : EMPTY_FIELD
88
+ end
89
+
90
+ def fax(card)
91
+ fax = card.telephones.detect { |t| t.capability.any? { |c| c =~ /fax/i } }
92
+ fax ? fax.to_s : EMPTY_FIELD
93
+ end
94
+
95
+ end
96
+
97
+ end
@@ -0,0 +1,3 @@
1
+ module ContactSport
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,32 @@
1
+ require "contact_sport/version"
2
+ require 'contact_sport/vcard_reader'
3
+ require 'contact_sport/outlook_reader'
4
+
5
+ module ContactSport
6
+
7
+ # Raised when a contacts file doesn't appear to be Outlook CSV or vCard.
8
+ UnknownProviderError = Class.new RuntimeError
9
+
10
+ # Raised when a contacts file cannot be parsed.
11
+ FormatError = Class.new RuntimeError
12
+
13
+ # Raised when a contacts file is in an unknown encoding.
14
+ EncodingError = Class.new RuntimeError
15
+
16
+ EMPTY_FIELD = ''
17
+
18
+ def self.contacts(file)
19
+ reader(file).contacts
20
+ end
21
+
22
+ private
23
+
24
+ def self.reader(file)
25
+ case File.extname(file)
26
+ when /[.]vcf$/i; VcardReader.new(file)
27
+ when /[.]csv$/i; OutlookReader.new(file)
28
+ else raise UnknownProviderError
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,5 @@
1
+ "Title","First Name","Middle Name","Last Name","Suffix","Company","Department","Job Title","Business Street","Business Street 2","Business Street 3","Business City","Business State","Business Postal Code","Business Country/Region","Home Street","Home Street 2","Home Street 3","Home City","Home State","Home Postal Code","Home Country/Region","Other Street","Other Street 2","Other Street 3","Other City","Other State","Other Postal Code","Other Country/Region","Assistant's Phone","Business Fax","Business Phone","Business Phone 2","Callback","Car Phone","Company Main Phone","Home Fax","Home Phone","Home Phone 2","ISDN","Mobile Phone","Other Fax","Other Phone","Pager","Primary Phone","Radio Phone","TTY/TDD Phone","Telex","Account","Anniversary","Assistant's Name","Billing Information","Birthday","Business Address PO Box","Categories","Children","Directory Server","E-mail Address","E-mail Type","E-mail Display Name","E-mail 2 Address","E-mail 2 Type","E-mail 2 Display Name","E-mail 3 Address","E-mail 3 Type","E-mail 3 Display Name","Gender","Government ID Number","Hobby","Home Address PO Box","Initials","Internet Free Busy","Keywords","Language","Location","Manager's Name","Mileage","Notes","Office Location","Organizational ID Number","Other Address PO Box","Priority","Private","Profession","Referred By","Sensitivity","Spouse","User 1","User 2","User 3","User 4","Web Page"
2
+ "","Bruce","","Wayne",,"Wayne Enterprises",,,"1st Floor","1 High Street",,"London","Middlesex","W1 1AB","United Kingdom",,,,,,,,,,,,,,,,"020 7123 4560","020 7123 4567",,,,,,,,,"07979 797 979",,,,,,,,,,,,,,,,,"b.wayne@example.com","SMTP",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"http://example.com"
3
+ "","James","","Bond",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,""
4
+ "","Clarke","","Kent",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
5
+ ",,,,,,,,,""
Binary file
@@ -0,0 +1,26 @@
1
+ BEGIN:VCARD
2
+ VERSION:3.0
3
+ N:;;;;
4
+ FN:Wayne Enterprises
5
+ ORG:Wayne Enterprises;
6
+ EMAIL;type=INTERNET;type=WORK;type=pref:info@wayneenterprises.com
7
+ X-ABShowAs:COMPANY
8
+ CATEGORIES:Test
9
+ X-ABUID:C9C08B97-1889-4D67-9595-C12482BF3B5F\:ABPerson
10
+ END:VCARD
11
+ BEGIN:VCARD
12
+ VERSION:3.0
13
+ N:Wayne;Bruce;;;
14
+ FN:Bruce Wayne
15
+ ORG:Wayne Enterprises;
16
+ EMAIL;type=INTERNET;type=WORK;type=pref:bruce@wayneenterprises.com
17
+ TEL;type=WORK;type=pref:+44 20 7123 4567
18
+ TEL;type=CELL:07777 999 888
19
+ TEL;type=HOME;type=FAX:+44 20 71234 4560
20
+ item1.ADR;type=WORK;type=pref:;;The Batcave;Gotham;NY;90210;USA
21
+ item1.X-ABADR:gb
22
+ item2.URL;type=pref:www.batman.com
23
+ item2.X-ABLabel:_$!<HomePage>!$_
24
+ CATEGORIES:Test
25
+ X-ABUID:3852D6F6-6DDB-441C-8CE7-6594B0112C3D\:ABPerson
26
+ END:VCARD
@@ -0,0 +1,74 @@
1
+ require 'minitest/autorun'
2
+ require 'test_helper'
3
+ require 'contact_sport'
4
+
5
+ class OutlookReaderTest < MiniTest::Unit::TestCase
6
+
7
+ def test_iso_8859_1_commas
8
+ contacts = ContactSport.contacts fixture('iso_8859_1_commas.csv')
9
+ assert_equal 3, contacts.length
10
+
11
+ contact = contacts.shift
12
+ assert_equal 'Bruce', contact.first_name
13
+ assert_equal 'Wayne', contact.last_name
14
+ assert_equal 'Bruce Wayne', contact.name
15
+ assert_equal 'b.wayne@example.com', contact.email
16
+ assert_equal 'http://example.com', contact.url
17
+ assert_equal '020 7123 4567', contact.office_phone
18
+ assert_equal '07979 797 979', contact.mobile_phone
19
+ assert_equal '020 7123 4560', contact.fax
20
+ assert_equal 'Wayne Enterprises', contact.company
21
+ assert_equal '1st Floor', contact.address1
22
+ assert_equal '1 High Street', contact.address2
23
+ assert_equal 'London', contact.city
24
+ assert_equal 'Middlesex', contact.region
25
+ assert_equal 'W1 1AB', contact.postcode
26
+ assert_equal 'United Kingdom', contact.country
27
+
28
+ contact = contacts.shift
29
+ assert_equal 'James Bond', contact.name
30
+
31
+ contact = contacts.shift
32
+ assert_equal 'Clarke Kent', contact.name
33
+ end
34
+
35
+ def test_utf_16_le_tabs
36
+ contacts = ContactSport.contacts fixture('utf_16_le_tabs.csv')
37
+ assert_equal 6, contacts.length
38
+
39
+ contact = contacts.shift
40
+ assert_equal 'Andrew', contact.first_name
41
+ assert_equal 'Stewart', contact.last_name
42
+ assert_equal 'Andrew Stewart', contact.name
43
+ assert_equal 'andrew@home.de', contact.email
44
+ assert_equal 'http://www.mcdonalds.com/staff/Andrew', contact.url
45
+ assert_equal '4420812345', contact.office_phone
46
+ assert_equal '49123456789', contact.mobile_phone
47
+ assert_equal '', contact.fax
48
+ assert_equal 'McDonalds Corporation', contact.company
49
+ assert_equal '1 Leicester Square', contact.address1
50
+ assert_equal '', contact.address2
51
+ assert_equal 'London', contact.city
52
+ assert_equal '', contact.region
53
+ assert_equal 'WC1A 1AA', contact.postcode
54
+ assert_equal '', contact.country
55
+
56
+ contact = contacts.pop
57
+ assert_equal '', contact.first_name
58
+ assert_equal '', contact.last_name
59
+ assert_equal '', contact.name
60
+ assert_equal 'info@mcdonalds.com', contact.email
61
+ assert_equal 'http://www.mcdonalds.com', contact.url
62
+ assert_equal '', contact.office_phone
63
+ assert_equal '', contact.mobile_phone
64
+ assert_equal '800234567', contact.fax
65
+ assert_equal 'McDonalds Corporation', contact.company
66
+ assert_equal '1 Canary Wharf', contact.address1
67
+ assert_equal '', contact.address2
68
+ assert_equal 'London', contact.city
69
+ assert_equal 'E1 1AA', contact.region # data-entry mistake
70
+ assert_equal '', contact.postcode # data-entry mistake
71
+ assert_equal '', contact.country
72
+ end
73
+
74
+ end
@@ -0,0 +1,7 @@
1
+ class MiniTest::Unit::TestCase
2
+
3
+ def fixture(filename)
4
+ File.expand_path "../fixtures/#{filename}", __FILE__
5
+ end
6
+
7
+ end
@@ -0,0 +1,45 @@
1
+ require 'minitest/autorun'
2
+ require 'test_helper'
3
+ require 'contact_sport'
4
+
5
+ class VcardReaderTest < MiniTest::Unit::TestCase
6
+
7
+ def test_foo
8
+ contacts = ContactSport.contacts fixture('vcards.vcf')
9
+ assert_equal 2, contacts.length
10
+
11
+ contact = contacts.shift
12
+ assert_equal '', contact.first_name
13
+ assert_equal '', contact.last_name
14
+ assert_equal 'Wayne Enterprises', contact.name
15
+ assert_equal 'info@wayneenterprises.com', contact.email
16
+ assert_equal '', contact.url
17
+ assert_equal '', contact.office_phone
18
+ assert_equal '', contact.mobile_phone
19
+ assert_equal '', contact.fax
20
+ assert_equal 'Wayne Enterprises', contact.company
21
+ assert_equal '', contact.address1
22
+ assert_equal '', contact.address2
23
+ assert_equal '', contact.city
24
+ assert_equal '', contact.region
25
+ assert_equal '', contact.postcode
26
+ assert_equal '', contact.country
27
+
28
+ contact = contacts.shift
29
+ assert_equal 'Bruce', contact.first_name
30
+ assert_equal 'Wayne', contact.last_name
31
+ assert_equal 'Bruce Wayne', contact.name
32
+ assert_equal 'bruce@wayneenterprises.com', contact.email
33
+ assert_equal 'www.batman.com', contact.url
34
+ assert_equal '+44 20 7123 4567', contact.office_phone
35
+ assert_equal '07777 999 888', contact.mobile_phone
36
+ assert_equal '+44 20 71234 4560', contact.fax
37
+ assert_equal 'Wayne Enterprises', contact.company
38
+ assert_equal 'The Batcave', contact.address1
39
+ assert_equal '', contact.address2
40
+ assert_equal 'Gotham', contact.city
41
+ assert_equal 'NY', contact.region
42
+ assert_equal '90210', contact.postcode
43
+ assert_equal 'USA', contact.country
44
+ end
45
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: contact_sport
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Andy Stewart
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: vcard
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '0.2'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '0.2'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.9.2
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.9.2
46
+ description: Simple importing of contacts from Outlook and vCard.
47
+ email:
48
+ - boss@airbladesoftware.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - LICENSE.txt
56
+ - README.md
57
+ - Rakefile
58
+ - contact_sport.gemspec
59
+ - lib/contact_sport.rb
60
+ - lib/contact_sport/contact.rb
61
+ - lib/contact_sport/encoding.rb
62
+ - lib/contact_sport/outlook_reader.rb
63
+ - lib/contact_sport/vcard_reader.rb
64
+ - lib/contact_sport/version.rb
65
+ - test/fixtures/iso_8859_1_commas.csv
66
+ - test/fixtures/utf_16_le_tabs.csv
67
+ - test/fixtures/vcards.vcf
68
+ - test/outlook_reader_test.rb
69
+ - test/test_helper.rb
70
+ - test/vcard_reader_test.rb
71
+ homepage: ''
72
+ licenses: []
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ segments:
84
+ - 0
85
+ hash: -3767443409390475510
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ segments:
93
+ - 0
94
+ hash: -3767443409390475510
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 1.8.23
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Simple importing of contacts from Outlook and vCard.
101
+ test_files:
102
+ - test/fixtures/iso_8859_1_commas.csv
103
+ - test/fixtures/utf_16_le_tabs.csv
104
+ - test/fixtures/vcards.vcf
105
+ - test/outlook_reader_test.rb
106
+ - test/test_helper.rb
107
+ - test/vcard_reader_test.rb