Skip to content

Commit

Permalink
Network, Search, Updates APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
Wynn Netherland committed Nov 26, 2009
1 parent e743c1f commit ea547f7
Show file tree
Hide file tree
Showing 13 changed files with 1,117 additions and 5 deletions.
1 change: 1 addition & 0 deletions Rakefile
Expand Up @@ -15,6 +15,7 @@ begin

gem.add_dependency('oauth', '~> 0.3.5')
gem.add_dependency('roxml', '~> 3.1.3')
gem.add_dependency('crack', '~> 0.1.4')

gem.add_development_dependency('thoughtbot-shoulda', '>= 2.10.1')
gem.add_development_dependency('jnunemaker-matchy', '0.4.0')
Expand Down
10 changes: 10 additions & 0 deletions changelog.markdown
@@ -1,6 +1,16 @@
## Changelog

### 0.1.0 - November 25, 2009

* Network updates API support
* Search API support
* Updates API support

### 0.0.2 - November 25, 2009

* Swapped out Crack for ROXML for prettier object access
* Added more tests for Profile API

### 0.0.1 - November 24, 2009

* Initial release
86 changes: 81 additions & 5 deletions lib/linked_in/client.rb
Expand Up @@ -51,6 +51,20 @@ def get(path, options={})
response.body
end

def put(path, options={})
path = "/v1#{path}"
response = access_token.put(path, options)
raise_errors(response)
response
end

def delete(path, options={})
path = "/v1#{path}"
response = access_token.delete(path, options)
raise_errors(response)
response
end


def profile(options={})

Expand Down Expand Up @@ -81,6 +95,42 @@ def connections(options={})
Connections.from_xml(get(path)).profiles
end

def search(options={})
path = "/people"
options = {:keywords => options} if options.is_a?(String)
options = format_options_for_query(options)

People.from_xml(get(to_uri(path, options)))
end

def current_status
path = "/people/~/current-status"
Crack::XML.parse(get(path))['current_status']
end

def update_status(text)
path = "/people/~/current-status"
put(path, status_to_xml(text))
end

def clear_status
path = "/people/~/current-status"
delete(path).code
end

def network_statuses(options={})
options[:type] = 'STAT'
network_updates(options)
end

def network_updates(options={})
path = "/people/~/network"
Network.from_xml(get(to_uri(path, options)))
end




# helpful in making authenticated calls and writing the
# raw xml to a fixture file
def write_fixture(path, filename)
Expand All @@ -100,15 +150,37 @@ def raise_errors(response)
raise Unavailable, "(#{response.code}): #{response.message}"
end

if response.body.include?("<error>")
if response.body && response.body.include?("<error>")
error = LinkedIn::Error.from_xml(response.body)
case error.status
when 404
Raise LinkedInError, "(#{error.status}): #{error.code} - #{error.message}"
end
Raise LinkedInError, "(#{error.status}): #{error.code} - #{error.message}"
end
end

def format_options_for_query(opts)
opts.keys.each do |key|
value = opts.delete(key)
value = value.join("+") if value.is_a?(Array)
value = value.gsub(" ", "+") if value.is_a?(String)
opts[key.to_s.gsub("_","-")] = value
end
opts
end

def to_query(options)
options.inject([]) do |collection, opt|
collection << "#{opt[0]}=#{opt[1]}"
collection
end * '&'
end

def to_uri(path, options)
uri = URI.parse(path)

if options && options != {}
uri.query = to_query(options)
end
uri.to_s
end

def person_path(options)
path = "/people/"
Expand All @@ -123,6 +195,10 @@ def person_path(options)
end
end

