contact_csv 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2008-02-05
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Marshall Huss
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,35 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ config/hoe.rb
7
+ config/requirements.rb
8
+ lib/contact_csv.rb
9
+ lib/contact_csv/contact.rb
10
+ lib/contact_csv/contact_csv.rb
11
+ lib/contact_csv/contact_manager.rb
12
+ lib/contact_csv/importer.rb
13
+ lib/contact_csv/lookup_tables/lookup_table.rb
14
+ lib/contact_csv/lookup_tables/outlook_csv.rb
15
+ lib/contact_csv/version.rb
16
+ script/destroy
17
+ script/generate
18
+ script/txt2html
19
+ setup.rb
20
+ tasks/deployment.rake
21
+ tasks/environment.rake
22
+ tasks/website.rake
23
+ test/outlook_contacts.csv
24
+ test/outlook_contacts_dos.csv
25
+ test/test_contact.rb
26
+ test/test_contact_csv.rb
27
+ test/test_contact_manager.rb
28
+ test/test_helper.rb
29
+ test/test_importer.rb
30
+ test/test_lookup_table.rb
31
+ website/index.html
32
+ website/index.txt
33
+ website/javascripts/rounded_corners_lite.inc.js
34
+ website/stylesheets/screen.css
35
+ website/template.rhtml
@@ -0,0 +1,20 @@
1
+ # === ContactCsv
2
+ #
3
+ # ==== Reading in CSV
4
+ #
5
+ # The two class methods are used to read in a CSV file of contacts exported by email clients such as Outlook or GMail. Both methods return an Array of Contact objects.
6
+ #
7
+ # contacts = ContactCSV.read('/path/to/file.csv')
8
+ #
9
+ # contacts = ContactCSV.parse('csv,data,string')
10
+ #
11
+ # ==== Getting the contacts
12
+ #
13
+ # contacts.each do |contact|
14
+ # puts contact.name
15
+ # puts contact.email
16
+ # end
17
+ #
18
+ # See the Contact class for a complete list of attributes.
19
+ #
20
+ #
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
@@ -0,0 +1,71 @@
1
+ require 'contact_csv/version'
2
+
3
+ AUTHOR = 'Marshall Huss' # can also be an array of Authors
4
+ EMAIL = "mwhuss@gmail.com"
5
+ DESCRIPTION = "Simple gem for reading in contact csv files that you can export from email clients like Outlook or GMail"
6
+ GEM_NAME = 'contact_csv' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'contactcsv' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+
11
+ @config_file = "~/.rubyforge/user-config.yml"
12
+ @config = nil
13
+ RUBYFORGE_USERNAME = "mwhuss"
14
+ def rubyforge_username
15
+ unless @config
16
+ begin
17
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
18
+ rescue
19
+ puts <<-EOS
20
+ ERROR: No rubyforge config file found: #{@config_file}
21
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
22
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
23
+ EOS
24
+ exit
25
+ end
26
+ end
27
+ RUBYFORGE_USERNAME.replace @config["username"]
28
+ end
29
+
30
+
31
+ REV = nil
32
+ # UNCOMMENT IF REQUIRED:
33
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
34
+ VERS = ContactCsv::VERSION::STRING + (REV ? ".#{REV}" : "")
35
+ RDOC_OPTS = ['--quiet', '--title', 'contact_csv documentation',
36
+ "--opname", "index.html",
37
+ "--line-numbers",
38
+ "--main", "README",
39
+ "--inline-source"]
40
+
41
+ class Hoe
42
+ def extra_deps
43
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
44
+ @extra_deps
45
+ end
46
+ end
47
+
48
+ # Generate all the Rake tasks
49
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
50
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
51
+ p.developer(AUTHOR, EMAIL)
52
+ p.description = DESCRIPTION
53
+ p.summary = DESCRIPTION
54
+ p.url = HOMEPATH
55
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
56
+ p.test_globs = ["test/**/test_*.rb"]
57
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
58
+
59
+ # == Optional
60
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
61
+ p.extra_deps = [ ['fastercsv'] ] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
62
+
63
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
64
+
65
+ end
66
+
67
+ CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
68
+ #PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
69
+ PATH = RUBYFORGE_PROJECT
70
+ hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
71
+ hoe.rsync_args = '-av --delete --ignore-errors'
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
16
+
17
+ require 'contact_csv'
@@ -0,0 +1,10 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'fastercsv'
5
+ require 'contact_csv/contact_csv.rb'
6
+ require 'contact_csv/importer.rb'
7
+ require 'contact_csv/contact.rb'
8
+ require 'contact_csv/contact_manager.rb'
9
+ require 'contact_csv/lookup_tables/lookup_table.rb'
10
+ require 'contact_csv/lookup_tables/outlook_csv.rb'
@@ -0,0 +1,102 @@
1
+ # === Contact
2
+ #
3
+ # Object that represents a Contact from an address book
4
+ #
5
+ class ContactCsv::Contact
6
+
7
+ attr_accessor :extras, :first_name, :middle_name, :last_name, :email, :title
8
+
9
+ def initialize(attributes={})
10
+ @extras = {}
11
+ @first_name = attributes[:first_name]
12
+ @middle_name = attributes[:middle_name]
13
+ @last_name = attributes[:last_name]
14
+ @email = attributes[:email]
15
+ @title = attributes[:title]
16
+ end
17
+
18
+ def extras
19
+ @extras
20
+ end
21
+
22
+ def add_extra(extra)
23
+ @extras.merge!(extra)
24
+ end
25
+
26
+ #def method_missing(method, *args)
27
+ # self.add_extras( { method => args[0] } )
28
+ #end
29
+
30
+ # attr_accessor :name, :email, :address, :notes, :email2, :email3, :mobile_phone, :pager,
31
+ # :company, :job_title, :home_phone, :home_phone2, :home_fax, :home_address,
32
+ # :business_phone, :business_phone2, :business_fax, :business_address,
33
+ # :other_phone, :other_fax, :other_address
34
+ #
35
+ # # Initilize takes in options hash and sets the local attributes
36
+ # def initialize(attributes={})
37
+ # @name = attributes[:name]
38
+ # @email = attributes[:email]
39
+ # @address = attributes[:address]
40
+ # @notes = attributes[:notes]
41
+ # @email2 = attributes[:email2]
42
+ # @email3 = attributes[:email3]
43
+ # @mobile_phone = attributes[:mobile_phone]
44
+ # @pager = attributes[:pager]
45
+ # @company = attributes[:company]
46
+ # @job_title = attributes[:job_title]
47
+ # @home_phone = attributes[:home_phone]
48
+ # @home_phone2 = attributes[:home_phone2]
49
+ # @home_fax = attributes[:home_fax]
50
+ # @home_address = attributes[:home_address]
51
+ # @business_phone = attributes[:business_phone]
52
+ # @business_phone2 = attributes[:business_phone2]
53
+ # @business_fax = attributes[:business_fax]
54
+ # @business_address = attributes[:business_address]
55
+ # @other_phone = attributes[:other_phone]
56
+ # @other_fax = attributes[:other_fax]
57
+ # @other_address = attributes[:other_address]
58
+ # end
59
+ #
60
+ # # Creates an Array of Contact objects from the FasterCSV Array
61
+ # def self.contacts(csv)
62
+ # contacts = []
63
+ # csv.each do |c|
64
+ # contacts << Contact.new(
65
+ # :name => c[0],
66
+ # :email => c[1],
67
+ # :address => c[2],
68
+ # :notes => c[3],
69
+ # :email2 => c[4],
70
+ # :email3 => c[5],
71
+ # :mobile_phone => c[6],
72
+ # :pager => c[7],
73
+ # :company => c[8],
74
+ # :job_title => c[9],
75
+ # :home_phone => c[10],
76
+ # :home_phone2 => c[11],
77
+ # :home_fax => c[12],
78
+ # :home_address => c[13],
79
+ # :business_phone => c[14],
80
+ # :business_phone2 => c[15],
81
+ # :business_fax => c[16],
82
+ # :business_address => c[17],
83
+ # :other_phone => c[18],
84
+ # :other_fax => c[19],
85
+ # :other_address => c[20]
86
+ # )
87
+ # end
88
+ # contacts
89
+ # end
90
+ #
91
+ # def empty?
92
+ # @name.nil? && @email.nil? && @address.nil? && @notes.nil? && @email2.nil? &&
93
+ # @email3.nil? && @mobile_phone.nil? && @pager.nil? && @company.nil? && @job_title.nil? &&
94
+ # @home_phone.nil? && @home_phone2.nil? && @home_fax.nil? && @home_address.nil? && @business_phone.nil? &&
95
+ # @business_phone2.nil? && @business_fax.nil? && @business_address.nil? && @other_phone.nil? && @other_fax.nil? && @other_address
96
+ # end
97
+ #
98
+ #
99
+ # def method_missing(method, *args)
100
+ # end
101
+
102
+ end
@@ -0,0 +1,14 @@
1
+ # === ContactCsv
2
+ #
3
+ # ==== Reading in CSV
4
+ #
5
+ # The two class methods are used to read in a CSV file of contacts exported by email clients such as Outlook or GMail. Both methods return an Array of Contact objects.
6
+ #
7
+ # ContactCSV.read('/path/to/file.csv')
8
+ #
9
+ # ContactCSV.parse('csv,data,string')
10
+ #
11
+ module ContactCsv
12
+ module LookupTables
13
+ end
14
+ end
@@ -0,0 +1,52 @@
1
+ class ContactCsv::ContactManager
2
+ include ContactCsv
3
+
4
+ attr_accessor :contacts
5
+
6
+ def initialize(csv, lookup_tables=[])
7
+ @contacts = []
8
+
9
+ lookup_table = find_lookup_table(csv, lookup_tables)
10
+ raise LookupTableNotFoundError if lookup_table.nil?
11
+
12
+ csv.each do |row|
13
+ c = Contact.new
14
+
15
+ row.each do |r|
16
+ col = lookup_table.lookup(r[0])
17
+ if !col.nil? && c.respond_to?(col.to_sym)
18
+ c.send("#{col.to_s}=", r[1])
19
+ else
20
+ c.add_extra({ r[0] => r[1] })
21
+ end
22
+
23
+ end
24
+
25
+ contacts << c
26
+ end
27
+
28
+ contacts
29
+ end
30
+
31
+
32
+
33
+ #def contacts
34
+ # []
35
+ #end
36
+
37
+
38
+
39
+ private
40
+
41
+ def find_lookup_table(csv, lookup_tables)
42
+ tables = lookup_tables + [ContactCsv::LookupTables::OutlookCsv.lookup_table]
43
+ tables.each do |table|
44
+ return table if table.headers == csv.headers
45
+ end
46
+ return nil
47
+ end
48
+
49
+
50
+ class LookupTableNotFoundError < StandardError; end
51
+
52
+ end
@@ -0,0 +1,18 @@
1
+ class ContactCsv::Importer
2
+ include ContactCsv
3
+
4
+ # Creates an Array of Contact objects from a CSV File
5
+ def self.read(file_path, lookup_tables=[])
6
+ csv = FasterCSV.read(file_path, :headers => true)
7
+ contact_manager = ContactManager.new(csv, lookup_tables)
8
+ contact_manager.contacts
9
+ end
10
+
11
+ # Creates an Array of Contact objects from a CSV String
12
+ def self.parse(csv_string, lookup_tables=[])
13
+ csv = FasterCSV.parse(csv_string, :headers => true)
14
+ contact_manager = ContactManager.new(csv, lookup_tables)
15
+ contact_manager.contacts
16
+ end
17
+
18
+ end
@@ -0,0 +1,20 @@
1
+ class ContactCsv::LookupTables::LookupTable
2
+
3
+ class InvalidInputFormatError < StandardError; end
4
+
5
+ attr_accessor :legend, :headers
6
+
7
+
8
+ def initialize(headers, legend)
9
+ raise InvalidInputFormatError unless headers.is_a?(Array) && legend.is_a?(Hash)
10
+ @headers = headers
11
+ @legend = legend
12
+ end
13
+
14
+
15
+ # Returns the corresponding Contact attribute mapped to the specific Outlook CSV column name
16
+ def lookup(column)
17
+ @legend[column]
18
+ end
19
+
20
+ end
@@ -0,0 +1,114 @@
1
+ # === OutlookCsv
2
+ #
3
+ #
4
+ #
5
+ #
6
+ class ContactCsv::LookupTables::OutlookCsv
7
+ include ContactCsv::LookupTables
8
+
9
+ def self.legend
10
+ {
11
+ 'Title' => :title,
12
+ 'First Name' => :first_name,
13
+ 'Middle Name' => :middle_name,
14
+ 'Last Name' => :last_name,
15
+ 'E-mail Address' => :email
16
+ }
17
+ end
18
+
19
+ # Returns an Array of all the headers for a Outlook CSV file
20
+ def self.headers
21
+ [ "Title",
22
+ "First Name",
23
+ "Middle Name",
24
+ "Last Name",
25
+ "Suffix",
26
+ "Company",
27
+ "Department",
28
+ "Job Title",
29
+ "Business Street",
30
+ "Business Street 2",
31
+ "Business Street 3",
32
+ "Business City",
33
+ "Business State",
34
+ "Business Postal Code",
35
+ "Business Country",
36
+ "Home Street",
37
+ "Home Street 2",
38
+ "Home Street 3",
39
+ "Home City",
40
+ "Home State",
41
+ "Home Postal Code",
42
+ "Home Country",
43
+ "Other Street",
44
+ "Other Street 2",
45
+ "Other Street 3",
46
+ "Other City",
47
+ "Other State",
48
+ "Other Postal Code",
49
+ "Other Country",
50
+ "Assistant's Phone",
51
+ "Business Fax",
52
+ "Business Phone",
53
+ "Business Phone 2",
54
+ "Callback",
55
+ "Car Phone",
56
+ "Company Main Phone",
57
+ "Home Fax","Home Phone",
58
+ "Home Phone 2",
59
+ "ISDN",
60
+ "Mobile Phone",
61
+ "Other Fax",
62
+ "Other Phone",
63
+ "Pager",
64
+ "Primary Phone",
65
+ "Radio Phone",
66
+ "TTY/TDD Phone",
67
+ "Telex","Account",
68
+ "Anniversary",
69
+ "Assistant's Name",
70
+ "Billing Information",
71
+ "Birthday",
72
+ "Business Address PO Box",
73
+ "Categories","Children",
74
+ "Directory Server",
75
+ "E-mail Address",
76
+ "E-mail Type",
77
+ "E-mail Display Name",
78
+ "E-mail 2 Address",
79
+ "E-mail 2 Type",
80
+ "E-mail 2 Display Name",
81
+ "E-mail 3 Address",
82
+ "E-mail 3 Type",
83
+ "E-mail 3 Display Name",
84
+ "Gender",
85
+ "Government ID Number",
86
+ "Hobby",
87
+ "Home Address PO Box",
88
+ "Initials",
89
+ "Internet Free Busy",
90
+ "Keywords","Language",
91
+ "Location",
92
+ "Manager's Name",
93
+ "Mileage",
94
+ "Notes",
95
+ "Office Location",
96
+ "Organizational ID Number",
97
+ "Other Address PO Box",
98
+ "Priority","Private",
99
+ "Profession",
100
+ "Referred By",
101
+ "Sensitivity",
102
+ "Spouse",
103
+ "User 1",
104
+ "User 2",
105
+ "User 3",
106
+ "User 4",
107
+ "Web Page"]
108
+ end
109
+
110
+ def self.lookup_table
111
+ LookupTable.new(self.headers, self.legend)
112
+ end
113
+
114
+ end