linkedin 0.1.7 → 0.2.1
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/.autotest +14 -0
 - data/.document +5 -0
 - data/.gitignore +25 -0
 - data/Gemfile +3 -0
 - data/README.markdown +12 -7
 - data/Rakefile +10 -33
 - data/VERSION +1 -1
 - data/changelog.markdown +38 -0
 - data/examples/authenticate.rb +1 -1
 - data/lib/linked_in/api_standard_profile_request.rb +14 -6
 - data/lib/linked_in/authorization_helpers.rb +48 -0
 - data/lib/linked_in/base.rb +13 -0
 - data/lib/linked_in/birthdate.rb +21 -0
 - data/lib/linked_in/client.rb +86 -146
 - data/lib/linked_in/company.rb +9 -7
 - data/lib/linked_in/connections.rb +14 -5
 - data/lib/linked_in/country.rb +7 -5
 - data/lib/linked_in/current_share.rb +56 -0
 - data/lib/linked_in/education.rb +40 -14
 - data/lib/linked_in/error.rb +19 -8
 - data/lib/linked_in/group.rb +30 -7
 - data/lib/linked_in/languages.rb +28 -0
 - data/lib/linked_in/likes.rb +23 -0
 - data/lib/linked_in/location.rb +11 -6
 - data/lib/linked_in/message.rb +20 -0
 - data/lib/linked_in/network.rb +10 -5
 - data/lib/linked_in/patents.rb +42 -0
 - data/lib/linked_in/people.rb +16 -8
 - data/lib/linked_in/person.rb +7 -0
 - data/lib/linked_in/phone_number.rb +29 -0
 - data/lib/linked_in/position.rb +45 -14
 - data/lib/linked_in/profile.rb +81 -28
 - data/lib/linked_in/publications.rb +40 -0
 - data/lib/linked_in/recipient.rb +7 -0
 - data/lib/linked_in/recipients.rb +18 -0
 - data/lib/linked_in/recommendations.rb +30 -0
 - data/lib/linked_in/request_helpers.rb +76 -0
 - data/lib/linked_in/short_profile.rb +13 -0
 - data/lib/linked_in/skill.rb +33 -0
 - data/lib/linked_in/to_xml_helpers.rb +53 -0
 - data/lib/linked_in/update.rb +21 -9
 - data/lib/linked_in/url_resource.rb +24 -6
 - data/lib/linkedin.rb +58 -59
 - data/linkedin.gemspec +52 -0
 - data/spec/cases/client_spec.rb +281 -0
 - data/spec/cases/linkedin_spec.rb +37 -0
 - data/spec/cases/oauth_spec.rb +109 -0
 - data/{test → spec}/fixtures/blank.xml +0 -0
 - data/{test → spec}/fixtures/connections.xml +0 -0
 - data/{test → spec}/fixtures/error.xml +0 -0
 - data/spec/fixtures/likes.xml +18 -0
 - data/spec/fixtures/mailbox_items.xml +16 -0
 - data/{test → spec}/fixtures/network_status_with_group.xml +3 -3
 - data/{test → spec}/fixtures/network_statuses.xml +18 -0
 - data/{test → spec}/fixtures/picture_updates.xml +0 -0
 - data/{test → spec}/fixtures/profile.xml +0 -0
 - data/{test → spec}/fixtures/profile_full.xml +57 -0
 - data/{test → spec}/fixtures/profile_with_positions.xml +0 -0
 - data/{test → spec}/fixtures/search.xml +2 -2
 - data/spec/fixtures/shares.xml +12 -0
 - data/{test → spec}/fixtures/status.xml +0 -0
 - data/spec/spec_helper.rb +49 -0
 - metadata +160 -76
 - data/test/client_test.rb +0 -124
 - data/test/oauth_test.rb +0 -117
 - data/test/test_helper.rb +0 -51
 
    
        data/lib/linked_in/position.rb
    CHANGED
    
    | 
         @@ -1,15 +1,46 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module LinkedIn
         
     | 
| 
       2 
     | 
    
         
            -
              class Position
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
                 
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
                 
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
                 
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
            end
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Position < LinkedIn::Base
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def positions
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @positions ||= @doc.children.inject([]) do |list, position|
         
     | 
| 
      
 6 
     | 
    
         
            +
                    list << Resource.new(position) unless position.blank?
         
     | 
| 
      
 7 
     | 
    
         
            +
                    list
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                class Resource
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def initialize(position)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @position = position
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  %w[id title summary is_current].each do |f|
         
     | 
