From 697be54c254d643e073bcc04ec0906169c61b9be Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Thu, 30 Jan 2014 23:45:37 +0000 Subject: [PATCH 01/17] First stab at bringing config connection client --- lib/linked_in/client.rb | 24 --------- lib/linked_in/configuration.rb | 95 ++++++++++++++++++++++++++++++++++ lib/linked_in/connection.rb | 29 +++++++++++ 3 files changed, 124 insertions(+), 24 deletions(-) create mode 100644 lib/linked_in/configuration.rb create mode 100644 lib/linked_in/connection.rb diff --git a/lib/linked_in/client.rb b/lib/linked_in/client.rb index 645f196d..2e80b831 100644 --- a/lib/linked_in/client.rb +++ b/lib/linked_in/client.rb @@ -22,30 +22,6 @@ def initialize(ctoken=LinkedIn.token, csecret=LinkedIn.secret, options={}) @consumer_options = options end - # - # def current_status - # path = "/people/~/current-status" - # Crack::XML.parse(get(path))['current_status'] - # 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) - # file = File.new("test/fixtures/#{filename}", "w") - # file.puts(access_token.get(path).body) - # file.close - # end - end end diff --git a/lib/linked_in/configuration.rb b/lib/linked_in/configuration.rb new file mode 100644 index 00000000..7f013d19 --- /dev/null +++ b/lib/linked_in/configuration.rb @@ -0,0 +1,95 @@ +require 'linked_in/version' + +module LinkedIn + # Defines constants and methods related to configuration + module Configuration + # An array of valid keys in the options hash when configuring a {LinkedIn::API} + VALID_OPTIONS_KEYS = [ + :adapter, + :consumer_key, + :consumer_secret, + :default_profile_fields, + :endpoint, + :format, + :gateway, + :oauth_token, + :oauth_token_secret, + :proxy, + :user_agent, + :faraday_options].freeze + + # The adapter that will be used to connect if none is set + DEFAULT_ADAPTER = :net_http + + # By default, don't set an application key + DEFAULT_CONSUMER_KEY = nil + + # By default, don't set an application secret + DEFAULT_CONSUMER_SECRET = nil + + # The endpoint that will be used to connect if none is set + # + DEFAULT_ENDPOINT = 'https://api.linkedin.com/v1'.freeze + + # The response format appended to the path and sent in the 'Accept' header if none is set + # + # @note JSON is preferred over XML because it is more concise and faster to parse. + DEFAULT_FORMAT = :json + + # By default, don't set a user oauth token + DEFAULT_OAUTH_TOKEN = nil + + # By default, don't set a user oauth secret + DEFAULT_OAUTH_TOKEN_SECRET = nil + + # By default, don't set any profile fields + DEFAULT_PROFILE_FIELDS = nil + + # By default, don't use a proxy server + DEFAULT_PROXY = nil + + # The value sent in the 'User-Agent' header if none is set + DEFAULT_USER_AGENT = "LinkedIn Ruby Gem #{LinkedIn::VERSION}".freeze + + DEFAULT_GATEWAY = nil + + DEFAULT_FARADAY_OPTIONS = {}.freeze + + # @private + attr_accessor *VALID_OPTIONS_KEYS + + # When this module is extended, set all configuration options to their default values + def self.extended(base) + base.reset + end + + # Convenience method to allow configuration options to be set in a block + def configure + yield self + end + + # Create a hash of options and their values + def options + options = {} + VALID_OPTIONS_KEYS.each{|k| options[k] = send(k)} + options + end + + # Reset all configuration options to defaults + def reset + self.adapter = DEFAULT_ADAPTER + self.consumer_key = DEFAULT_CONSUMER_KEY + self.consumer_secret = DEFAULT_CONSUMER_SECRET + self.default_profile_fields = DEFAULT_PROFILE_FIELDS + self.endpoint = DEFAULT_ENDPOINT + self.format = DEFAULT_FORMAT + self.oauth_token = DEFAULT_OAUTH_TOKEN + self.oauth_token_secret = DEFAULT_OAUTH_TOKEN_SECRET + self.proxy = DEFAULT_PROXY + self.user_agent = DEFAULT_USER_AGENT + self.gateway = DEFAULT_GATEWAY + self.faraday_options = DEFAULT_FARADAY_OPTIONS + self + end + end +end \ No newline at end of file diff --git a/lib/linked_in/connection.rb b/lib/linked_in/connection.rb new file mode 100644 index 00000000..9c39e04e --- /dev/null +++ b/lib/linked_in/connection.rb @@ -0,0 +1,29 @@ +require 'faraday' +require 'faraday_middleware' + +module LinkedIn + module Connection + private + def connection_options + { + :headers => { + 'Accept' => "application/#{format}", + 'User-Agent' => user_agent, + 'x-li-format' => 'json' + }, + :proxy => proxy, + :ssl => {:verity => false}, + :url => api_endpoint + } + end + + def connection + Faraday.new(connection_options) do |builder| + builder.use Faraday::Request::OAuth, authentication + builder.use Faraday::Request::UrlEncoded + builder.use Faraday::Response::ParseJson + builder.adapter(adapter) + end + end + end +end From 9be1bf32fd6da037f53aff8eda916fb2d36586eb Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Thu, 30 Jan 2014 23:49:24 +0000 Subject: [PATCH 02/17] Verify not verity --- lib/linked_in/connection.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/linked_in/connection.rb b/lib/linked_in/connection.rb index 9c39e04e..44ae7a3c 100644 --- a/lib/linked_in/connection.rb +++ b/lib/linked_in/connection.rb @@ -5,16 +5,16 @@ module LinkedIn module Connection private def connection_options - { + faraday_options.merge({ :headers => { 'Accept' => "application/#{format}", 'User-Agent' => user_agent, 'x-li-format' => 'json' }, :proxy => proxy, - :ssl => {:verity => false}, + :ssl => {:verify => false}, :url => api_endpoint - } + }) end def connection From 213513bec42d8d8570deeb3cd1ee4f1f1908fbeb Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Thu, 30 Jan 2014 23:57:31 +0000 Subject: [PATCH 03/17] Caching locally the connection variable --- lib/linked_in/connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/linked_in/connection.rb b/lib/linked_in/connection.rb index 44ae7a3c..d4391c93 100644 --- a/lib/linked_in/connection.rb +++ b/lib/linked_in/connection.rb @@ -18,7 +18,7 @@ def connection_options end def connection - Faraday.new(connection_options) do |builder| + @connection ||= Faraday.new(connection_options) do |builder| builder.use Faraday::Request::OAuth, authentication builder.use Faraday::Request::UrlEncoded builder.use Faraday::Response::ParseJson From 59312ed441aa4fb93a5984896e92f6b24486885c Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Thu, 30 Jan 2014 15:59:21 -0800 Subject: [PATCH 04/17] Move connection into client --- lib/linked_in/client.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/linked_in/client.rb b/lib/linked_in/client.rb index 2e80b831..b6288213 100644 --- a/lib/linked_in/client.rb +++ b/lib/linked_in/client.rb @@ -22,6 +22,28 @@ def initialize(ctoken=LinkedIn.token, csecret=LinkedIn.secret, options={}) @consumer_options = options end + def connection_options + faraday_options.merge({ + :headers => { + 'Accept' => "application/#{format}", + 'User-Agent' => user_agent, + 'x-li-format' => 'json' + }, + :proxy => proxy, + :ssl => {:verify => false}, + :url => api_endpoint + }) + end + + def connection + @connection ||= Faraday.new(connection_options) do |builder| + builder.use Faraday::Request::OAuth, authentication + builder.use Faraday::Request::UrlEncoded + builder.use Faraday::Response::ParseJson + builder.adapter(adapter) + end + end + end end From 5dacc9a980bb1911faa0d8df9f4618a903278b1f Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Fri, 31 Jan 2014 00:28:08 +0000 Subject: [PATCH 05/17] WIP Faraday connection --- .rspec | 1 + lib/linked_in/client.rb | 30 ++++++++++++++++++++++++------ lib/linked_in/helpers/request.rb | 14 ++++---------- lib/linkedin.rb | 3 ++- linkedin.gemspec | 3 +++ 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/.rspec b/.rspec index 4e1e0d2f..ba44b749 100644 --- a/.rspec +++ b/.rspec @@ -1 +1,2 @@ --color +--fail-fast diff --git a/lib/linked_in/client.rb b/lib/linked_in/client.rb index b6288213..67a8b1b0 100644 --- a/lib/linked_in/client.rb +++ b/lib/linked_in/client.rb @@ -1,4 +1,6 @@ require 'cgi' +require 'faraday' +require 'faraday_middleware' module LinkedIn @@ -21,26 +23,42 @@ def initialize(ctoken=LinkedIn.token, csecret=LinkedIn.secret, options={}) @consumer_secret = csecret @consumer_options = options end + private + + def authentication + { + :consumer_key => consumer_token, + :consumer_secret => consumer_secret, + :token => @auth_token, + :token_secret => @auth_secret + } + end + + def authenticated? + authentication.values.all? + end def connection_options - faraday_options.merge({ + LinkedIn.faraday_options.merge({ :headers => { - 'Accept' => "application/#{format}", - 'User-Agent' => user_agent, + 'Accept' => "application/#{LinkedIn.format}", + 'User-Agent' => LinkedIn.user_agent, 'x-li-format' => 'json' }, - :proxy => proxy, + :proxy => LinkedIn.proxy, :ssl => {:verify => false}, - :url => api_endpoint + :url => LinkedIn.endpoint }) end def connection + raise "Please authenticate first" unless authenticated? + @connection ||= Faraday.new(connection_options) do |builder| builder.use Faraday::Request::OAuth, authentication builder.use Faraday::Request::UrlEncoded builder.use Faraday::Response::ParseJson - builder.adapter(adapter) + builder.adapter(LinkedIn.adapter) end end diff --git a/lib/linked_in/helpers/request.rb b/lib/linked_in/helpers/request.rb index 94f66592..e604d633 100644 --- a/lib/linked_in/helpers/request.rb +++ b/lib/linked_in/helpers/request.rb @@ -3,34 +3,28 @@ module Helpers module Request - DEFAULT_HEADERS = { - 'x-li-format' => 'json' - } - - API_PATH = '/v1' - protected def get(path, options={}) - response = access_token.get("#{API_PATH}#{path}", DEFAULT_HEADERS.merge(options)) + response = connection.get(path, options) raise_errors(response) response.body end def post(path, body='', options={}) - response = access_token.post("#{API_PATH}#{path}", body, DEFAULT_HEADERS.merge(options)) + response = connection.post(path, body, options) raise_errors(response) response end def put(path, body, options={}) - response = access_token.put("#{API_PATH}#{path}", body, DEFAULT_HEADERS.merge(options)) + response = connection.put(path, body, options) raise_errors(response) response end def delete(path, options={}) - response = access_token.delete("#{API_PATH}#{path}", DEFAULT_HEADERS.merge(options)) + response = connection.delete(path, options) raise_errors(response) response end diff --git a/lib/linkedin.rb b/lib/linkedin.rb index 513f55ca..cea67420 100644 --- a/lib/linkedin.rb +++ b/lib/linkedin.rb @@ -1,7 +1,8 @@ require 'oauth' +require 'linked_in/configuration' module LinkedIn - + extend Configuration class << self attr_accessor :token, :secret, :default_profile_fields diff --git a/linkedin.gemspec b/linkedin.gemspec index c8e57ffe..cc78a173 100644 --- a/linkedin.gemspec +++ b/linkedin.gemspec @@ -5,6 +5,9 @@ Gem::Specification.new do |gem| gem.add_dependency 'hashie', ['>= 1.2', '< 2.1'] gem.add_dependency 'multi_json', '~> 1.0' gem.add_dependency 'oauth', '~> 0.4' + gem.add_dependency 'faraday', '~> 0.8' + gem.add_dependency 'faraday_middleware' + gem.add_dependency 'simple_oauth' # gem.add_development_dependency 'json', '~> 1.6' gem.add_development_dependency 'rake', '~> 10' gem.add_development_dependency 'yard' From 01e82d4ccd951e6ea26d709b54dc38448b82ae39 Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Fri, 31 Jan 2014 01:00:49 +0000 Subject: [PATCH 06/17] Proof of Concept done minus the weird fields issue --- lib/linked_in/api/communications.rb | 2 +- lib/linked_in/api/companies.rb | 6 ++--- lib/linked_in/api/groups.rb | 4 +-- lib/linked_in/api/jobs.rb | 2 +- lib/linked_in/api/query_helpers.rb | 10 ++++---- lib/linked_in/api/share_and_social_stream.rb | 8 +++--- lib/linked_in/helpers/request.rb | 8 +++--- lib/linked_in/mash.rb | 10 -------- lib/linked_in/search.rb | 9 +++---- spec/cases/api_spec.rb | 26 ++++++++++---------- spec/cases/mash_spec.rb | 10 -------- spec/cases/search_spec.rb | 12 ++++----- 12 files changed, 43 insertions(+), 64 deletions(-) diff --git a/lib/linked_in/api/communications.rb b/lib/linked_in/api/communications.rb index b6ac9983..6d805658 100644 --- a/lib/linked_in/api/communications.rb +++ b/lib/linked_in/api/communications.rb @@ -24,7 +24,7 @@ module Communications # message # @return [void] def send_message(subject, body, recipient_paths) - path = "/people/~/mailbox" + path = "people/~/mailbox" message = { 'subject' => subject, diff --git a/lib/linked_in/api/companies.rb b/lib/linked_in/api/companies.rb index 1110c100..d8f1a790 100644 --- a/lib/linked_in/api/companies.rb +++ b/lib/linked_in/api/companies.rb @@ -96,7 +96,7 @@ def company_updates_likes(update_key, options={}) # @macro share_input_fields # @return [void] def add_company_share(company_id, share) - path = "/companies/#{company_id}/shares" + path = "companies/#{company_id}/shares" defaults = {:visibility => {:code => "anyone"}} post(path, MultiJson.dump(defaults.merge(share)), "Content-Type" => "application/json") end @@ -108,7 +108,7 @@ def add_company_share(company_id, share) # @param [String] company_id Company ID # @return [void] def follow_company(company_id) - path = "/people/~/following/companies" + path = "people/~/following/companies" body = {:id => company_id } post(path, MultiJson.dump(body), "Content-Type" => "application/json") end @@ -120,7 +120,7 @@ def follow_company(company_id) # @param [String] company_id Company ID # @return [void] def unfollow_company(company_id) - path = "/people/~/following/companies/id=#{company_id}" + path = "people/~/following/companies/id=#{company_id}" delete(path) end end diff --git a/lib/linked_in/api/groups.rb b/lib/linked_in/api/groups.rb index 3483bd84..a21fd3f7 100644 --- a/lib/linked_in/api/groups.rb +++ b/lib/linked_in/api/groups.rb @@ -95,7 +95,7 @@ def post_group_discussion(group_id, discussion) # @macro share_input_fields # @return [void] def add_group_share(group_id, share) - path = "/groups/#{group_id}/posts" + path = "groups/#{group_id}/posts" post(path, MultiJson.dump(share), "Content-Type" => "application/json") end @@ -106,7 +106,7 @@ def add_group_share(group_id, share) # @param [String] group_id Group ID # @return [void] def join_group(group_id) - path = "/people/~/group-memberships/#{group_id}" + path = "people/~/group-memberships/#{group_id}" body = {'membership-state' => {'code' => 'member' }} put(path, MultiJson.dump(body), "Content-Type" => "application/json") end diff --git a/lib/linked_in/api/jobs.rb b/lib/linked_in/api/jobs.rb index 3689bc28..547b08e9 100644 --- a/lib/linked_in/api/jobs.rb +++ b/lib/linked_in/api/jobs.rb @@ -55,7 +55,7 @@ def job_suggestions(options = {}) # @param [String] job_id Job ID # @return [void] def add_job_bookmark(job_id) - path = "/people/~/job-bookmarks" + path = "people/~/job-bookmarks" body = {'job' => {'id' => job_id}} post(path, MultiJson.dump(body), "Content-Type" => "application/json") end diff --git a/lib/linked_in/api/query_helpers.rb b/lib/linked_in/api/query_helpers.rb index 93b36385..2df43bab 100644 --- a/lib/linked_in/api/query_helpers.rb +++ b/lib/linked_in/api/query_helpers.rb @@ -5,7 +5,7 @@ module QueryHelpers private def group_path(options) - path = "/groups" + path = "groups" if id = options.delete(:id) path += "/#{id}" end @@ -24,7 +24,7 @@ def simple_query(path, options={}) params = to_query(options) path += "#{path.include?("?") ? "&" : "?"}#{params}" if !params.empty? - Mash.from_json(get(path, headers)) + Mash.new(get(path, headers)) end def build_fields_params(fields) @@ -38,7 +38,7 @@ def build_fields_params(fields) end def person_path(options) - path = "/people" + path = "people" if id = options.delete(:id) path += "/id=#{id}" elsif url = options.delete(:url) @@ -51,7 +51,7 @@ def person_path(options) end def company_path(options) - path = "/companies" + path = "companies" if domain = options.delete(:domain) path += "?email-domain=#{CGI.escape(domain)}" @@ -74,7 +74,7 @@ def picture_urls_path(options) end def jobs_path(options) - path = "/jobs" + path = "jobs" if id = options.delete(:id) path += "/id=#{id}" else diff --git a/lib/linked_in/api/share_and_social_stream.rb b/lib/linked_in/api/share_and_social_stream.rb index e9f2b4d9..8d7d44dd 100644 --- a/lib/linked_in/api/share_and_social_stream.rb +++ b/lib/linked_in/api/share_and_social_stream.rb @@ -85,7 +85,7 @@ def share_likes(update_key, options={}) # @macro share_input_fields # @return [void] def add_share(share) - path = "/people/~/shares" + path = "people/~/shares" defaults = {:visibility => {:code => "anyone"}} post(path, MultiJson.dump(defaults.merge(share)), "Content-Type" => "application/json") end @@ -99,7 +99,7 @@ def add_share(share) # @param [String] comment The text of the comment # @return [void] def update_comment(update_key, comment) - path = "/people/~/network/updates/key=#{update_key}/update-comments" + path = "people/~/network/updates/key=#{update_key}/update-comments" body = {'comment' => comment} post(path, MultiJson.dump(body), "Content-Type" => "application/json") end @@ -112,7 +112,7 @@ def update_comment(update_key, comment) # particular network update # @return [void] def like_share(update_key) - path = "/people/~/network/updates/key=#{update_key}/is-liked" + path = "people/~/network/updates/key=#{update_key}/is-liked" put(path, 'true', "Content-Type" => "application/json") end @@ -125,7 +125,7 @@ def like_share(update_key) # particular network update # @return [void] def unlike_share(update_key) - path = "/people/~/network/updates/key=#{update_key}/is-liked" + path = "people/~/network/updates/key=#{update_key}/is-liked" put(path, 'false', "Content-Type" => "application/json") end end diff --git a/lib/linked_in/helpers/request.rb b/lib/linked_in/helpers/request.rb index e604d633..e0a11da4 100644 --- a/lib/linked_in/helpers/request.rb +++ b/lib/linked_in/helpers/request.rb @@ -34,15 +34,15 @@ def delete(path, options={}) def raise_errors(response) # Even if the json answer contains the HTTP status code, LinkedIn also sets this code # in the HTTP answer (thankfully). - case response.code.to_i + case response.status.to_i when 401 - data = Mash.from_json(response.body) + data = Mash.new(response.body) raise LinkedIn::Errors::UnauthorizedError.new(data), "(#{data.status}): #{data.message}" when 400 - data = Mash.from_json(response.body) + data = Mash.new(response.body) raise LinkedIn::Errors::GeneralError.new(data), "(#{data.status}): #{data.message}" when 403 - data = Mash.from_json(response.body) + data = Mash.new(response.body) raise LinkedIn::Errors::AccessDeniedError.new(data), "(#{data.status}): #{data.message}" when 404 raise LinkedIn::Errors::NotFoundError, "(#{response.code}): #{response.message}" diff --git a/lib/linked_in/mash.rb b/lib/linked_in/mash.rb index b07e8ddd..9b987850 100644 --- a/lib/linked_in/mash.rb +++ b/lib/linked_in/mash.rb @@ -6,16 +6,6 @@ module LinkedIn # The generalized pseudo-object that is returned for all query # requests. class Mash < ::Hashie::Mash - - # Convert a json string to a Mash - # - # @param [String] json_string - # @return [LinkedIn::Mash] - def self.from_json(json_string) - result_hash = ::MultiJson.decode(json_string) - new(result_hash) - end - # Returns a Date if we have year, month and day, and no conflicting key # # @return [Date] diff --git a/lib/linked_in/search.rb b/lib/linked_in/search.rb index 2cf3f821..ce72e38b 100644 --- a/lib/linked_in/search.rb +++ b/lib/linked_in/search.rb @@ -18,7 +18,7 @@ module Search # @return [LinkedIn::Mash] def search(options={}, type='people') - path = "/#{type.to_s}-search" + path = "#{type.to_s}-search" if options.is_a?(Hash) fields = options.delete(:fields) @@ -27,10 +27,9 @@ def search(options={}, type='people') options = { :keywords => options } if options.is_a?(String) options = format_options_for_query(options) - - result_json = get(to_uri(path, options)) - - Mash.from_json(result_json) + puts options.inspect + puts path.inspect + Mash.new(get(path, options)) end private diff --git a/spec/cases/api_spec.rb b/spec/cases/api_spec.rb index 7346ce2a..fe616c76 100644 --- a/spec/cases/api_spec.rb +++ b/spec/cases/api_spec.rb @@ -61,7 +61,7 @@ client.search(:first_name => "Javan").should be_an_instance_of(LinkedIn::Mash) end - it "should be able to search with an option and fetch specific fields" do + pending "should be able to search with an option and fetch specific fields" do stub_request(:get, "https://api.linkedin.com/v1/people-search:(num-results,total)?first-name=Javan").to_return( :body => "{}") client.search(:first_name => "Javan", :fields => ["num_results", "total"]).should be_an_instance_of(LinkedIn::Mash) @@ -71,14 +71,14 @@ stub_request(:post, "https://api.linkedin.com/v1/people/~/shares").to_return(:body => "", :status => 201) response = client.add_share(:comment => "Testing, 1, 2, 3") response.body.should == nil - response.code.should == "201" + response.status.should == 201 end it "should be able to share a new company status" do stub_request(:post, "https://api.linkedin.com/v1/companies/123456/shares").to_return(:body => "", :status => 201) response = client.add_company_share("123456", { :comment => "Testing, 1, 2, 3" }) response.body.should == nil - response.code.should == "201" + response.status.should == 201 end it "returns the shares for a person" do @@ -92,7 +92,7 @@ :body => "", :status => 201) response = client.update_comment('SOMEKEY', "Testing, 1, 2, 3") response.body.should == nil - response.code.should == "201" + response.status.should == 201 end it "should be able to like a network update" do @@ -100,7 +100,7 @@ with(:body => "true").to_return(:body => "", :status => 201) response = client.like_share('SOMEKEY') response.body.should == nil - response.code.should == "201" + response.status.should == 201 end it "should be able to unlike a network update" do @@ -108,7 +108,7 @@ with(:body => "false").to_return(:body => "", :status => 201) response = client.unlike_share('SOMEKEY') response.body.should == nil - response.code.should == "201" + response.status.should == 201 end it "should be able to pass down the additional arguments to OAuth's get_request_token" do @@ -187,7 +187,7 @@ response = client.follow_company(1586) response.body.should == nil - response.code.should == "201" + response.status.should == 201 end it "should be able to unfollow a company" do @@ -195,7 +195,7 @@ response = client.unfollow_company(1586) response.body.should == nil - response.code.should == "201" + response.status.should == 201 end end @@ -222,7 +222,7 @@ stub_request(:post, "https://api.linkedin.com/v1/people/~/job-bookmarks").to_return(:body => "", :status => 201) response = client.add_job_bookmark(:id => 1452577) response.body.should == nil - response.code.should == "201" + response.status.should == 201 end end @@ -249,7 +249,7 @@ response = client.join_group(123) response.body.should == nil - response.code.should == "201" + response.status.should == 201 end it "should be able to list a group profile" do @@ -276,14 +276,14 @@ stub_request(:post, "https://api.linkedin.com/v1/groups/123/posts").with(:body => expected).to_return(:body => "", :status => 201) response = client.post_group_discussion(123, expected) response.body.should == nil - response.code.should == '201' + response.status.should == 201 end it "should be able to share a new group status" do stub_request(:post, "https://api.linkedin.com/v1/groups/1/posts").to_return(:body => "", :status => 201) response = client.add_group_share(1, :comment => "Testing, 1, 2, 3") response.body.should == nil - response.code.should == "201" + response.status.should == 201 end end @@ -292,7 +292,7 @@ stub_request(:post, "https://api.linkedin.com/v1/people/~/mailbox").to_return(:body => "", :status => 201) response = client.send_message("subject", "body", ["recip1", "recip2"]) response.body.should == nil - response.code.should == "201" + response.status.should == 201 end end diff --git a/spec/cases/mash_spec.rb b/spec/cases/mash_spec.rb index 08021e39..e2fcc904 100644 --- a/spec/cases/mash_spec.rb +++ b/spec/cases/mash_spec.rb @@ -2,16 +2,6 @@ describe LinkedIn::Mash do - describe ".from_json" do - it "should convert a json string to a Mash" do - json_string = "{\"name\":\"Josh Kalderimis\"}" - mash = LinkedIn::Mash.from_json(json_string) - - mash.should have_key('name') - mash.name.should == 'Josh Kalderimis' - end - end - describe "#convert_keys" do let(:mash) do LinkedIn::Mash.new({ diff --git a/spec/cases/search_spec.rb b/spec/cases/search_spec.rb index 652274c0..bbde000d 100644 --- a/spec/cases/search_spec.rb +++ b/spec/cases/search_spec.rb @@ -85,7 +85,7 @@ client.search({:keywords => 'apple', :fields => fields}, 'company') end - it "should perform a search" do + pending "should perform a search" do results.companies.all.first.name.should == 'Apple' results.companies.all.first.description.should == 'Apple designs Macs, the best personal computers in the world, along with OS X, iLife, iWork and professional software. Apple leads the digital music revolution with its iPods and iTunes online store. Apple has reinvented the mobile phone with its revolutionary iPhone and App Store, and is defining the future of mobile media and computing devices with iPad.' results.companies.all.first.id.should == 162479 @@ -164,7 +164,7 @@ client.profile(:email => 'email=yy@zz.com', :fields => fields) end - it "should perform a people search" do + pending "should perform a people search" do results._total.should == 1 output = results["values"] output.each do |record| @@ -182,7 +182,7 @@ client.profile(:email => 'email=yy@zz.com,email=xx@yy.com', :fields => fields) end - it "should perform a multi-email search" do + pending "should perform a multi-email search" do results._total.should == 2 output = results["values"] output.count.should == 2 @@ -192,7 +192,7 @@ describe "email search returns unauthorized" do use_vcr_cassette :record => :new_episodes - it "should raise an unauthorized error" do + pending "should raise an unauthorized error" do fields = ['id'] expect {client.profile(:email => 'email=aa@bb.com', :fields => fields)}.to raise_error(LinkedIn::Errors::UnauthorizedError) end @@ -206,7 +206,7 @@ client.search(:first_name => 'Charles', :last_name => 'Garcia', :fields => fields) end - it "should perform a search" do + pending "should perform a search" do first_person = results.people.all.first results.people.all.size.should == 10 first_person.first_name.should == 'Charles' @@ -243,4 +243,4 @@ end -end \ No newline at end of file +end From b02c7d12de74e3344213337710909a45cee69733 Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Mon, 3 Feb 2014 10:25:17 -0800 Subject: [PATCH 07/17] Take out puts --- lib/linked_in/search.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/linked_in/search.rb b/lib/linked_in/search.rb index ce72e38b..76e7f4de 100644 --- a/lib/linked_in/search.rb +++ b/lib/linked_in/search.rb @@ -27,8 +27,6 @@ def search(options={}, type='people') options = { :keywords => options } if options.is_a?(String) options = format_options_for_query(options) - puts options.inspect - puts path.inspect Mash.new(get(path, options)) end From a23658b1f8a5a663cc5c12d5d1ce77b0d373b282 Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Mon, 3 Feb 2014 11:02:12 -0800 Subject: [PATCH 08/17] All things passing --- lib/linked_in/configuration.rb | 2 +- lib/linked_in/helpers/request.rb | 9 ++++----- spec/cases/api_spec.rb | 2 +- spec/cases/search_spec.rb | 12 ++++++------ 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/linked_in/configuration.rb b/lib/linked_in/configuration.rb index 7f013d19..93564223 100644 --- a/lib/linked_in/configuration.rb +++ b/lib/linked_in/configuration.rb @@ -29,7 +29,7 @@ module Configuration # The endpoint that will be used to connect if none is set # - DEFAULT_ENDPOINT = 'https://api.linkedin.com/v1'.freeze + DEFAULT_ENDPOINT = 'https://api.linkedin.com/'.freeze # The response format appended to the path and sent in the 'Accept' header if none is set # diff --git a/lib/linked_in/helpers/request.rb b/lib/linked_in/helpers/request.rb index e0a11da4..37a2e1b6 100644 --- a/lib/linked_in/helpers/request.rb +++ b/lib/linked_in/helpers/request.rb @@ -6,25 +6,25 @@ module Request protected def get(path, options={}) - response = connection.get(path, options) + response = connection.get('v1/' + path, options) raise_errors(response) response.body end def post(path, body='', options={}) - response = connection.post(path, body, options) + response = connection.post('v1/' + path, body, options) raise_errors(response) response end def put(path, body, options={}) - response = connection.put(path, body, options) + response = connection.put('v1/' + path, body, options) raise_errors(response) response end def delete(path, options={}) - response = connection.delete(path, options) + response = connection.delete('v1/' + path, options) raise_errors(response) response end @@ -53,7 +53,6 @@ def raise_errors(response) end end - # Stolen from Rack::Util.build_query def to_query(params) params.map { |k, v| diff --git a/spec/cases/api_spec.rb b/spec/cases/api_spec.rb index fe616c76..3d8fed11 100644 --- a/spec/cases/api_spec.rb +++ b/spec/cases/api_spec.rb @@ -61,7 +61,7 @@ client.search(:first_name => "Javan").should be_an_instance_of(LinkedIn::Mash) end - pending "should be able to search with an option and fetch specific fields" do + it "should be able to search with an option and fetch specific fields" do stub_request(:get, "https://api.linkedin.com/v1/people-search:(num-results,total)?first-name=Javan").to_return( :body => "{}") client.search(:first_name => "Javan", :fields => ["num_results", "total"]).should be_an_instance_of(LinkedIn::Mash) diff --git a/spec/cases/search_spec.rb b/spec/cases/search_spec.rb index bbde000d..89d4be12 100644 --- a/spec/cases/search_spec.rb +++ b/spec/cases/search_spec.rb @@ -85,7 +85,7 @@ client.search({:keywords => 'apple', :fields => fields}, 'company') end - pending "should perform a search" do + it "should perform a search" do results.companies.all.first.name.should == 'Apple' results.companies.all.first.description.should == 'Apple designs Macs, the best personal computers in the world, along with OS X, iLife, iWork and professional software. Apple leads the digital music revolution with its iPods and iTunes online store. Apple has reinvented the mobile phone with its revolutionary iPhone and App Store, and is defining the future of mobile media and computing devices with iPad.' results.companies.all.first.id.should == 162479 @@ -164,7 +164,7 @@ client.profile(:email => 'email=yy@zz.com', :fields => fields) end - pending "should perform a people search" do + it "should perform a people search" do results._total.should == 1 output = results["values"] output.each do |record| @@ -176,13 +176,13 @@ describe "by multiple email address" do use_vcr_cassette :record => :new_episodes - + let(:results) do fields = ['id'] client.profile(:email => 'email=yy@zz.com,email=xx@yy.com', :fields => fields) end - pending "should perform a multi-email search" do + it "should perform a multi-email search" do results._total.should == 2 output = results["values"] output.count.should == 2 @@ -192,7 +192,7 @@ describe "email search returns unauthorized" do use_vcr_cassette :record => :new_episodes - pending "should raise an unauthorized error" do + it "should raise an unauthorized error" do fields = ['id'] expect {client.profile(:email => 'email=aa@bb.com', :fields => fields)}.to raise_error(LinkedIn::Errors::UnauthorizedError) end @@ -206,7 +206,7 @@ client.search(:first_name => 'Charles', :last_name => 'Garcia', :fields => fields) end - pending "should perform a search" do + it "should perform a search" do first_person = results.people.all.first results.people.all.size.should == 10 first_person.first_name.should == 'Charles' From 8df14cd171a301febb089091f8f46c04565a337f Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Mon, 3 Feb 2014 11:14:28 -0800 Subject: [PATCH 09/17] Finishing up and giving the ability to add new middleware --- lib/linked_in/configuration.rb | 11 ++++++++++- lib/linked_in/connection.rb | 9 ++++++--- spec/helper.rb | 1 + 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/linked_in/configuration.rb b/lib/linked_in/configuration.rb index 93564223..0e8577fc 100644 --- a/lib/linked_in/configuration.rb +++ b/lib/linked_in/configuration.rb @@ -1,4 +1,6 @@ require 'linked_in/version' +require 'faraday' +require 'faraday_middleware' module LinkedIn # Defines constants and methods related to configuration @@ -16,7 +18,8 @@ module Configuration :oauth_token_secret, :proxy, :user_agent, - :faraday_options].freeze + :faraday_options, + :middleware].freeze # The adapter that will be used to connect if none is set DEFAULT_ADAPTER = :net_http @@ -55,6 +58,11 @@ module Configuration DEFAULT_FARADAY_OPTIONS = {}.freeze + DEFAULT_MIDDLEWARE = [ + ::Faraday::Request::UrlEncoded, + ::Faraday::Response::ParseJson + ] + # @private attr_accessor *VALID_OPTIONS_KEYS @@ -89,6 +97,7 @@ def reset self.user_agent = DEFAULT_USER_AGENT self.gateway = DEFAULT_GATEWAY self.faraday_options = DEFAULT_FARADAY_OPTIONS + self.middleware = DEFAULT_MIDDLEWARE self end end diff --git a/lib/linked_in/connection.rb b/lib/linked_in/connection.rb index d4391c93..62bc734e 100644 --- a/lib/linked_in/connection.rb +++ b/lib/linked_in/connection.rb @@ -19,9 +19,12 @@ def connection_options def connection @connection ||= Faraday.new(connection_options) do |builder| - builder.use Faraday::Request::OAuth, authentication - builder.use Faraday::Request::UrlEncoded - builder.use Faraday::Response::ParseJson + Faraday::Request::OAuth, authentication + + middleware.each do |middle| + builder.use middle + end + builder.adapter(adapter) end end diff --git a/spec/helper.rb b/spec/helper.rb index 159e70b9..dc0e2b21 100644 --- a/spec/helper.rb +++ b/spec/helper.rb @@ -1,5 +1,6 @@ $:.unshift File.expand_path('..', __FILE__) $:.unshift File.expand_path('../../lib', __FILE__) + if ENV['COVERAGE'] == 't' require 'simplecov' SimpleCov.start From 038f84f64d4c8d5fe87daae5a6a060a5becf817d Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Mon, 3 Feb 2014 11:18:37 -0800 Subject: [PATCH 10/17] Take out to_query and to_uri helpers --- lib/linked_in/api/query_helpers.rb | 6 +++--- lib/linked_in/helpers/request.rb | 24 ++---------------------- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/lib/linked_in/api/query_helpers.rb b/lib/linked_in/api/query_helpers.rb index 2df43bab..b65c31c0 100644 --- a/lib/linked_in/api/query_helpers.rb +++ b/lib/linked_in/api/query_helpers.rb @@ -21,10 +21,10 @@ def simple_query(path, options={}) end headers = options.delete(:headers) || {} - params = to_query(options) - path += "#{path.include?("?") ? "&" : "?"}#{params}" if !params.empty? + # params = to_query(options) + # path += "#{path.include?("?") ? "&" : "?"}#{params}" if !params.empty? - Mash.new(get(path, headers)) + Mash.new(get(path, options, headers)) end def build_fields_params(fields) diff --git a/lib/linked_in/helpers/request.rb b/lib/linked_in/helpers/request.rb index 37a2e1b6..a7d92e3b 100644 --- a/lib/linked_in/helpers/request.rb +++ b/lib/linked_in/helpers/request.rb @@ -5,8 +5,8 @@ module Request protected - def get(path, options={}) - response = connection.get('v1/' + path, options) + def get(path, query_params, headers = {}) + response = connection.get('v1/' + path, query_params, headers) raise_errors(response) response.body end @@ -52,26 +52,6 @@ def raise_errors(response) raise LinkedIn::Errors::UnavailableError, "(#{response.code}): #{response.message}" end end - - # Stolen from Rack::Util.build_query - def to_query(params) - params.map { |k, v| - if v.class == Array - to_query(v.map { |x| [k, x] }) - else - v.nil? ? escape(k) : "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" - end - }.join("&") - end - - def to_uri(path, options) - uri = URI.parse(path) - - if options && options != {} - uri.query = to_query(options) - end - uri.to_s - end end end From d3c9b1a21f74f73bbb8d644dfe6b9b3703cfb4fd Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Mon, 3 Feb 2014 11:44:19 -0800 Subject: [PATCH 11/17] Refactor error reporting --- lib/linked_in/client.rb | 7 ++- lib/linked_in/configuration.rb | 4 +- lib/linked_in/connection.rb | 32 ----------- lib/linked_in/helpers/request.rb | 67 ++++++---------------- lib/linked_in/middleware/error_reporter.rb | 23 ++++++++ lib/linkedin.rb | 2 +- spec/cases/error_reporter_spec.rb | 42 ++++++++++++++ 7 files changed, 92 insertions(+), 85 deletions(-) delete mode 100644 lib/linked_in/connection.rb create mode 100644 lib/linked_in/middleware/error_reporter.rb create mode 100644 spec/cases/error_reporter_spec.rb diff --git a/lib/linked_in/client.rb b/lib/linked_in/client.rb index 67a8b1b0..8e7328e2 100644 --- a/lib/linked_in/client.rb +++ b/lib/linked_in/client.rb @@ -28,7 +28,7 @@ def initialize(ctoken=LinkedIn.token, csecret=LinkedIn.secret, options={}) def authentication { :consumer_key => consumer_token, - :consumer_secret => consumer_secret, + :consumer_secret => consumer_secret, :token => @auth_token, :token_secret => @auth_secret } @@ -56,8 +56,9 @@ def connection @connection ||= Faraday.new(connection_options) do |builder| builder.use Faraday::Request::OAuth, authentication - builder.use Faraday::Request::UrlEncoded - builder.use Faraday::Response::ParseJson + LinkedIn.middleware.each do |middle| + builder.use middle + end builder.adapter(LinkedIn.adapter) end end diff --git a/lib/linked_in/configuration.rb b/lib/linked_in/configuration.rb index 0e8577fc..599c73b6 100644 --- a/lib/linked_in/configuration.rb +++ b/lib/linked_in/configuration.rb @@ -1,6 +1,7 @@ require 'linked_in/version' require 'faraday' require 'faraday_middleware' +require 'linked_in/middleware/error_reporter' module LinkedIn # Defines constants and methods related to configuration @@ -60,7 +61,8 @@ module Configuration DEFAULT_MIDDLEWARE = [ ::Faraday::Request::UrlEncoded, - ::Faraday::Response::ParseJson + ::Faraday::Response::ParseJson, + ::LinkedIn::ErrorReporter ] # @private diff --git a/lib/linked_in/connection.rb b/lib/linked_in/connection.rb deleted file mode 100644 index 62bc734e..00000000 --- a/lib/linked_in/connection.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'faraday' -require 'faraday_middleware' - -module LinkedIn - module Connection - private - def connection_options - faraday_options.merge({ - :headers => { - 'Accept' => "application/#{format}", - 'User-Agent' => user_agent, - 'x-li-format' => 'json' - }, - :proxy => proxy, - :ssl => {:verify => false}, - :url => api_endpoint - }) - end - - def connection - @connection ||= Faraday.new(connection_options) do |builder| - Faraday::Request::OAuth, authentication - - middleware.each do |middle| - builder.use middle - end - - builder.adapter(adapter) - end - end - end -end diff --git a/lib/linked_in/helpers/request.rb b/lib/linked_in/helpers/request.rb index a7d92e3b..14711c2d 100644 --- a/lib/linked_in/helpers/request.rb +++ b/lib/linked_in/helpers/request.rb @@ -5,54 +5,25 @@ module Request protected - def get(path, query_params, headers = {}) - response = connection.get('v1/' + path, query_params, headers) - raise_errors(response) - response.body - end - - def post(path, body='', options={}) - response = connection.post('v1/' + path, body, options) - raise_errors(response) - response - end - - def put(path, body, options={}) - response = connection.put('v1/' + path, body, options) - raise_errors(response) - response - end - - def delete(path, options={}) - response = connection.delete('v1/' + path, options) - raise_errors(response) - response - end - - private - - def raise_errors(response) - # Even if the json answer contains the HTTP status code, LinkedIn also sets this code - # in the HTTP answer (thankfully). - case response.status.to_i - when 401 - data = Mash.new(response.body) - raise LinkedIn::Errors::UnauthorizedError.new(data), "(#{data.status}): #{data.message}" - when 400 - data = Mash.new(response.body) - raise LinkedIn::Errors::GeneralError.new(data), "(#{data.status}): #{data.message}" - when 403 - data = Mash.new(response.body) - raise LinkedIn::Errors::AccessDeniedError.new(data), "(#{data.status}): #{data.message}" - when 404 - raise LinkedIn::Errors::NotFoundError, "(#{response.code}): #{response.message}" - when 500 - raise LinkedIn::Errors::InformLinkedInError, "LinkedIn had an internal error. Please let them know in the forum. (#{response.code}): #{response.message}" - when 502..503 - raise LinkedIn::Errors::UnavailableError, "(#{response.code}): #{response.message}" - end - end + def get(path, query_params, headers = {}) + response = connection.get('v1/' + path, query_params, headers) + response.body + end + + def post(path, body='', options={}) + response = connection.post('v1/' + path, body, options) + response + end + + def put(path, body, options={}) + response = connection.put('v1/' + path, body, options) + response + end + + def delete(path, options={}) + response = connection.delete('v1/' + path, options) + response + end end - end end diff --git a/lib/linked_in/middleware/error_reporter.rb b/lib/linked_in/middleware/error_reporter.rb new file mode 100644 index 00000000..5c5a1106 --- /dev/null +++ b/lib/linked_in/middleware/error_reporter.rb @@ -0,0 +1,23 @@ +module LinkedIn + class ErrorReporter < Faraday::Middleware + def call(env) + @app.call(env).on_complete do + response = env[:response] + case response.status + when 401 + raise LinkedIn::Errors::UnauthorizedError.new(response), "(#{response.status}): #{response.body}" + when 400 + raise LinkedIn::Errors::GeneralError.new(response), "(#{response.status}): #{response.body}" + when 403 + raise LinkedIn::Errors::AccessDeniedError.new(response), "(#{response.status}): #{response.body}" + when 404 + raise LinkedIn::Errors::NotFoundError, "(#{response.status}): #{response.body}" + when 500 + raise LinkedIn::Errors::InformLinkedInError, "LinkedIn had an internal error. Please let them know in the forum. (#{response.status}): #{response.body}" + when 502..503 + raise LinkedIn::Errors::UnavailableError, "(#{response.status}): #{response.body}" + end + end + end + end +end \ No newline at end of file diff --git a/lib/linkedin.rb b/lib/linkedin.rb index cea67420..ef4e5554 100644 --- a/lib/linkedin.rb +++ b/lib/linkedin.rb @@ -33,4 +33,4 @@ def configure autoload :Helpers, "linked_in/helpers" autoload :Search, "linked_in/search" autoload :Version, "linked_in/version" -end +end \ No newline at end of file diff --git a/spec/cases/error_reporter_spec.rb b/spec/cases/error_reporter_spec.rb new file mode 100644 index 00000000..6cebfe98 --- /dev/null +++ b/spec/cases/error_reporter_spec.rb @@ -0,0 +1,42 @@ +require 'helper' + +describe LinkedIn::Client do + before do + LinkedIn.default_profile_fields = nil + client.stub(:consumer).and_return(consumer) + client.authorize_from_access('atoken', 'asecret') + end + + let(:client){LinkedIn::Client.new('token', 'secret')} + let(:consumer){OAuth::Consumer.new('token', 'secret', {:site => 'https://api.linkedin.com'})} + + it 'raises an unauthorized error when 401' do + stub_request(:get, "https://api.linkedin.com/v1/people/~").to_return(:body => "{}", :status => 401) + ->{ client.profile }.should raise_error(LinkedIn::Errors::UnauthorizedError) + end + + it 'raises a general error when 400' do + stub_request(:get, "https://api.linkedin.com/v1/people/~").to_return(:body => "{}", :status => 400) + ->{ client.profile }.should raise_error(LinkedIn::Errors::GeneralError) + end + + it 'raises a access denied error when 403' do + stub_request(:get, "https://api.linkedin.com/v1/people/~").to_return(:body => "{}", :status => 403) + ->{ client.profile }.should raise_error(LinkedIn::Errors::AccessDeniedError) + end + + it 'raises a notfounderror when 404' do + stub_request(:get, "https://api.linkedin.com/v1/people/~").to_return(:body => "{}", :status => 404) + ->{ client.profile }.should raise_error(LinkedIn::Errors::NotFoundError) + end + + it 'raises a informlinkedinerror if 500' do + stub_request(:get, "https://api.linkedin.com/v1/people/~").to_return(:body => "{}", :status => 500) + ->{ client.profile }.should raise_error(LinkedIn::Errors::InformLinkedInError) + end + + it 'raises an unavailable error if either 502 or 503' do + stub_request(:get, "https://api.linkedin.com/v1/people/~").to_return(:body => "{}", :status => 502) + ->{ client.profile }.should raise_error(LinkedIn::Errors::UnavailableError) + end +end \ No newline at end of file From 2abab01a954374f4d3c9417f986c0af6940b9d49 Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Mon, 3 Feb 2014 11:56:33 -0800 Subject: [PATCH 12/17] Use mashify instead of Mash.new --- lib/linked_in/api/query_helpers.rb | 2 +- lib/linked_in/client.rb | 8 +++++++- lib/linked_in/configuration.rb | 2 -- lib/linked_in/errors.rb | 8 +------- lib/linked_in/search.rb | 2 +- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/linked_in/api/query_helpers.rb b/lib/linked_in/api/query_helpers.rb index b65c31c0..57234081 100644 --- a/lib/linked_in/api/query_helpers.rb +++ b/lib/linked_in/api/query_helpers.rb @@ -24,7 +24,7 @@ def simple_query(path, options={}) # params = to_query(options) # path += "#{path.include?("?") ? "&" : "?"}#{params}" if !params.empty? - Mash.new(get(path, options, headers)) + get(path, options, headers) end def build_fields_params(fields) diff --git a/lib/linked_in/client.rb b/lib/linked_in/client.rb index 8e7328e2..44b639fd 100644 --- a/lib/linked_in/client.rb +++ b/lib/linked_in/client.rb @@ -55,10 +55,16 @@ def connection raise "Please authenticate first" unless authenticated? @connection ||= Faraday.new(connection_options) do |builder| - builder.use Faraday::Request::OAuth, authentication + builder.use ::Faraday::Request::OAuth, authentication + builder.use ::Faraday::Request::UrlEncoded + + builder.use ::FaradayMiddleware::Mashify, :mash_class => LinkedIn::Mash + builder.use ::Faraday::Response::ParseJson + LinkedIn.middleware.each do |middle| builder.use middle end + builder.adapter(LinkedIn.adapter) end end diff --git a/lib/linked_in/configuration.rb b/lib/linked_in/configuration.rb index 599c73b6..e1efbe22 100644 --- a/lib/linked_in/configuration.rb +++ b/lib/linked_in/configuration.rb @@ -60,8 +60,6 @@ module Configuration DEFAULT_FARADAY_OPTIONS = {}.freeze DEFAULT_MIDDLEWARE = [ - ::Faraday::Request::UrlEncoded, - ::Faraday::Response::ParseJson, ::LinkedIn::ErrorReporter ] diff --git a/lib/linked_in/errors.rb b/lib/linked_in/errors.rb index bded0658..59c422aa 100644 --- a/lib/linked_in/errors.rb +++ b/lib/linked_in/errors.rb @@ -1,12 +1,6 @@ module LinkedIn module Errors - class LinkedInError < StandardError - attr_reader :data - def initialize(data) - @data = data - super - end - end + class LinkedInError < StandardError; end # Raised when a 401 response status code is received class UnauthorizedError < LinkedInError; end diff --git a/lib/linked_in/search.rb b/lib/linked_in/search.rb index 76e7f4de..9a2d5561 100644 --- a/lib/linked_in/search.rb +++ b/lib/linked_in/search.rb @@ -27,7 +27,7 @@ def search(options={}, type='people') options = { :keywords => options } if options.is_a?(String) options = format_options_for_query(options) - Mash.new(get(path, options)) + get(path, options) end private From 57da072d28e5df19a39b0b268b0d1c057d49f56b Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Thu, 20 Feb 2014 17:45:53 -0800 Subject: [PATCH 13/17] Take out whitespace --- lib/linked_in/client.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/linked_in/client.rb b/lib/linked_in/client.rb index 44b639fd..fcdb4bba 100644 --- a/lib/linked_in/client.rb +++ b/lib/linked_in/client.rb @@ -57,7 +57,6 @@ def connection @connection ||= Faraday.new(connection_options) do |builder| builder.use ::Faraday::Request::OAuth, authentication builder.use ::Faraday::Request::UrlEncoded - builder.use ::FaradayMiddleware::Mashify, :mash_class => LinkedIn::Mash builder.use ::Faraday::Response::ParseJson From 26e741cd26f8609404031126cfc28cda52a35916 Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Thu, 20 Feb 2014 17:46:36 -0800 Subject: [PATCH 14/17] Cleanup brackets on spec --- spec/cases/error_reporter_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/cases/error_reporter_spec.rb b/spec/cases/error_reporter_spec.rb index 6cebfe98..fb008429 100644 --- a/spec/cases/error_reporter_spec.rb +++ b/spec/cases/error_reporter_spec.rb @@ -7,8 +7,8 @@ client.authorize_from_access('atoken', 'asecret') end - let(:client){LinkedIn::Client.new('token', 'secret')} - let(:consumer){OAuth::Consumer.new('token', 'secret', {:site => 'https://api.linkedin.com'})} + let(:client) { LinkedIn::Client.new('token', 'secret') } + let(:consumer) { OAuth::Consumer.new('token', 'secret', :site => 'https://api.linkedin.com') } it 'raises an unauthorized error when 401' do stub_request(:get, "https://api.linkedin.com/v1/people/~").to_return(:body => "{}", :status => 401) @@ -39,4 +39,4 @@ stub_request(:get, "https://api.linkedin.com/v1/people/~").to_return(:body => "{}", :status => 502) ->{ client.profile }.should raise_error(LinkedIn::Errors::UnavailableError) end -end \ No newline at end of file +end From 3b7c35d5abb0d8a21884ba3b32458c15d6b6a2b2 Mon Sep 17 00:00:00 2001 From: Jason Nochlin Date: Mon, 3 Feb 2014 19:43:01 -0500 Subject: [PATCH 15/17] Remove failfast option --- .rspec | 1 - 1 file changed, 1 deletion(-) diff --git a/.rspec b/.rspec index ba44b749..4e1e0d2f 100644 --- a/.rspec +++ b/.rspec @@ -1,2 +1 @@ --color ---fail-fast From 43b6985dd2c5f44e08655ef90e955eb0c46eee1e Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Thu, 20 Feb 2014 18:02:05 -0800 Subject: [PATCH 16/17] Raise multi_json to ~>1.8 --- linkedin.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linkedin.gemspec b/linkedin.gemspec index cc78a173..acaf529a 100644 --- a/linkedin.gemspec +++ b/linkedin.gemspec @@ -3,7 +3,7 @@ require File.expand_path('../lib/linked_in/version', __FILE__) Gem::Specification.new do |gem| gem.add_dependency 'hashie', ['>= 1.2', '< 2.1'] - gem.add_dependency 'multi_json', '~> 1.0' + gem.add_dependency 'multi_json', '~> 1.8' gem.add_dependency 'oauth', '~> 0.4' gem.add_dependency 'faraday', '~> 0.8' gem.add_dependency 'faraday_middleware' From b201ca197d7fb3e64f61451fe2464862f74fa2ac Mon Sep 17 00:00:00 2001 From: Matt Kirk Date: Thu, 20 Feb 2014 18:02:58 -0800 Subject: [PATCH 17/17] Bump Version --- lib/linked_in/version.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/linked_in/version.rb b/lib/linked_in/version.rb index 48fcafc5..7235f150 100644 --- a/lib/linked_in/version.rb +++ b/lib/linked_in/version.rb @@ -2,8 +2,8 @@ module LinkedIn module VERSION #:nodoc: MAJOR = 0 - MINOR = 4 - PATCH = 5 + MINOR = 5 + PATCH = 0 PRE = nil STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.') end