sovren 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +19 -0
  3. data/Gemfile +14 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +41 -0
  6. data/Rakefile +7 -0
  7. data/lib/sovren.rb +30 -0
  8. data/lib/sovren/achievement.rb +16 -0
  9. data/lib/sovren/association.rb +17 -0
  10. data/lib/sovren/certification.rb +18 -0
  11. data/lib/sovren/client.rb +45 -0
  12. data/lib/sovren/competency.rb +18 -0
  13. data/lib/sovren/contact_information.rb +33 -0
  14. data/lib/sovren/education.rb +30 -0
  15. data/lib/sovren/employment.rb +29 -0
  16. data/lib/sovren/language.rb +31 -0
  17. data/lib/sovren/military.rb +19 -0
  18. data/lib/sovren/patent.rb +19 -0
  19. data/lib/sovren/publication.rb +35 -0
  20. data/lib/sovren/reference.rb +18 -0
  21. data/lib/sovren/resume.rb +28 -0
  22. data/lib/sovren/version.rb +3 -0
  23. data/sovren.gemspec +30 -0
  24. data/spec/sovren/achievement_spec.rb +24 -0
  25. data/spec/sovren/association_spec.rb +25 -0
  26. data/spec/sovren/certification_spec.rb +26 -0
  27. data/spec/sovren/client_spec.rb +28 -0
  28. data/spec/sovren/competency_spec.rb +26 -0
  29. data/spec/sovren/contact_information_spec.rb +73 -0
  30. data/spec/sovren/education_spec.rb +48 -0
  31. data/spec/sovren/employment_spec.rb +45 -0
  32. data/spec/sovren/language_spec.rb +27 -0
  33. data/spec/sovren/military_spec.rb +29 -0
  34. data/spec/sovren/patent_spec.rb +27 -0
  35. data/spec/sovren/publication_spec.rb +70 -0
  36. data/spec/sovren/reference_spec.rb +34 -0
  37. data/spec/sovren/resume_spec.rb +42 -0
  38. data/spec/sovren_spec.rb +4 -0
  39. data/spec/spec_helper.rb +17 -0
  40. data/spec/support/ResumeSample.doc +0 -0
  41. data/spec/support/_resume.xml +970 -0
  42. data/spec/support/achievements.xml +5 -0
  43. data/spec/support/associations.xml +8 -0
  44. data/spec/support/certifications.xml +23 -0
  45. data/spec/support/competencies.xml +353 -0
  46. data/spec/support/competencies_sparse.xml +3 -0
  47. data/spec/support/contact_information.xml +69 -0
  48. data/spec/support/contact_information_sparse.xml +10 -0
  49. data/spec/support/education.xml +81 -0
  50. data/spec/support/education_sparse.xml +10 -0
  51. data/spec/support/employment.xml +179 -0
  52. data/spec/support/employment_sparse.xml +11 -0
  53. data/spec/support/languages.xml +23 -0
  54. data/spec/support/military.xml +19 -0
  55. data/spec/support/patents.xml +14 -0
  56. data/spec/support/publications.xml +60 -0
  57. data/spec/support/references.xml +36 -0
  58. data/spec/support/resume.json +466 -0
  59. data/spec/support/resume.xml +1072 -0
  60. data/spec/support/speaking_events.xml +7 -0
  61. data/spec/vcr/parsed_resume.yml +3695 -0
  62. metadata +215 -0