| 
      
 18 
     | 
    
         
            +
                    define_method(f.to_sym) do
         
     | 
| 
      
 19 
     | 
    
         
            +
                      @position.xpath("./#{f.gsub(/_/,'-')}").text
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def start_month
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @position.xpath('./start-date/month').text.to_i
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def start_year
         
     | 
| 
      
 28 
     | 
    
         
            +
                    @position.xpath('./start-date/year').text.to_i
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def end_month
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @position.xpath('./end-date/month').text.to_i
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def end_year
         
     | 
| 
      
 36 
     | 
    
         
            +
                    @position.xpath('./end-date/year').text.to_i
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  def company
         
     | 
| 
      
 40 
     | 
    
         
            +
                    @company ||= Company.new(@position.xpath('./company'))
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                end # resource
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              end # class
         
     | 
| 
      
 46 
     | 
    
         
            +
            end # module
         
     | 
    
        data/lib/linked_in/profile.rb
    CHANGED
    
    | 
         @@ -1,32 +1,85 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module LinkedIn
         
     | 
| 
       2 
     | 
    
         
            -
              class Profile
         
     | 
| 
       3 
     | 
    
         
            -
                include ROXML
         
     | 
| 
       4 
     | 
    
         
            -
                xml_convention {|val| val.gsub("_","-") }
         
     | 
| 
       5 
     | 
    
         
            -
                xml_reader :id
         
     | 
| 
       6 
     | 
    
         
            -
                xml_reader :first_name
         
     | 
| 
       7 
     | 
    
         
            -
                xml_reader :last_name
         
     | 
| 
       8 
     | 
    
         
            -
                xml_reader :headline
         
     | 
| 
       9 
     | 
    
         
            -
                xml_reader :location, :as => Location
         
     | 
| 
       10 
     | 
    
         
            -
                xml_reader :industry
         
     | 
| 
       11 
     | 
    
         
            -
                xml_reader :distance, :as => Integer
         
     | 
| 
       12 
     | 
    
         
            -
                xml_reader :relation_to_viewer, :as => {:key => :name, :value => :content}
         
     | 
| 
       13 
     | 
    
         
            -
                xml_reader :num_recommenders, :as => Integer
         
     | 
| 
       14 
     | 
    
         
            -
                xml_reader :current_status
         
     | 
| 
       15 
     | 
    
         
            -
                xml_reader :current_status_timestamp
         
     | 
| 
       16 
     | 
    
         
            -
                xml_reader :connections, :as => [Profile], :from => "connections/person"
         
     | 
| 
       17 
     | 
    
         
            -
                xml_reader :summary
         
     | 
| 
       18 
     | 
    
         
            -
                xml_reader :specialties
         
     | 
| 
       19 
     | 
    
         
            -
                xml_reader :proposal_comments
         
     | 
| 
       20 
     | 
    
         
            -
                xml_reader :associations
         
     | 
| 
       21 
     | 
    
         
            -
                xml_reader :honors
         
     | 
| 
       22 
     | 
    
         
            -
                xml_reader :interests
         
     | 
| 
       23 
     | 
    
         
            -
                xml_reader :positions, :as => [Position]
         
     | 
| 
       24 
     | 
    
         
            -
                xml_reader :education, :as => [Education]
         
     | 
| 
       25 
     | 
    
         
            -
                xml_reader :three_current_positions, :as => [Position]
         
     | 
| 
       26 
     | 
    
         
            -
                xml_reader :member_url_resources, :as => [UrlResource], :from => 'member-url-resources/member-url'
         
     | 
| 
       27 
     | 
    
         
            -
                xml_reader :api_standard_profile_request
         
     | 
| 
       28 
     | 
    
         
            -
                xml_reader :site_standard_profile_request, :as => ApiStandardProfileRequest
         
     | 
| 
       29 
     | 
    
         
            -
                xml_reader :picture_url
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Profile < LinkedIn::Base
         
     | 
| 
       30 
3 
     | 
    
         | 
| 
      
 4 
     | 
    
         
            +
                # xml_reader :three_current_positions, :as => [Position]
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                PROFILE_FIELDS = %w[id first_name last_name headline industry
         
     | 
| 
      
 7 
     | 
    
         
            +
                                    current_status current_status_timestamp summary
         
     | 
| 
      
 8 
     | 
    
         
            +
                                    specialties proposal_comments associations honors
         
     | 
| 
      
 9 
     | 
    
         
            +
                                    interests picture_url distance num_recommenders public_profile_url]
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                PROFILE_FIELDS.each do |f|
         
     | 
