hayesdavis-grackle 0.0.1 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.txt CHANGED
@@ -1,7 +1,8 @@
1
- grackle
2
- by Hayes Davis
3
- http://www.appozite.com
4
- http://hayesdavis.net
1
+ =grackle
2
+ by Hayes Davis
3
+ hayes@appozite.com
4
+ http://www.appozite.com
5
+ http://hayesdavis.net
5
6
 
6
7
  == DESCRIPTION
7
8
  Grackle is a lightweight Ruby wrapper around the Twitter REST and Search APIs. It's based on my experience using the
@@ -17,6 +18,7 @@ will potentially require, however, some modifications to your code that uses Gra
17
18
  ==USING GRACKLE
18
19
 
19
20
  ===Creating a Grackle::Client
21
+
20
22
  require 'grackle'
21
23
  client = Grackle::Client(:username=>'your_user',:password=>'yourpass')
22
24
 
@@ -27,10 +29,10 @@ Grackle uses a method syntax that corresponds to the Twitter API URLs with a few
27
29
  a Twitter URL, that becomes a "." in a chained set of Grackle method calls. Each call in the method chain is used to build
28
30
  Twitter URL path until a particular call is encountered which causes the request to be sent. Methods which will cause a
29
31
  request to be execute include:
30
- *A method call ending in "?" will cause an HTTP GET to be executed
31
- *A method call ending in "!" will cause an HTTP POST to be executed
32
- *If a valid format such as .json, .xml, .rss or .atom is encounted, a get will be executed with that format
33
- *A format method can also include a ? or ! to determine GET or POST in that format respectively
32
+ - A method call ending in "?" will cause an HTTP GET to be executed
33
+ - A method call ending in "!" will cause an HTTP POST to be executed
34
+ - If a valid format such as .json, .xml, .rss or .atom is encounted, a get will be executed with that format
35
+ - A format method can also include a ? or ! to determine GET or POST in that format respectively
34
36
 
35
37
  ===GETting Data
36
38
  Invoking the API method "/users/show" in XML format for the Twitter user "some_user" looks like
@@ -59,17 +61,25 @@ Or, with JSON
59
61
  Or, using the default format
60
62
  client.statuses.update! :status=>'this status is from grackle' #POST to http://twitter.com/statuses/update.json
61
63
 
62
- ===Search
63
- Search works the same as everything else but your queries get submitted to search.twitter.com
64
- client.search? :q=>'grackle' #http://search.twitter.com/search.json?q=grackle
64
+ ===Toggling APIs
65
+ By default, the Grackle::Client sends all requests to the Twitter REST API. If you want to send requests to the Twitter Search API, just
66
+ set Grackle::Client.api to :search. To toggle back, set it to be :rest. All requests made after setting this
67
+ attribute will go to that API.
68
+
69
+ If you want to make a specific request to one API and not change the Client's overall api setting beyond that request, you can use the
70
+ bracket syntax like so:
71
+ client[:search].trends.daily? :exclue=>'hashtags'
72
+ client[:rest].users.show? :id=>'hayesdavis'
73
+
74
+ Search and REST requests are all built using the same method chaining and termination conventions.
65
75
 
66
76
  ===Parameter handling
67
- *All parameters are URL encoded as necessary.
68
- *If you use a File object as a parameter it will be POSTed to Twitter in a multipart request.
69
- *If you use a Time object as a parameter, .httpdate will be called on it and that value will be used
77
+ - All parameters are URL encoded as necessary.
78
+ - If you use a File object as a parameter it will be POSTed to Twitter in a multipart request.
79
+ - If you use a Time object as a parameter, .httpdate will be called on it and that value will be used
70
80
 
71
81
  ===Return Values
72
- Regardless of the format used, Grackle returns a Grackle::TwitterStruct (which is mostly just an OpenStruct) of data. The attributes
82
+ Regardless of the format used, Grackle returns an OpenStruct (actually a Grackle::TwitterStruct) of data. The attributes
73
83
  available on these structs correspond to the data returned by Twitter.
74
84
 
75
85
  ===Dealing with Errors
@@ -77,6 +87,8 @@ If the request to Twitter does not return a status code of 200, then a TwitterEr
77
87
  the full request URI, the response status, the response body in text and a response object build by parsing the formatted error
