sovren 0.0.3

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.
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