| 
      
 12 
     | 
    
         
            +
                  define_method(f.to_sym) do
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @doc.xpath("./person/#{f.gsub(/_/,'-')}").text
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def birthdate
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @birthday ||= Birthdate.new(@doc.xpath('./person/date-of-birth'))
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def location
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @location ||= Location.new(@doc)
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def api_standard_profile_request
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @api_standard ||= ApiStandardProfileRequest.new(@doc.xpath('./person/api-standard-profile-request'))
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def site_standard_profile_request
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @doc.xpath('//site-standard-profile-request/url').text
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def relation_to_viewer
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @doc.xpath('//relation-to-viewer/distance').text
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def member_url_resources
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @url_resources ||= UrlResource.new(@doc.xpath('//member-url-resources')).resources
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                def positions
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @positions ||= Position.new(@doc.xpath('//positions')).positions
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def educations
         
     | 
| 
      
 46 
     | 
    
         
            +
                  @educations ||= Education.new(@doc.xpath('//educations')).educations
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def connections
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @connections ||= Connections.new(@doc.xpath('//connections')).connections
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                def groups
         
     | 
| 
      
 54 
     | 
    
         
            +
                  @groups ||= Group.new(@doc.xpath('//member-groups')).groups
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                def recommendations
         
     | 
| 
      
 58 
     | 
    
         
            +
                  @recommendations ||= Recommendations.new(@doc.xpath('//recommendations-received')).recommendations
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def current_share
         
     | 
| 
      
 62 
     | 
    
         
            +
                  @current_share ||= CurrentShare.new(@doc.xpath('//current-share'))
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def languages
         
     | 
| 
      
 66 
     | 
    
         
            +
                  @languages ||= Languages.new(@doc.xpath('//languages')).languages
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                def skills
         
     | 
| 
      
 70 
     | 
    
         
            +
                  @skills ||= Skill.new(@doc.xpath('//skills')).skills
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def phone_numbers
         
     | 
| 
      
 74 
     | 
    
         
            +
                  @phone_number ||= PhoneNumber.new(@doc.xpath('//phone-numbers')).phone_numbers
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                def publications
         
     | 
| 
      
 78 
     | 
    
         
            +
                  @publications ||= Publications.new(@doc.xpath('//publications')).publications
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def patents
         
     | 
| 
      
 82 
     | 
    
         
            +
                  @patents ||= Patents.new(@doc.xpath('//patents')).patents
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
       31 
84 
     | 
    
         
             
              end
         
     | 
| 
       32 
85 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module LinkedIn
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Publications < LinkedIn::Base
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def publications
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @publications ||= @doc.children.inject([]) do |list, publication|
         
     | 
| 
      
 6 
     | 
    
         
            +
                    list << Resource.new(publication) unless publication.blank?
         
     | 
| 
      
 7 
     | 
    
         
            +
                    list
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                class Resource
         
     | 
| 
      
 12 
     | 
    
         
            +
                  def initialize(publication)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @publication = publication
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  %w[id title].each do |f|
         
     | 
| 
      
 17 
     | 
    
         
            +
                    define_method(f.to_sym) do
         
     | 
| 
      
 18 
     | 
    
         
            +
                      @publication.xpath("./#{f.gsub(/_/,'-')}").text
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def year
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @year ||= @publication.xpath("./date/year").text.to_i
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def day
         
     | 
| 
      
 27 
     | 
    
         
            +
                    @day ||= @publication.xpath("./date/day").text.to_i
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def month
         
     | 
| 
      
 31 
     | 
    
         
            +
                    @month ||= @publication.xpath("./date/month").text.to_i
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def date
         
     | 
| 
      
 35 
     | 
    
         
            +
                    Date.civil(year, month, day)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module LinkedIn
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Recipients
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                attr_accessor :recipients
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def to_xml
         
     | 
| 
      
 7 
     | 
    
         
            +
                  self.to_xml_nodes(Nokogiri.XML('<root/>', nil, 'UTF-8')).to_xml
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
                
         
     | 
| 
      
 10 
     | 
    
         
            +
                def to_xml_nodes(doc)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  recipients.inject(Nokogiri::XML::NodeSet.new(doc)) do |nodes, recipient|
         
     | 
| 
      
 12 
     | 
    
         
            +
                    node = Nokogiri::XML::DocumentFragment.new(doc, '<recipient><person/></recipient>')
         
     | 
| 
      
 13 
     | 
    
         
            +
                    node.at_css('person')['path'] = recipient.person.path
         
     | 