78
88
  returned by Twitter. It's a good idea to wrap your API calls with rescue clauses for Grackle::TwitterError.
79
89
 
90
+ If there is an unexpected connection error or Twitter returns data in the wrong format (which it can do), you'll still get a TwitterError.
91
+
80
92
  ===Formats
81
93
  Twitter allows you to request data in particular formats. Grackle currently supports JSON and XML. The Grackle::Client has a
82
94
  default_format you can specify. By default, the default_format is :json. If you don't include a named format in your method
@@ -85,8 +97,8 @@ chain as described above, but use a "?" or "!" then the Grackle::Client.default_
85
97
  == REQUIREMENTS:
86
98
 
87
99
  You'll need the following gems to use all features of Grackle:
88
- *json_pure
89
- *httpclient
100
+ - json_pure
101
+ - httpclient
90
102
 
91
103
  == INSTALL:
92
104
 
data/grackle.gemspec CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{grackle}
5
- s.version = "0.0.1"
5
+ s.version = "0.0.4"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Hayes Davis"]
9
- s.date = %q{2009-03-22}
10
- s.description = %q{Grackle is a library for the Twitter REST and Search API that aims to go with the flow.}
9
+ s.date = %q{2009-03-23}
10
+ s.description = %q{Grackle is a lightweight library for the Twitter REST and Search API.}
11
11
  s.email = %q{hayes@appozite.com}
12
12
  s.files = ["History.txt", "README.txt", "Rakefile", "bin/grackle", "grackle.gemspec", "lib/grackle.rb", "lib/grackle/client.rb", "lib/grackle/handlers.rb", "lib/grackle/transport.rb", "lib/grackle/utils.rb", "spec/grackle_spec.rb", "spec/spec_helper.rb", "test/test_grackle.rb"]
13
13
  s.has_rdoc = true
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.require_paths = ["lib"]
17
17
  s.rubyforge_project = %q{grackle}
18
18
  s.rubygems_version = %q{1.3.1}
19
- s.summary = %q{Grackle is a library for the Twitter REST and Search API}
19
+ s.summary = %q{Grackle is a library for the Twitter REST and Search API designed to not require a new release in the face Twitter API changes or errors.}
20
20
 
21
21
  if s.respond_to? :specification_version then
22
22
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
@@ -24,16 +24,16 @@ Gem::Specification.new do |s|
24
24
 
25
25
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
26
  s.add_runtime_dependency(%q<json>, [">= 0"])
27
- s.add_runtime_dependency(%q<httpclient>, [">= 2.1.4"])
27
+ s.add_runtime_dependency(%q<httpclient>, [">= 0"])
28
28
  s.add_development_dependency(%q<bones>, [">= 2.4.2"])
29
29
  else
30
30
  s.add_dependency(%q<json>, [">= 0"])
31
- s.add_dependency(%q<httpclient>, [">= 2.1.4"])
31
+ s.add_dependency(%q<httpclient>, [">= 0"])
32
32
  s.add_dependency(%q<bones>, [">= 2.4.2"])
33
33
  end
34
34
  else
35
35
  s.add_dependency(%q<json>, [">= 0"])
36
- s.add_dependency(%q<httpclient>, [">= 2.1.4"])
36
+ s.add_dependency(%q<httpclient>, [">= 0"])
37
37
  s.add_dependency(%q<bones>, [">= 2.4.2"])
38
38
  end
39
- end
39
+ end
@@ -7,52 +7,65 @@ module Grackle
7
7
  class TwitterError < StandardError
8
8
  attr_accessor :method, :request_uri, :status, :response_body, :response_object
9
9
 
10
- def initialize(method, request_uri, status, response_body)
10
+ def initialize(method, request_uri, status, response_body, msg=nil)
11
11
  self.method = method
12
12
  self.request_uri = request_uri
13
13
  self.status = status
14
14
  self.response_body = response_body
15
- super("#{self.method} #{self.request_uri} => #{self.status}: #{self.response_body}")
15
+ super(msg||"#{self.method} #{self.request_uri} => #{self.status}: #{self.response_body}")
16
16
  end
17
17
  end
18
18
 
19
+ # The Client is the public interface to Grackle. You build Twitter API calls using method chains. See the README for details
20
+ # and new for information on valid options.
19
21
  class Client