@@ -0,0 +1,35 @@
1
+ module Sovren
2
+ class Publication
3
+ attr_accessor :type, :title, :role, :publication_date, :journal_or_serial_name, :volume, :issue, :page_number, :abstract, :copyright_date, :copyright_text, :edition, :isbn, :publisher_name, :publisher_location, :event_name, :conference_date, :conference_location, :comments, :number_of_pages
4
+
5
+ def self.parse(publications)
6
+ return Array.new if publications.nil?
7
+ result = publications.css('Article,Book,ConferencePaper,OtherPublication').collect do |item|
8
+ c = Publication.new
9
+ c.type = item.name == "OtherPublication" ? item['type'] : item.name
10
+ c.title = item.css('Title').text
11
+ c.role = item.css('Name').first['role'] rescue nil
12
+ c.publication_date = item.css('PublicationDate').css('YearMonth,Year').first.text rescue nil
13
+ c.journal_or_serial_name = item.css('JournalOrSerialName').text
14
+ c.volume = item.css('Volume').text
15
+ c.issue = item.css('Issue').text
16
+ c.page_number = item.css('PageNumber').text
17
+ c.abstract = item.css('Abstract').text
18
+ c.copyright_date = item.css('Copyright CopyrightDates OriginalDate Year, Copyright CopyrightDates OriginalDate YearMonth').first.text rescue nil
19
+ c.copyright_text = item.css('Copyright CopyrightText').first.text rescue nil
20
+ c.edition = item.css('Edition').text
21
+ c.isbn = item.css('ISBN').text
22
+ c.publisher_name = item.css('PublisherName').text
23
+ c.publisher_location = item.css('PublisherLocation').text
24
+ c.event_name = item.css('EventName').text
25
+ c.conference_date = Date.parse(item.css('ConferenceDate AnyDate').text) rescue nil
26
+ c.conference_location = item.css('ConferenceLocation').text
27
+ c.comments = item.css('Comments').text
28
+ c.number_of_pages = item.css('NumberOfPages').text.to_i rescue nil
29
+ c
30
+ end
31
+ result
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,18 @@
1
+ module Sovren
2
+ class Reference
3
+ attr_accessor :name, :title, :email, :phone_number
4
+
5
+ def self.parse(references)
6
+ return Array.new if references.nil?
7
+ result = references.css('Reference').collect do |item|
8
+ r = Reference.new
9
+ r.name = item.css('PersonName FormattedName').text
10
+ r.title = item.css('PositionTitle').text
11
+ r.email = item.css('ContactMethod InternetEmailAddress').first.text rescue nil
12
+ r.phone_number = item.css('ContactMethod Telephone FormattedNumber').first.text rescue nil
13
+ r
14
+ end
15
+ result
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,28 @@
1
+ require 'json'
2
+
3
+ module Sovren
4
+ class Resume
5
+ attr_accessor :executive_summary, :objective, :contact_information, :education_history, :employment_history, :certifications, :competencies, :achievements, :associations, :languages, :military_history, :patent_history, :publication_history, :references
6
+
7
+ def self.parse(resume)
8
+ parsed_resume = Nokogiri::XML.parse(resume)
9
+ resume = self.new
10
+ resume.executive_summary = parsed_resume.css('ExecutiveSummary').text
11
+ resume.objective = parsed_resume.css('Objective').text
12
+ resume.contact_information = ContactInformation.parse(parsed_resume.css('ContactInfo').first)
13
+ resume.education_history = Education.parse(parsed_resume.css('EducationHistory').first)
14
+ resume.employment_history = Employment.parse(parsed_resume.css('EmploymentHistory').first)
15
+ resume.certifications = Certification.parse(parsed_resume.css('LicensesAndCertifications').first)
16
+ resume.competencies = Competency.parse(parsed_resume.css('Qualifications').first)
17
+ resume.achievements = Achievement.parse(parsed_resume.css('Achievements').first)
18
+ resume.associations = Association.parse(parsed_resume.css('Associations').first)
19
+ resume.languages = Language.parse(parsed_resume.css('Languages').first)
20
+ resume.military_history = Military.parse(parsed_resume.css('MilitaryHistory').first)
21
+ resume.patent_history = Patent.parse(parsed_resume.css('PatentHistory').first)
22
+ resume.publication_history = Publication.parse(parsed_resume.css('PublicationHistory').first)
23
+ resume.references = Reference.parse(parsed_resume.css('References').first)
24
+ resume
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module Sovren
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sovren/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sovren"
8
+ spec.version = Sovren::VERSION
9
+ spec.authors = ["Eric Fleming"]
10
+ spec.email = ["efleming@gmail.com"]
11
+ spec.description = "This is a gem used for parsing resumes using the Sovren resume parser service."
12
+ spec.summary = "This is a gem used for parsing resumes using the Sovren resume parser service."
13
+ spec.homepage = "http://github.com/efleming/sovren"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.required_ruby_version = '>= 1.9.2'
22
+
23
+ spec.add_dependency "savon", "~> 2.2.0"
24
+ spec.add_dependency "httpclient", "~> 2.3.3"
25
+ spec.add_dependency "nokogiri", "~> 1.5.9"
26
+ spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "rake"
28
+
29
+ spec.requirements << "Access to a sovren resume parser server."
30
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sovren::Achievement do
4
+ use_natural_assertions
5
+
6
+ context ".parse" do
7
+ context "a full resume" do
8
+ Given(:raw_xml) { File.read(File.expand_path(File.dirname(__FILE__) + '/../support/achievements.xml')) }
9
+ Given(:xml) { Nokogiri::XML.parse(raw_xml) }
10
+
11
+ When(:result) { Sovren::Achievement.parse(xml) }
12
+
13
+ Then { result.length == 1 }
14
+ Then { result.first.description == "Awarded Medal of Merit by the Royal Society of Forensics, 2005" }
15
+ end
16
+
17
+ context "no achievements" do
18
+ When(:result) { Sovren::Achievement.parse(nil) }
19
+
20
+ Then { result == Array.new }
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sovren::Association do
4
+ use_natural_assertions
5
+
6
+ context ".parse" do
7
+ context "a full resume" do
8
+ Given(:raw_xml) { File.read(File.expand_path(File.dirname(__FILE__) + '/../support/associations.xml')) }
9
+ Given(:xml) { Nokogiri::XML.parse(raw_xml) }
10
+
11
+ When(:result) { Sovren::Association.parse(xml) }
12
+
13
+ Then { result.length == 1 }
14
+ Then { result.first.name == "Association of Retired Military Document Examiners" }
15
+ Then { result.first.role == "Member" }
16
+ end
17
+
18
+ context "no associations" do
19
+ When(:result) { Sovren::Association.parse(nil) }
20
+
21
+ Then { result == Array.new }
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sovren::Certification do
4
+ use_natural_assertions
5
+
6
+ context ".parse" do
7
+ context "a full resume" do
8
+ Given(:raw_xml) { File.read(File.expand_path(File.dirname(__FILE__) + '/../support/certifications.xml')) }
9
+ Given(:xml) { Nokogiri::XML.parse(raw_xml) }
10
+
11
+ When(:result) { Sovren::Certification.parse(xml) }
12
+
13
+ Then { result.length == 4 }
14
+ Then { result[2].name == "Sun Secure Global Desktop (Tarantella) System Administration" }
15
+ Then { result[2].description == "certification" }
16
+ Then { result[2].effective_date == Date.new(2001,9,1) }
17
+ end
18
+
19
+ context "no competencies" do
20
+ When(:result) { Sovren::Certification.parse(nil) }
21
+
22
+ Then { result == Array.new }
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sovren::Client do
4
+ Given(:sovren_client) { Sovren::Client.new(endpoint: "foo1", username: "foo2", password: "foo3") }
5
+
6
+ context 'init' do
7
+ Then { sovren_client.should_not be_nil }
8
+ end
9
+
10
+ context '.config' do
11
+ Then { sovren_client.should respond_to :endpoint }
12
+ Then { sovren_client.endpoint == "foo1" }
13
+ Then { sovren_client.should respond_to :username }
14
+ Then { sovren_client.username == "foo2" }
15
+ Then { sovren_client.should respond_to :password }
16
+ Then { sovren_client.password == "foo3" }
17
+ end
18
+
19
+ describe 'parsing' do
20
+ Given(:sovren_client) { Sovren::Client.new(endpoint: "http://www.foo.com/") }
21
+ Given(:resume) { File.read(File.expand_path(File.dirname(__FILE__) + '/../support/ResumeSample.doc')) }
22
+
23
+ context ".parse", vcr: {cassette_name: 'parsed_resume'} do
24
+ When(:result) { sovren_client.parse(resume) }
25
+ Then { result.class.should == Sovren::Resume }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sovren::Competency do
4
+ use_natural_assertions
5
+
6
+ context ".parse" do
7
+ context "a full resume" do
8
+ Given(:raw_xml) { File.read(File.expand_path(File.dirname(__FILE__) + '/../support/competencies.xml')) }
9
+ Given(:xml) { Nokogiri::XML.parse(raw_xml) }
10
+
11
+ When(:result) { Sovren::Competency.parse(xml) }
12
+
13
+ Then { result.length == 50 }
14
+ Then { result.first.name == "MARKETING" }
15
+ Then { result.first.months == 158 }
16
+ Then { result.first.last_used_date == Date.new(2013,4,29) }
17
+ end
18
+
19
+ context "no competencies" do
20
+ When(:result) { Sovren::Competency.parse(nil) }
21
+
22
+ Then { result == Array.new }
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sovren::ContactInformation do
4
+ use_natural_assertions
5
+
6
+ Given(:contact_information) { Sovren::ContactInformation.new }
7
+
8
+ Then { contact_information.should respond_to :first_name }
9
+ Then { contact_information.should respond_to :middle_name }
10
+ Then { contact_information.should respond_to :last_name }
11
+ Then { contact_information.should respond_to :generation }
12
+
13
+ Then { contact_information.should respond_to :address_line_1 }
14
+ Then { contact_information.should respond_to :address_line_2 }
15
+ Then { contact_information.should respond_to :city }
16
+ Then { contact_information.should respond_to :state }
17
+ Then { contact_information.should respond_to :country }
18
+ Then { contact_information.should respond_to :postal_code }
19
+
20
+ Then { contact_information.should respond_to :home_phone }
21
+ Then { contact_information.should respond_to :mobile_phone }
22
+
23
+ Then { contact_information.should respond_to :email }
24
+ Then { contact_information.should respond_to :website }
25
+
26
+ context ".parse" do
27
+ context "a full resume" do
28
+ Given(:raw_xml) { File.read(File.expand_path(File.dirname(__FILE__) + '/../support/contact_information.xml')) }
29
+ Given(:xml) { Nokogiri::XML.parse(raw_xml) }
30
+
31
+ When(:result) { Sovren::ContactInformation.parse(xml) }
32
+
33
+ Then { result.first_name == "John" }
34
+ Then { result.middle_name == "F." }
35
+ Then { result.last_name == "Adams" }
36
+ Then { result.generation == "III" }
37
+ Then { result.aristocratic_title == "Duke" }
38
+ Then { result.form_of_address == "Mr." }
39
+ Then { result.qualification == "M.D." }
40
+
41
+ Then { result.address_line_1 == "930 Via Mil Cumbres" }
42
+ Then { result.address_line_2 == "Unit 119" }
43
+ Then { result.city == "Solana Beach" }
44
+ Then { result.state == "CA" }
45
+ Then { result.postal_code == "92075" }
46
+ Then { result.country == "US" }
47
+
48
+ Then { result.home_phone == "(858) 555-1000" }
49
+ Then { result.mobile_phone == "(858) 555-1001" }
50
+
51
+ Then { result.website == "http://www.linkedin.com/in/johnadams" }
52
+ Then { result.email == "johnadams@yamoo.com" }
53
+ end
54
+
55
+ context "a sparse resume" do
56
+ Given(:raw_xml) { File.read(File.expand_path(File.dirname(__FILE__) + '/../support/contact_information_sparse.xml')) }
57
+ Given(:xml) { Nokogiri::XML.parse(raw_xml) }
58
+
59
+ When(:result) { Sovren::ContactInformation.parse(xml) }
60
+
61
+ Then { result.first_name == "John" }
62
+ Then { result.last_name == "Adams" }
63
+ Then { result.email == "johnadams@yamoo.com" }
64
+ end
65
+
66
+ context "no contact info" do
67
+ When(:result) { Sovren::ContactInformation.parse(nil) }
68
+
69
+ Then { result == Array.new }
70
+ end
71
+ end
72
+
73
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sovren::Education do
4
+ use_natural_assertions
5
+
6
+ context ".graduated?" do
7
+ When(:education) {Sovren::Education.new}
8
+ Then { education.graduated? == false }
9
+ end
10
+
11
+ context ".parse" do
12
+ context "a full list of experience" do
13
+ Given(:raw_education_xml) { File.read(File.expand_path(File.dirname(__FILE__) + '/../support/education.xml')) }
14
+ Given(:education_xml) { Nokogiri::XML.parse(raw_education_xml) }
15
+
16
+ When(:result) { Sovren::Education.parse(education_xml) }
17
+
18
+ Then { result.length == 2 }
19
+ Then { result.first.school_name == "California State University" }
20
+ Then { result.first.city == "Chico"}
21
+ Then { result.first.state == "CA"}
22
+ Then { result.first.country == "US"}
23
+ Then { result.first.major == "Business Administration" }
24
+ Then { result.first.minor == "" }
25
+ Then { result.first.degree_type == "bachelors" }
26
+ Then { result.first.degree_name == "B.S." }
27
+ Then { result.first.gpa == 3.66 }
28
+ Then { result.first.gpa_out_of == 4.00 }
29
+ Then { result.first.start_date == Date.new(1996,1,1) }
30
+ Then { result.first.end_date == Date.new(1999,1,1) }
31
+ Then { result.first.graduated == true }
32
+ Then { result.first.graduated? == true }
33
+ end
34
+
35
+ context "very little experience information" do
36
+ Given(:raw_education_xml) { File.read(File.expand_path(File.dirname(__FILE__) + '/../support/education_sparse.xml')) }
37
+ Given(:education_xml) { Nokogiri::XML.parse(raw_education_xml) }
38
+
39
+ When(:result) { Sovren::Education.parse(education_xml) }
40
+
41
+ Then { result.length == 1 }
42
+ Then { result.first.school_name == "California State University" }
43
+ Then { result.first.degree_type == "bachelors" }
44
+ Then { result.first.degree_name == "B.S." }
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sovren::Employment do
4
+ use_natural_assertions
5
+
6
+ context ".current_employer?" do
7
+ When(:employment) {Sovren::Employment.new}
8
+ Then { employment.current_employer? == false }
9
+ end
10
+
11
+ context ".parse" do
12
+ context "a full resume" do
13
+ Given(:raw_employment_xml) { File.read(File.expand_path(File.dirname(__FILE__) + '/../support/employment.xml')) }
14
+ Given(:employment_xml) { Nokogiri::XML.parse(raw_employment_xml) }
15
+
16
+ When(:result) { Sovren::Employment.parse(employment_xml) }
17
+
18
+ Then { result.length == 4 }
19
+ Then { result.first.employer == "Technical Difference" }
20
+ Then { result.first.division == nil }
21
+ Then { result.first.title == "Director of Web Applications Development" }
22
+ Then { result.first.city == "Encinitas"}
23
+ Then { result.first.state == "CA"}
24
+ Then { result.first.country == "US"}
25
+ Then { result.first.description.length == 694 }
26
+ Then { result.first.start_date == Date.new(2004,10,01) }
27
+ Then { result.first.end_date == nil }
28
+ Then { result.first.current_employer == true }
29
+ Then { result.first.current_employer? == true }
30
+ end
31
+
32
+ context "a sparse resume" do
33
+ Given(:raw_employment_xml) { File.read(File.expand_path(File.dirname(__FILE__) + '/../support/employment_sparse.xml')) }
34
+ Given(:employment_xml) { Nokogiri::XML.parse(raw_employment_xml) }
35
+
36
+ When(:result) { Sovren::Employment.parse(employment_xml) }
37
+
38
+ Then { result.length == 1 }
39
+ Then { result.first.employer == "Technical Difference" }
40
+ Then { result.first.title == "Director of Web Applications Development" }
41
+ Then { result.first.current_employer? == false }
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sovren::Language do
4
+ use_natural_assertions
5
+
6
+ context ".parse" do
7
+ context "a full resume" do
8
+ Given(:raw_xml) { File.read(File.expand_path(File.dirname(__FILE__) + '/../support/languages.xml')) }
9
+ Given(:xml) { Nokogiri::XML.parse(raw_xml) }
10
+
11
+ When(:result) { Sovren::Language.parse(xml) }
12
+
13
+ Then { result.length == 3 }
14
+ Then { result.first.language_code == "ps" }
15
+ Then { result.first.read? == true }
16
+ Then { result.first.speak? == true }
17
+ Then { result.first.write? == true }
18
+ end
19
+
20
+ context "no languages" do
21
+ When(:result) { Sovren::Language.parse(nil) }
22
+
23
+ Then { result == Array.new }
24
+ end
25
+ end
26
+
27
+ end