| 
      
 14 
     | 
    
         
            +
                    nodes << node
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module LinkedIn
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              class Recommendations < LinkedIn::Base
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def recommendations
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @recommendations ||= @doc.children.inject([]) do |list, recommendation|
         
     | 
| 
      
 7 
     | 
    
         
            +
                    list << Recommendation.new(recommendation) unless recommendation.blank?
         
     | 
| 
      
 8 
     | 
    
         
            +
                    list
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                class Recommendation
         
     | 
| 
      
 13 
     | 
    
         
            +
                  def initialize(recommendation)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @recommendation = recommendation
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  %w[id recommendation_type recommendation_text].each do |f|
         
     | 
| 
      
 18 
     | 
    
         
            +
                    define_method(f.to_sym) do
         
     | 
| 
      
 19 
     | 
    
         
            +
                      @recommendation.xpath("./#{f.gsub(/_/,'-')}").text
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def recommender
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @recommender ||= ShortProfile.new(@recommendation.xpath('./recommender'))
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,76 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module LinkedIn
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              module RequestHelpers
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def get(path, options={})
         
     | 
| 
      
 6 
     | 
    
         
            +
                  path = "/v1#{path}"
         
     | 
| 
      
 7 
     | 
    
         
            +
                  response = access_token.get(path, options)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  raise_errors(response)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  response.body
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def post(path, body='', options={})
         
     | 
| 
      
 13 
     | 
    
         
            +
                  path = "/v1#{path}"
         
     | 
| 
      
 14 
     | 
    
         
            +
                  default_options = { 'Content-Type' => 'application/xml' }
         
     | 
| 
      
 15 
     | 
    
         
            +
                  response = access_token.post(path, body, default_options.merge(options))
         
     | 
| 
      
 16 
     | 
    
         
            +
                  raise_errors(response)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  response
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def put(path, body, options={})
         
     | 
| 
      
 21 
     | 
    
         
            +
                  path = "/v1#{path}"
         
     | 
| 
      
 22 
     | 
    
         
            +
                  response = access_token.put(path, body, options)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  raise_errors(response)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  response
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def delete(path, options={})
         
     | 
| 
      
 28 
     | 
    
         
            +
                  path = "/v1#{path}"
         
     | 
| 
      
 29 
     | 
    
         
            +
                  response = access_token.delete(path, options)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  raise_errors(response)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  response
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                private
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  def raise_errors(response)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    # Even if the XML answer contains the HTTP status code, LinkedIn also sets this code
         
     | 
| 
      
 38 
     | 
    
         
            +
                    # in the HTTP answer (thankfully).
         
     | 
| 
      
 39 
     | 
    
         
            +
                    case response.code.to_i
         
     | 
| 
      
 40 
     | 
    
         
            +
                    when 400
         
     | 
| 
      
 41 
     | 
    
         
            +
                      data = LinkedIn::Error.from_xml(response.body)
         
     | 
| 
      
 42 
     | 
    
         
            +
                      raise RateLimitExceeded.new(data), "(#{response.code}): #{response.message} - #{data.code if data}"
         
     | 
| 
      
 43 
     | 
    
         
            +
                    when 401
         
     | 
| 
      
 44 
     | 
    
         
            +
                      data = LinkedIn::Error.from_xml(response.body)
         
     | 
| 
      
 45 
     | 
    
         
            +
                      raise Unauthorized.new(data), "(#{response.code}): #{response.message} - #{data.code if data}"
         
     | 
| 
      
 46 
     | 
    
         
            +
                    when 403
         
     | 
| 
      
 47 
     | 
    
         
            +
                      data = LinkedIn::Error.from_xml(response.body)
         
     | 
| 
      
 48 
     | 
    
         
            +
                      raise General.new(data), "(#{response.code}): #{response.message} - #{data.code if data}"
         
     | 
| 
      
 49 
     | 
    
         
            +
                    when 404
         
     | 
| 
      
 50 
     | 
    
         
            +
                      raise NotFound, "(#{response.code}): #{response.message}"
         
     | 
| 
      
 51 
     | 
    
         
            +
                    when 500
         
     | 
| 
      
 52 
     | 
    
         
            +
                      raise InformLinkedIn, "LinkedIn had an internal error. Please let them know in the forum. (#{response.code}): #{response.message}"
         
     | 
| 
      
 53 
     | 
    
         
            +
                    when 502..503
         
     | 
| 
      
 54 
     | 
    
         
            +
                      raise Unavailable, "(#{response.code}): #{response.message}"
         
     | 
