contact_sport 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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