def status_to_xml(status)
%Q{<?xml version="1.0" encoding="UTF-8"?>
<current-status>#{status}</current-status>}
end


end
Expand Down
7 changes: 7 additions & 0 deletions lib/linked_in/network.rb
@@ -0,0 +1,7 @@
module LinkedIn
class Network
include ROXML
xml_convention {|val| val.gsub("_","-") }
xml_reader :updates, :as => [Update]
end
end
10 changes: 10 additions & 0 deletions lib/linked_in/people.rb
@@ -0,0 +1,10 @@
module LinkedIn
class People
include ROXML
xml_convention {|val| val.gsub("_","-") }
xml_reader :total, :as => Integer, :from => "@total"
xml_reader :start, :as => Integer, :from => "@start"
xml_reader :count, :as => Integer, :from => "@count"
xml_reader :profiles, :as => [Profile], :from => 'person'
end
end
11 changes: 11 additions & 0 deletions lib/linked_in/update.rb
@@ -0,0 +1,11 @@
module LinkedIn
class Update
include ROXML
xml_convention {|val| val.gsub("_","-") }
xml_reader :timestamp, :as => Integer
xml_reader :update_key
xml_reader :update_type
xml_reader :profile, :as => Profile, :from => 'update-content/person'
xml_reader :is_commentable?
end
end
6 changes: 6 additions & 0 deletions lib/linkedin.rb
Expand Up @@ -7,6 +7,9 @@
gem 'roxml', '~> 3.1.3'
require 'roxml'

gem 'crack', '~> 0.1.4'
require 'crack'

require 'cgi'

module LinkedIn
Expand Down Expand Up @@ -38,5 +41,8 @@ class NotFound < StandardError; end
require File.join(directory, 'linked_in', 'location')
require File.join(directory, 'linked_in', 'position')
require File.join(directory, 'linked_in', 'profile')
require File.join(directory, 'linked_in', 'update')
require File.join(directory, 'linked_in', 'network')
require File.join(directory, 'linked_in', 'people')
require File.join(directory, 'linked_in', 'connections')
require File.join(directory, 'linked_in', 'client')
55 changes: 55 additions & 0 deletions test/client_test.rb
Expand Up @@ -44,6 +44,61 @@ class ClientTest < Test::Unit::TestCase
cons.size.should == 146
cons.last.last_name.should == 'Yuchnewicz'
end

should "perform a search by keyword" do
stub_get("/v1/people?keywords=github", "search.xml")
results = @linkedin.search(:keywords => 'github')
results.start == 0
results.count == 10
results.profiles.first.first_name.should == 'Zach'
results.profiles.first.last_name.should == 'Inglis'
end

should "perform a search by multiple keywords" do
stub_get("/v1/people?keywords=ruby+rails", "search.xml")
results = @linkedin.search(:keywords => ["ruby", "rails"])
results.start == 0
results.count == 10
results.profiles.first.first_name.should == 'Zach'
results.profiles.first.last_name.should == 'Inglis'
end

should "perform a search by name" do
stub_get("/v1/people?name=Zach+Inglis", "search.xml")
results = @linkedin.search(:name => "Zach Inglis")
results.start == 0
results.count == 10
results.profiles.first.first_name.should == 'Zach'
results.profiles.first.last_name.should == 'Inglis'
end

should "update a user's current status" do
stub_put("/v1/people/~/current-status", "blank.xml")
@linkedin.update_status("Testing out the LinkedIn API")
end

should "clear a user's current status" do
stub_delete("/v1/people/~/current-status", "blank.xml")
@linkedin.clear_status
end

should "retrieve the authenticated user's current status" do
stub_get("/v1/people/~/current-status", "status.xml")
@linkedin.current_status.should == "New blog post: What makes a good API wrapper? http://wynnnetherland.com/2009/11/what-makes-a-good-api-wrapper/"
end

should "retrieve status updates for the authenticated user's network" do
stub_get("/v1/people/~/network?type=STAT", "network_statuses.xml")
stats = @linkedin.network_statuses
stats.updates.first.profile.first_name.should == 'Vahid'
end

should "retrieve network updates" do
stub_get("/v1/people/~/network?type=PICT", "picture_updates.xml")
stats = @linkedin.network_updates(:type => "PICT")
stats.updates.size.should == 4
stats.updates.last.profile.headline.should == "Creative Director for Intridea"
end

end

Expand Down
Empty file added test/fixtures/blank.xml
Empty file.

0 comments on commit ea547f7

Please sign in to comment.