diff --git a/lib/twitter.rb b/lib/twitter.rb index 869f23509..305d94f78 100644 --- a/lib/twitter.rb +++ b/lib/twitter.rb @@ -1,5 +1,6 @@ require File.expand_path('../twitter/error', __FILE__) require File.expand_path('../twitter/configuration', __FILE__) +require File.expand_path('../twitter/api', __FILE__) require File.expand_path('../twitter/client', __FILE__) require File.expand_path('../twitter/search', __FILE__) require File.expand_path('../twitter/base', __FILE__) diff --git a/lib/twitter/api.rb b/lib/twitter/api.rb new file mode 100644 index 000000000..d9d3794d0 --- /dev/null +++ b/lib/twitter/api.rb @@ -0,0 +1,20 @@ +require File.expand_path('../connection', __FILE__) +require File.expand_path('../request', __FILE__) +require File.expand_path('../authentication', __FILE__) + +module Twitter + class API + attr_accessor *Configuration::VALID_OPTIONS_KEYS + + def initialize(options={}) + options = Twitter.options.merge(options) + Configuration::VALID_OPTIONS_KEYS.each do |key| + send("#{key}=", options[key]) + end + end + + include Connection + include Request + include Authentication + end +end diff --git a/lib/twitter/authentication.rb b/lib/twitter/authentication.rb new file mode 100644 index 000000000..c1f47a829 --- /dev/null +++ b/lib/twitter/authentication.rb @@ -0,0 +1,18 @@ +module Twitter + module Authentication + private + + def authentication + { + :consumer_key => consumer_key, + :consumer_secret => consumer_secret, + :token => oauth_token, + :token_secret => oauth_token_secret + } + end + + def authenticated? + authentication.values.all? + end + end +end diff --git a/lib/twitter/client.rb b/lib/twitter/client.rb index ababaf1af..f135e2350 100644 --- a/lib/twitter/client.rb +++ b/lib/twitter/client.rb @@ -1,19 +1,12 @@ -Dir[File.expand_path('../client/*.rb', __FILE__)].each{|f| require f} - module Twitter - class Client - attr_accessor *Configuration::VALID_OPTIONS_KEYS + class Client < API + # Require client method modules after initializing the Client class in + # order to avoid a superclass mismatch error, allowing those modules to be + # Client-namespaced. + Dir[File.expand_path('../client/*.rb', __FILE__)].each{|f| require f} - def initialize(options={}) - options = Twitter.options.merge(options) - Configuration::VALID_OPTIONS_KEYS.each do |key| - send("#{key}=", options[key]) - end - end + alias :api_endpoint :endpoint - include Connection - include Request - include Authentication include Utils include Timeline diff --git a/lib/twitter/client/authentication.rb b/lib/twitter/client/authentication.rb deleted file mode 100644 index 2e3cdf415..000000000 --- a/lib/twitter/client/authentication.rb +++ /dev/null @@ -1,19 +0,0 @@ -module Twitter - class Client - module Authentication - private - def authentication - { - :consumer_key => consumer_key, - :consumer_secret => consumer_secret, - :token => oauth_token, - :token_secret => oauth_token_secret - } - end - - def authenticated? - authentication.values.all? - end - end - end -end diff --git a/lib/twitter/client/connection.rb b/lib/twitter/client/connection.rb deleted file mode 100644 index d4222880a..000000000 --- a/lib/twitter/client/connection.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'faraday_middleware' -Dir[File.expand_path('../../../faraday/*.rb', __FILE__)].each{|f| require f} - -module Twitter - class Client - module Connection - private - - def connection(raw=false) - options = { - :headers => {:user_agent => user_agent}, - :ssl => {:verify => false}, - :url => endpoint - } - - Faraday::Connection.new(options) do |builder| - builder.use Faraday::Request::Multipart - builder.use Faraday::Request::OAuth, authentication if authenticated? - builder.adapter(adapter) - builder.use Faraday::Response::RaiseHttp5xx - builder.use Faraday::Response::Parse unless raw - builder.use Faraday::Response::RaiseHttp4xx - builder.use Faraday::Response::Mashify unless raw - end - end - end - end -end diff --git a/lib/twitter/client/request.rb b/lib/twitter/client/request.rb deleted file mode 100644 index 0c3665774..000000000 --- a/lib/twitter/client/request.rb +++ /dev/null @@ -1,40 +0,0 @@ -module Twitter - class Client - module Request - def get(path, options={}, raw=false) - request(:get, path, options, raw) - end - - def post(path, options={}, raw=false) - request(:post, path, options, raw) - end - - def put(path, options={}, raw=false) - request(:put, path, options, raw) - end - - def delete(path, options={}, raw=false) - request(:delete, path, options, raw) - end - - private - - def request(method, path, options, raw) - response = connection(raw).send(method) do |request| - case method - when :get, :delete - request.url(formatted_path(path), options) - when :post, :put - request.path = formatted_path(path) - request.body = options - end - end - raw ? response : response.body - end - - def formatted_path(path) - [path, format].compact.join('.') - end - end - end -end diff --git a/lib/twitter/configuration.rb b/lib/twitter/configuration.rb index f2b4f020e..9a0e27696 100644 --- a/lib/twitter/configuration.rb +++ b/lib/twitter/configuration.rb @@ -3,12 +3,14 @@ module Twitter module Configuration - VALID_OPTIONS_KEYS = [:consumer_key, :consumer_secret, :oauth_token, :oauth_token_secret, :adapter, :endpoint, :format, :user_agent].freeze - VALID_FORMATS = [:json, :xml].freeze - DEFAULT_ADAPTER = Faraday.default_adapter.freeze - DEFAULT_ENDPOINT = 'https://api.twitter.com/1/'.freeze - DEFAULT_FORMAT = :json.freeze - DEFAULT_USER_AGENT = "Twitter Ruby Gem #{Twitter::VERSION}".freeze + VALID_OPTIONS_KEYS = [:consumer_key, :consumer_secret, :oauth_token, :oauth_token_secret, :adapter, :endpoint, :search_endpoint, :format, :user_agent].freeze + VALID_FORMATS = [:json, :xml].freeze + + DEFAULT_ADAPTER = Faraday.default_adapter.freeze + DEFAULT_ENDPOINT = 'https://api.twitter.com/1/'.freeze + DEFAULT_SEARCH_ENDPOINT = 'https://search.twitter.com/'.freeze + DEFAULT_FORMAT = :json.freeze + DEFAULT_USER_AGENT = "Twitter Ruby Gem #{Twitter::VERSION}".freeze attr_accessor *VALID_OPTIONS_KEYS @@ -25,10 +27,11 @@ def options end def reset - self.adapter = DEFAULT_ADAPTER - self.endpoint = DEFAULT_ENDPOINT - self.format = DEFAULT_FORMAT - self.user_agent = DEFAULT_USER_AGENT + self.adapter = DEFAULT_ADAPTER + self.endpoint = DEFAULT_ENDPOINT + self.search_endpoint = DEFAULT_SEARCH_ENDPOINT + self.format = DEFAULT_FORMAT + self.user_agent = DEFAULT_USER_AGENT end end end diff --git a/lib/twitter/connection.rb b/lib/twitter/connection.rb new file mode 100644 index 000000000..309b4e94b --- /dev/null +++ b/lib/twitter/connection.rb @@ -0,0 +1,26 @@ +require 'faraday_middleware' +Dir[File.expand_path('../../faraday/*.rb', __FILE__)].each{|f| require f} + +module Twitter + module Connection + private + + def connection(raw=false) + options = { + :headers => {:user_agent => user_agent}, + :ssl => {:verify => false}, + :url => api_endpoint + } + + Faraday::Connection.new(options) do |builder| + builder.use Faraday::Request::Multipart + builder.use Faraday::Request::OAuth, authentication if authenticated? + builder.adapter(adapter) + builder.use Faraday::Response::RaiseHttp5xx + builder.use Faraday::Response::Parse unless raw + builder.use Faraday::Response::RaiseHttp4xx + builder.use Faraday::Response::Mashify unless raw + end + end + end +end diff --git a/lib/twitter/request.rb b/lib/twitter/request.rb new file mode 100644 index 000000000..9128e3ac9 --- /dev/null +++ b/lib/twitter/request.rb @@ -0,0 +1,38 @@ +module Twitter + module Request + def get(path, options={}, raw=false) + request(:get, path, options, raw) + end + + def post(path, options={}, raw=false) + request(:post, path, options, raw) + end + + def put(path, options={}, raw=false) + request(:put, path, options, raw) + end + + def delete(path, options={}, raw=false) + request(:delete, path, options, raw) + end + + private + + def request(method, path, options, raw) + response = connection(raw).send(method) do |request| + case method + when :get, :delete + request.url(formatted_path(path), options) + when :post, :put + request.path = formatted_path(path) + request.body = options + end + end + raw ? response : response.body + end + + def formatted_path(path) + [path, format].compact.join('.') + end + end +end diff --git a/lib/twitter/search.rb b/lib/twitter/search.rb index 198a65f14..3c9ed279f 100644 --- a/lib/twitter/search.rb +++ b/lib/twitter/search.rb @@ -1,30 +1,22 @@ require 'cgi' -require File.expand_path('../search/request', __FILE__) -Dir[File.expand_path('../search/*.rb', __FILE__)].each{|f| require f} module Twitter # Handles the Twitter Search API # # @see http://dev.twitter.com/doc/get/search Twitter Search API docs - class Search - attr_accessor *Configuration::VALID_OPTIONS_KEYS + class Search < API attr_reader :fetch, :query # Creates a new instance of a search # # @param [String] query the optional keyword to search - def initialize(options={}) - options = Twitter.options.merge(options) + def initialize(*) clear - Configuration::VALID_OPTIONS_KEYS.each do |key| - send("#{key}=", options[key]) - end + super end - include Connection - include Request - include Authentication + alias :api_endpoint :search_endpoint # Clears all the query filters to make a new search def clear diff --git a/lib/twitter/search/authentication.rb b/lib/twitter/search/authentication.rb deleted file mode 100644 index 5ac8ec1ba..000000000 --- a/lib/twitter/search/authentication.rb +++ /dev/null @@ -1,19 +0,0 @@ -module Twitter - class Search - module Authentication - private - def authentication - { - :consumer_key => consumer_key, - :consumer_secret => consumer_secret, - :token => oauth_token, - :token_secret => oauth_token_secret - } - end - - def authenticated? - authentication.values.all? - end - end - end -end diff --git a/lib/twitter/search/connection.rb b/lib/twitter/search/connection.rb deleted file mode 100644 index 5216da7e8..000000000 --- a/lib/twitter/search/connection.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'faraday_middleware' -Dir[File.expand_path('../../../faraday/*.rb', __FILE__)].each{|f| require f} - -module Twitter - class Search - module Connection - private - - def connection(raw=false) - options = { - :headers => {:user_agent => user_agent}, - :ssl => {:verify => false}, - :url => endpoint - } - - Faraday::Connection.new(options) do |builder| - builder.use Faraday::Request::OAuth, authentication if authenticated? - builder.adapter(adapter) - builder.use Faraday::Response::RaiseHttp5xx - builder.use Faraday::Response::Parse unless raw - builder.use Faraday::Response::RaiseHttp4xx - builder.use Faraday::Response::Mashify unless raw - end - end - end - end -end diff --git a/lib/twitter/search/request.rb b/lib/twitter/search/request.rb deleted file mode 100644 index 57d55d28a..000000000 --- a/lib/twitter/search/request.rb +++ /dev/null @@ -1,22 +0,0 @@ -module Twitter - class Search - module Request - def get(path, options={}, raw=false) - request(:get, path, options, raw) - end - - private - - def request(method, path, options, raw) - response = connection(raw).send(method) do |request| - request.url(formatted_path(path), options) - end - raw ? response : response.body - end - - def formatted_path(path) - [path, format].compact.join('.') - end - end - end -end diff --git a/spec/twitter/api_spec.rb b/spec/twitter/api_spec.rb new file mode 100644 index 000000000..d70852808 --- /dev/null +++ b/spec/twitter/api_spec.rb @@ -0,0 +1,68 @@ +require File.expand_path('../../spec_helper', __FILE__) + +describe "Twitter::API" do + before do + @keys = Twitter::Configuration::VALID_OPTIONS_KEYS + end + + context "with module configuration" do + + before do + Twitter.configure do |config| + @keys.each do |key| + config.send("#{key}=", key) + end + end + end + + after do + Twitter.reset + end + + it "should inherit module configuration" do + api = Twitter::API.new + @keys.each do |key| + api.send(key).should == key + end + end + + context "with class configuration" do + + before do + @configuration = { + :consumer_key => 'CK', + :consumer_secret => 'CS', + :oauth_token => 'OT', + :oauth_token_secret => 'OS', + :adapter => :typhoeus, + :endpoint => 'http://tumblr.com/', + :search_endpoint => 'http://google.com/', + :format => :xml, + :user_agent => 'Custom User Agent', + } + end + + context "during initialization" + + it "should override module configuration" do + api = Twitter::API.new(@configuration) + @keys.each do |key| + api.send(key).should == @configuration[key] + end + end + + context "after initilization" do + + it "should override module configuration after initialization" do + api = Twitter::API.new + @configuration.each do |key, value| + api.send("#{key}=", value) + end + @keys.each do |key| + api.send(key).should == @configuration[key] + end + end + end + end + end +end diff --git a/spec/twitter/client_spec.rb b/spec/twitter/client_spec.rb index 7a3c47c0a..1e8c6395b 100644 --- a/spec/twitter/client_spec.rb +++ b/spec/twitter/client_spec.rb @@ -1,67 +1,10 @@ require File.expand_path('../../spec_helper', __FILE__) describe "Twitter::Client" do - before do - @keys = Twitter::Configuration::VALID_OPTIONS_KEYS - end - - context "with module configuration" do - - before do - Twitter.configure do |config| - @keys.each do |key| - config.send("#{key}=", key) - end - end - end - - after do - Twitter.reset - end - - it "should inherit module configuration" do - client = Twitter::Client.new - @keys.each do |key| - client.send(key).should == key - end - end - - context "with class configuration" do - - before do - @configuration = { - :consumer_key => 'CK', - :consumer_secret => 'CS', - :oauth_token => 'OT', - :oauth_token_secret => 'OS', - :adapter => :typhoeus, - :endpoint => 'http://tumblr.com/', - :format => :xml, - :user_agent => 'Custom User Agent', - } - end - - context "during initialization" - - it "should override module configuration" do - client = Twitter::Client.new(@configuration) - @keys.each do |key| - client.send(key).should == @configuration[key] - end - end - - context "after initilization" do - - it "should override module configuration after initialization" do - client = Twitter::Client.new - @configuration.each do |key, value| - client.send("#{key}=", value) - end - @keys.each do |key| - client.send(key).should == @configuration[key] - end - end - end - end + it "should connect using the endpoint configuration" do + client = Twitter::Client.new + endpoint = URI.parse(client.api_endpoint) + connection = client.send(:connection).build_url(nil).to_s + connection.should == endpoint.to_s end end diff --git a/spec/twitter/search_spec.rb b/spec/twitter/search_spec.rb index 35fecba80..f2860bf7c 100644 --- a/spec/twitter/search_spec.rb +++ b/spec/twitter/search_spec.rb @@ -2,6 +2,13 @@ describe "Twitter::Search" do + it "should connect using the search_endpoint configuration" do + search = Twitter::Search.new + endpoint = URI.parse(search.api_endpoint) + connection = search.send(:connection).build_url(nil).to_s + connection.should == endpoint.to_s + end + context "with module configuration" do before do @@ -34,6 +41,7 @@ :oauth_token_secret => 'OS', :adapter => :typhoeus, :endpoint => 'http://tumblr.com/', + :search_endpoint => 'http://google.com/', :format => :xml, :user_agent => 'Custom User Agent', }