20
22
 
21
23
  class Request
22
- attr_accessor :path, :method
24
+ attr_accessor :path, :method, :api, :ssl
23
25
 
24
- def method
25
- @method ||= :get
26
+ def initialize(api=:rest,ssl=true)
27
+ self.api = api
28
+ self.ssl = ssl
29
+ self.method = :get
30
+ self.path = ''
26
31
  end
27
32
 
28
33
  def <<(path)
29
34
  self.path << path
30
35
  end
31
36
 
32
- def path
33
- @path ||= ''
34
- end
35
-
36
37
  def path?
37
38
  path.length > 0
38
39
  end
40
+
41
+ def url
42
+ "#{scheme}://#{host}#{path}"
43
+ end
44
+
45
+ def host
46
+ APIS[api]
47
+ end
48
+
49
+ def scheme
50
+ ssl ? 'https' :'http'
51
+ end
39
52
  end
40
53
 
41
54
  VALID_METHODS = [:get,:post,:put,:delete]
42
55
  VALID_FORMATS = [:json,:xml,:atom,:rss]
56
+
57
+ APIS = {:rest=>'twitter.com',:search=>'search.twitter.com'}
43
58
 
44
- REST_API_DOMAIN = 'twitter.com'
45
- SEARCH_API_DOMAIN = 'search.twitter.com'
46
-
47
- attr_accessor :username, :password, :handlers, :default_format, :headers, :ssl, :transport, :request
59
+ attr_accessor :username, :password, :handlers, :default_format, :headers, :ssl, :api, :transport, :request
48
60
 
49
61
  # Arguments (all are optional):
50
- # :username - twitter username to authenticate with
51
- # :password - twitter password to authenticate with
52
- # :handlers - Hash of formats to Handler instances (e.g. {:json=>CustomJSONHandler.new})
53
- # :default_format - Symbol of format to use when no format is specified in an API call (e.g. :json)
54
- # :headers - Hash of string keys and values for headers to pass in the HTTP request to twitter
55
- # :ssl - true or false to turn SSL on or off. Default is off (i.e. http://)
62
+ # - :username - twitter username to authenticate with
63
+ # - :password - twitter password to authenticate with
64
+ # - :handlers - Hash of formats to Handler instances (e.g. {:json=>CustomJSONHandler.new})
65
+ # - :default_format - Symbol of format to use when no format is specified in an API call (e.g. :json, :xml)
66
+ # - :headers - Hash of string keys and values for headers to pass in the HTTP request to twitter
67
+ # - :ssl - true or false to turn SSL on or off. Default is off (i.e. http://)
68
+ # - :api - one of :rest or :search
56
69
  def initialize(options={})
57
70
  self.transport = Transport.new
58
71
  self.username = options.delete(:username)
@@ -62,15 +75,10 @@ module Grackle
62
75
  self.default_format = options[:default_format] || :json
63
76
  self.headers = {'User-Agent'=>'Grackle/1.0'}.merge!(options[:headers]||{})
64
77
  self.ssl = options[:ssl] == true
78
+ self.api = options[:api] || :rest
65
79
  end
66
80
 
67
81
  def method_missing(name,*args)
68
- #Check for HTTP method and apply it to the request.
69
- #Can use this for an explict HTTP method
70
- if http_method_invocation?(name)
71
- self.request.method = name
72
- return self
73
- end
74
82
  #If method is a format name, execute using that format
75
83
  if format_invocation?(name)
76
84
  return call_with_format(name,*args)
@@ -92,35 +100,57 @@ module Grackle
92
100
  self
93
101
  end
94
102
 
95
- protected
96
- def rest_api_domain
97
- REST_API_DOMAIN
98
- end
103
+ # Used to toggle APIs for a particular request without setting the Client's default API
104
+ # client[:rest].users.show.hayesdavis?
105
+ def [](api_name)
106
+ request.api = api_name
107
+ self
108
+ end
99
109
 
100
- def search_api_domain
101
- SEARCH_API_DOMAIN
102
- end
103
-
110
+ #Clears any pending request built up by chained methods but not executed
111
+ def clear
112
+ self.request = nil
113
+ end
114
+
115
+ protected
104
116
  def call_with_format(format,params={})
105
117
  id = params.delete(:id)