| 
      
 55 
     | 
    
         
            +
                    end
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  def to_query(options)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    query_string = options.inject([]) do |collection, opt|
         
     | 
| 
      
 60 
     | 
    
         
            +
                      collection << "#{opt[0]}=#{opt[1]}"
         
     | 
| 
      
 61 
     | 
    
         
            +
                      collection
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end * '&'
         
     | 
| 
      
 63 
     | 
    
         
            +
                    URI.escape(query_string)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  def to_uri(path, options)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    uri = URI.parse(path)
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                    if options && options != {}
         
     | 
| 
      
 70 
     | 
    
         
            +
                      uri.query = to_query(options)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
                    uri.to_s
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module LinkedIn
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Skill < LinkedIn::Base
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def skills
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @array ||= begin
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @array = []
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @doc.children.each do |skill|
         
     | 
| 
      
 8 
     | 
    
         
            +
                      @array << Resource.new(skill) unless skill.blank?
         
     | 
| 
      
 9 
     | 
    
         
            +
                    end
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @array
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                class Resource
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def initialize(skill)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @skill = skill
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def name
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @skill.xpath("./skill/name").text
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  
         
     | 
| 
      
 24 
     | 
    
         
            +
                  %w[id].each do |f| #proficiency level to come? http://developer.linkedin.com/community/apis/blog/2011/01/04/new-profile-fields-are-here
         
     | 
| 
      
 25 
     | 
    
         
            +
                    define_method(f.to_sym) do
         
     | 
| 
      
 26 
     | 
    
         
            +
                      @skill.xpath("./#{f.gsub(/_/,'-')}").text
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  
         
     | 
| 
      
 30 
     | 
    
         
            +
                end # resource class
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              end # skill class
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module LinkedIn
         
     | 
| 
      
 2 
     | 
    
         
            +
              module ToXmlHelpers
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                private
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def status_to_xml(status)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  doc = Nokogiri.XML('<current-status/>', nil, 'UTF-8')
         
     | 
| 
      
 8 
     | 
    
         
            +
                  doc.root.content = status
         
     | 
| 
      
 9 
     | 
    
         
            +
                  doc.to_xml
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def message_to_xml(message)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  doc = Nokogiri.XML('')
         
     | 
| 
      
 14 
     | 
    
         
            +
                  doc.encoding = 'UTF-8'
         
     | 
| 
      
 15 
     | 
    
         
            +
                  doc.root = message.to_xml_node(doc)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  doc.to_xml
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def share_to_xml(options={})
         
     | 
| 
      
 20 
     | 
    
         
            +
                  doc = Nokogiri.XML('<share><comment/><content><title/><submitted-url/><submitted-image-url/></content><visibility><code/></visibility></share>')
         
     | 
| 
      
 21 
     | 
    
         
            +
                  doc.encoding = 'UTF-8'
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  {:comment => 'comment', :title => 'title', :url => 'submitted-url', :image_url => 'submitted-image-url'}.each do |key, name|
         
     | 
| 
      
 24 
     | 
    
         
            +
                    doc.at_css(name).content = options[key] if options[key]
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  doc.at_css('visibility > code').content = options[:visibility] || options[:visability] # backward-compatible typo fix
         
     | 
| 
      
 28 
     | 
    
         
            +
                  doc.to_xml
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def comment_to_xml(comment)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  doc = Nokogiri.XML('<update-comment><comment/><update-comment/>')
         
     | 
| 
      
 33 
     | 
    
         
            +
                  doc.encoding = 'UTF-8'
         
     | 
| 
      
 34 
     | 
    
         
            +
                  doc.at_css('comment').content = comment
         
     | 
| 
      
 35 
     | 
    
         
            +
                  doc.to_xml
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def is_liked_to_xml(is_liked)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  doc = Nokogiri.XML('<is-liked/>')
         
     | 
| 
      
 40 
     | 
    
         
            +
                  doc.encoding = 'UTF-8'
         
     | 
| 
      
 41 
     | 
    
         
            +
                  doc.at_css('is-liked').content = is_liked
         
     | 
| 
      
 42 
     | 
    
         
            +
                  doc.to_xml
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def network_update_to_xml(message)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  doc = Nokogiri::XML('<activity locale="en_US"><content-type>linkedin-html</content-type><body/></activity>')
         
     | 
| 
      
 47 
     | 
    
         
            +
                  doc.encoding = 'UTF-8'
         
     | 
| 
      
 48 
     | 
    
         
            +
                  doc.at_css('body').content = message
         
     | 
| 
      
 49 
     | 
    
         
            +
                  doc.to_xml
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     |