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,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZGI2YjYyNjA3NDlkOTcwOWExOTk4MTdmNjc1ZGI2MWQ4NWY2NDI3Yw==
5
+ data.tar.gz: !binary |-
6
+ YjU3ZDU1MzFjYWEyMDQ4MWQ5NTQ3NzQ4MTk0NzFiNTRjNGY2OWIwYg==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NjBlMTc0ODVhMTMxZjZjODM2ZjkzZTRkNGZhMWQ4NmI5YjE5NTViYTZkZmNl
10
+ NzM0OGUzMzNkMDBjZjlkZDVlNTgwMGJjZTEyNDc3YzU5MjIzODMyZGMwOWE4
11
+ M2JkYmM3MzQ2N2EzNjQ0ZTJlZDBhZGNlYTE1MjNhZThiN2Q3Y2I=
12
+ data.tar.gz: !binary |-
13
+ NWMwODgwNDA5MmM2OTc5MDU3MzUxY2QwNzg2OGNmZTJlODYyMmFiYjNhODdk
14
+ Y2ZjM2ZlNGJjZDZkYTJhNzA4NjgwYWMwMTc2MzE4YjAwMjc5NGIwYjA0NjBi
15
+ OTYxNWJhMGRlYWU4NjA2NWI3ZmI2NDBmZGFiNTMzZTk0ZDE2NTU=
@@ -0,0 +1,19 @@
1
+ .DS_Store
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .rvmrc
7
+ .yardoc
8
+ Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'httpclient'
4
+ gem 'nokogiri'
5
+ gem 'savon'
6
+
7
+ # Specify your gem's dependencies in sovren.gemspec
8
+ gemspec
9
+
10
+ gem 'pry'
11
+ gem 'rspec'
12
+ gem 'rspec-given'
13
+ gem 'vcr'
14
+ gem 'webmock', '< 1.10'
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Eric Fleming
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.
@@ -0,0 +1,41 @@
1
+ # Sovren
2
+
3
+ A simple ruby gem that parses a resume using the sovren resume parser and returns the resume back as a ruby object.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'sovren'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install sovren
18
+
19
+ ## Usage Example
20
+
21
+ 1. Create a client
22
+
23
+ ```ruby
24
+ client = Sovren::Client.new(endpoint: "http://yourhost.com/SovrenConvertAndParse/ConvertAndParse.asmx?WSDL", username: "http basic username (optional)", password: "http basic password (optional)")
25
+ ```
26
+
27
+ 2. Parse a resume
28
+
29
+ ```ruby
30
+ resume = client.parse(File.read('/path/to/your/file/resume.doc'))
31
+ ```
32
+
33
+ ## Contributing
34
+
35
+ The testing could use some more coverage for other hr-xml use cases. I also haven't added any of the sovren specific fields returned but those could be added if you need them.
36
+
37
+ 1. Fork it
38
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
39
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
40
+ 4. Push to the branch (`git push origin my-new-feature`)
41
+ 5. Create new Pull Request
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new('spec')
6
+
7
+ task :default => :spec
@@ -0,0 +1,30 @@
1
+ require "pry"
2
+ require "sovren/version"
3
+ require "savon"
4
+
5
+ module Sovren
6
+ class << self
7
+ FIELDS = [:endpoint, :username, :password, :timeout, :hard_time_out_multiplier, :parser_configuration_params]
8
+ attr_accessor(*FIELDS)
9
+
10
+ def configure
11
+ yield self
12
+ true
13
+ end
14
+ end
15
+
16
+ require_relative "sovren/achievement"
17
+ require_relative "sovren/association"
18
+ require_relative "sovren/certification"
19
+ require_relative "sovren/client"
20
+ require_relative "sovren/competency"
21
+ require_relative "sovren/contact_information"
22
+ require_relative "sovren/education"
23
+ require_relative "sovren/employment"
24
+ require_relative "sovren/resume"
25
+ require_relative "sovren/language"
26
+ require_relative "sovren/military"
27
+ require_relative "sovren/patent"
28
+ require_relative "sovren/publication"
29
+ require_relative "sovren/reference"
30
+ end
@@ -0,0 +1,16 @@
1
+ module Sovren
2
+ class Achievement
3
+ attr_accessor :description
4
+
5
+ def self.parse(achievements)
6
+ return Array.new if achievements.nil?
7
+ result = achievements.css('Achievement').collect do |item|
8
+ c = Achievement.new
9
+ c.description = item.css('Description').text
10
+ c
11
+ end
12
+ result
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module Sovren
2
+ class Association
3
+ attr_accessor :name, :role
4
+
5
+ def self.parse(associations)
6
+ return Array.new if associations.nil?
7
+ result = associations.css('Association').collect do |item|
8
+ c = Association.new
9
+ c.name = item.css('Name').first.text
10
+ c.role = item.css('Role Name').text
11
+ c
12
+ end
13
+ result
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module Sovren
2
+ class Certification
3
+ attr_accessor :name, :description, :effective_date
4
+
5
+ def self.parse(certifications)
6
+ return Array.new if certifications.nil?
7
+ result = certifications.css('LicenseOrCertification').collect do |item|
8
+ c = Certification.new
9
+ c.name = item.css('Name').text
10
+ c.description = item.css('Description').text
11
+ c.effective_date = Date.parse(item.css('EffectiveDate FirstIssuedDate AnyDate').text) rescue nil
12
+ c
13
+ end
14
+ result
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,45 @@
1
+ module Sovren
2
+ class Client
3
+ attr_reader :endpoint, :username, :password, :timeout, :hard_time_out_multiplier, :parser_configuration_params
4
+
5
+ #Initialize the client class that will be used for all sovren requests.
6
+ #
7
+ #Certain requests will require an oauth token. See http://developer.foursquare.com/docs/index_docs.html for the full list.
8
+ #
9
+ # @param [Hash] options
10
+ # @option options String :endpoint The url that the web service is located at
11
+ # @option options String :username The HTTP Basic auth username for the webservice
12
+ # @option options String :password The HTTP Basic auth password for the webservice
13
+ # @option options Integer :timeout The timeout for the parser
14
+ # @option options Integer :hard_time_out_multiplier The hard timeout for the parser
15
+ # @option options Integer :parser_configuration_params The parser configuration params, used to tweak the output of the parser
16
+
17
+ def initialize(options={})
18
+ @endpoint = options[:endpoint]
19
+ @username = options[:username]
20
+ @password = options[:password]
21
+ @timeout = options[:timout] || 30000
22
+ @hard_time_out_multiplier = options[:hard_time_out_multiplier] || 2
23
+ @parser_configuration_params = options[:parser_configuration_params] || "_100000_0_00000010_0000000110101100_1_0000000000000111111102000000000010000100000000000000"
24
+ end
25
+
26
+ def connection
27
+ Savon.client(wsdl: endpoint, log: false)
28
+ end
29
+
30
+ def parse(file)
31
+ result = connection.call(:parse) do |c|
32
+ c.message({
33
+ "DocumentAsByteArray" => Base64.encode64(file),
34
+ "ParserConfigurationParams" => parser_configuration_params,
35
+ "AlsoUseSovrenTaxonomy" => true,
36
+ "EmbedConvertedTextInHrXml" => true,
37
+ "HardTimeOutMultiplier" => hard_time_out_multiplier,
38
+ "TimeOutInMs" => timeout})
39
+ end
40
+
41
+ Resume.parse(result.body[:parse_response][:parse_result])
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,18 @@
1
+ module Sovren
2
+ class Competency
3
+ attr_accessor :name, :months, :last_used_date
4
+
5
+ def self.parse(competencies)
6
+ return Array.new if competencies.nil?
7
+ results = competencies.css('Competency').collect do |item|
8
+ c = Competency.new
9
+ c.name = item['name']
10
+ c.months = item.css('CompetencyEvidence NumericValue').text.to_i rescue nil
11
+ c.last_used_date = Date.parse(item.css('CompetencyEvidence').first['lastUsed']) rescue nil
12
+ c
13
+ end
14
+ results
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ module Sovren
2
+ class ContactInformation
3
+ attr_accessor :first_name, :middle_name, :last_name, :aristocratic_title, :form_of_address, :generation, :qualification, :address_line_1, :address_line_2, :city, :state, :country, :postal_code, :home_phone, :mobile_phone, :email, :website
4
+
5
+ def self.parse(contact_information)
6
+ return nil if contact_information.nil?
7
+ result = self.new
8
+ result.first_name = contact_information.css('PersonName GivenName').collect(&:text).join(" ")
9
+ result.middle_name = contact_information.css('PersonName MiddleName').collect(&:text).join(" ")
10
+ result.last_name = contact_information.css('PersonName FamilyName').collect(&:text).join(" ")
11
+ result.aristocratic_title = contact_information.css('PersonName Affix[type=aristocraticTitle]').collect(&:text).join(" ")
12
+ result.form_of_address = contact_information.css('PersonName Affix[type=formOfAddress]').collect(&:text).join(" ")
13
+ result.generation = contact_information.css('PersonName Affix[type=generation]').collect(&:text).join(" ")
14
+ result.qualification = contact_information.css('PersonName Affix[type=qualification]').collect(&:text).join(" ")
15
+
16
+ address = contact_information.css('PostalAddress DeliveryAddress AddressLine').collect(&:text)
17
+ result.address_line_1 = address[0] if address.length > 0
18
+ result.address_line_2 = address[1] if address.length > 1
19
+ result.city = contact_information.css('PostalAddress').first.css('Municipality').text rescue nil
20
+ result.state = contact_information.css('PostalAddress').first.css('Region').text rescue nil
21
+ result.postal_code = contact_information.css('PostalAddress').first.css('PostalCode').text rescue nil
22
+ result.country = contact_information.css('PostalAddress').first.css('CountryCode').text rescue nil
23
+
24
+ result.home_phone = contact_information.css('Telephone FormattedNumber').first.text rescue nil
25
+ result.mobile_phone = contact_information.css('Mobile FormattedNumber').first.text rescue nil
26
+
27
+ result.website = contact_information.css('InternetWebAddress').first.text rescue nil
28
+ result.email = contact_information.css('InternetEmailAddress').first.text rescue nil
29
+
30
+ result
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,30 @@
1
+ module Sovren
2
+ class Education
3
+ attr_accessor :school_name, :city, :state, :country, :degree_name, :degree_type, :major, :minor, :gpa, :gpa_out_of, :start_date, :end_date, :graduated
4
+
5
+ def self.parse(education_history)
6
+ return Array.new if education_history.nil?
7
+ result = education_history.css('SchoolOrInstitution').collect do |item|
8
+ e = Education.new
9
+ e.school_name = item.css('SchoolName').text
10
+ e.city, e.state, e.country = item.css('PostalAddress Municipality, PostalAddress Region, PostalAddress CountryCode').collect(&:text)
11
+ e.degree_type = item.css('Degree').first['degreeType']
12
+ e.degree_name = item.css('Degree DegreeName').text
13
+ e.major = item.css('DegreeMajor Name').text
14
+ e.minor = item.css('DegreeMinor name').text
15
+ e.gpa = item.css('EducationalMeasure MeasureValue StringValue').text.to_f rescue nil
16
+ e.gpa_out_of = item.css('EducationalMeasure HighestPossibleValue StringValue').text.to_f rescue nil
17
+ e.start_date = Date.parse(item.css('DatesOfAttendance StartDate AnyDate').text) rescue nil
18
+ e.end_date = Date.parse(item.css('DatesOfAttendance EndDate AnyDate').text) rescue nil
19
+ e.graduated = item.css('Degree DegreeDate AnyDate').text != ""
20
+ e
21
+ end
22
+ result
23
+ end
24
+
25
+ def graduated?
26
+ !graduated.nil? && graduated
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ module Sovren
2
+ class Employment
3
+ attr_accessor :employer, :division, :city, :state, :country, :title, :description, :start_date, :end_date, :current_employer
4
+
5
+ def self.parse(employment_history)
6
+ return Array.new if employment_history.nil?
7
+ result = employment_history.css('EmployerOrg').collect do |item|
8
+ position = item.css('PositionHistory').first
9
+ e = Employment.new
10
+ e.employer = item.css('EmployerOrgName').text
11
+ e.division = position.css('OrganizationName').text
12
+ e.division = nil if e.employer == e.division
13
+ e.city, e.state, e.country = item.css('PositionLocation Municipality, PositionLocation Region, PositionLocation CountryCode').collect(&:text)
14
+ e.title = position.css('Title').text
15
+ e.description = position.css('Description').text
16
+ e.start_date = Date.parse(position.css('StartDate').text) rescue nil
17
+ e.current_employer = position['currentEmployer'] == "true"
18
+ e.end_date = e.current_employer ? nil : (Date.parse(position.css('EndDate').text) rescue nil)
19
+ e
20
+ end
21
+ result
22
+ end
23
+
24
+ def current_employer?
25
+ !current_employer.nil? && current_employer
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ module Sovren
2
+ class Language
3
+ attr_accessor :language_code, :read, :write, :speak
4
+
5
+ def self.parse(languages)
6
+ return Array.new if languages.nil?
7
+ result = languages.css('Language').collect do |item|
8
+ c = Language.new
9
+ c.language_code = item.css('LanguageCode').text
10
+ c.read = item.css('Read').text == "true" rescue nil
11
+ c.write = item.css('Write').text == "true" rescue nil
12
+ c.speak = item.css('Speak').text == "true" rescue nil
13
+ c
14
+ end
15
+ result
16
+ end
17
+
18
+ def read?
19
+ !read.nil? && read
20
+ end
21
+
22
+ def write?
23
+ !write.nil? && write
24
+ end
25
+
26
+ def speak?
27
+ !speak.nil? && speak
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module Sovren
2
+ class Military
3
+ attr_accessor :country_served, :branch, :rank_achieved, :recognition_achieved, :discharge_status, :start_date, :end_date
4
+
5
+ def self.parse(military_history)
6
+ return nil if military_history.nil?
7
+ e = Military.new
8
+ e.country_served = military_history.css('CountryServed').text
9
+ e.branch = military_history.css('ServiceDetail').first['branch']
10
+ e.rank_achieved = military_history.css('ServiceDetail RankAchieved CurrentOrEndRank').text
11
+ e.recognition_achieved = military_history.css('ServiceDetail RecognitionAchieved').text
12
+ e.discharge_status = military_history.css('ServiceDetail DischargeStatus').text
13
+ e.start_date = Date.parse(military_history.css('DatesOfService StartDate AnyDate').text) rescue nil
14
+ e.end_date = Date.parse(military_history.css('DatesOfService EndDate AnyDate').text) rescue nil
15
+ e
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Sovren
2
+ class Patent
3
+ attr_accessor :title, :description, :inventor_name, :patent_id
4
+
5
+ def self.parse(patents)
6
+ return Array.new if patents.nil?
7
+ result = patents.css('Patent').collect do |item|
8
+ c = Patent.new
9
+ c.title = item.css('PatentTitle').text
10
+ c.description = item.css('Description').text
11
+ c.inventor_name = item.css('Inventors InventorName').first.text rescue nil
12
+ c.patent_id = item.css('PatentDetail PatentMilestone Id').text
13
+ c
14
+ end
15
+ result
16
+ end
17
+
18
+ end
19
+ end