106
- self.request << "/#{id}" if id
107
- self.request << ".#{format}"
108
- url = "#{scheme}://#{request_host}#{self.request.path}"
109
- req_info = self.request
110
- self.request = nil
111
- res = transport.request(
112
- req_info.method,url,:username=>self.username,:password=>self.password,:headers=>headers,:params=>params
113
- )
114
- fmt_handler = handler(format)
115
- unless res.status == 200
116
- handle_error_response(res,fmt_handler)
117
- else
118
- fmt_handler.decode_response(res.body)
118
+ request << "/#{id}" if id
119
+ request << ".#{format}"
120
+ res = send_request(params)
121
+ process_response(format,res)
122
+ ensure
123
+ clear
124
+ end
125
+
126
+ def send_request(params)
127
+ begin
128
+ transport.request(
129
+ request.method,request.url,:username=>self.username,:password=>self.password,:headers=>headers,:params=>params
130
+ )
131
+ rescue => e
132
+ puts e
133
+ raise TwitterError.new(request.method,request.url,nil,nil,"Unexpected failure making request: #{e}")
134
+ end
135
+ end
136
+
137
+ def process_response(format,res)
138
+ fmt_handler = handler(format)
139
+ begin
140
+ unless res.status == 200
141
+ handle_error_response(res,fmt_handler)
142
+ else
143
+ fmt_handler.decode_response(res.body)
144
+ end
145
+ rescue TwitterError => e
146
+ raise e
147
+ rescue => e
148
+ raise TwitterError.new(res.method,res.request_uri,res.status,res.body,"Unable to decode response: #{e}")
119
149
  end
120
150
  end
121
151
 
122
152
  def request
123
- @request ||= Request.new
153
+ @request ||= Request.new(api,ssl)
124
154
  end
125
155
 
126
156
  def handler(format)
@@ -133,21 +163,8 @@ module Grackle
133
163
  raise err
134
164
  end
135
165
 
136
- def http_method_invocation?(name)
137
- !self.request.path? && VALID_METHODS.include?(name)
138
- end
139
-
140
166
  def format_invocation?(name)
141
167
  self.request.path? && VALID_FORMATS.include?(name)
142
168
  end
143
-
144
- def request_host
145
- self.request.path =~ /^\/search/ ? search_api_domain : rest_api_domain
146
- end
147
-
148
- def scheme
149
- self.ssl ? 'https' :'http'
150
- end
151
-
152
169
  end
153
170
  end
@@ -3,7 +3,7 @@ module Grackle
3
3
  # This module contain handlers that know how to take a response body
4
4
  # from Twitter and turn it into a TwitterStruct return value. Handlers are
5
5
  # used by the Client to give back return values from API calls. A handler
6
- # is intended to provide a +decode+ method which accepts the response body
6
+ # is intended to provide a +decode_response+ method which accepts the response body
7
7
  # as a string.
8
8
  module Handlers
9
9
 
data/lib/grackle.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Grackle
2
2
 
3
3
  # :stopdoc:
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.4'
5
5
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
6
6
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
7
7
  # :startdoc:
@@ -24,4 +24,4 @@ require 'json'
24
24
  require 'grackle/utils'
25
25
  require 'grackle/transport'
26
26
  require 'grackle/handlers'
27
- require 'grackle/client'
27
+ require 'grackle/client'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hayesdavis-grackle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hayes Davis
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-22 00:00:00 -07:00
12
+ date: 2009-03-23 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 2.1.4
33
+ version: "0"
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: bones
@@ -42,7 +42,7 @@ dependencies:
42
42
  - !ruby/object:Gem::Version
43
43
  version: 2.4.2
44
44
  version:
45
- description: Grackle is a library for the Twitter REST and Search API that aims to go with the flow.
45
+ description: Grackle is a lightweight library for the Twitter REST and Search API.
46
46
  email: hayes@appozite.com
47
47
  executables: []
48
48
 
@@ -90,6 +90,6 @@ rubyforge_project: grackle
90
90
  rubygems_version: 1.2.0
91
91
  signing_key:
92
92
  specification_version: 2
93
- summary: Grackle is a library for the Twitter REST and Search API
93
+ summary: Grackle is a library for the Twitter REST and Search API designed to not require a new release in the face Twitter API changes or errors.
94
94
  test_files: []
95
95