grackle 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +6 -0
- data/README.rdoc +87 -59
- data/lib/grackle/client.rb +16 -9
- data/lib/grackle/version.rb +2 -2
- data/test/client_test.rb +49 -32
- metadata +76 -63
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 0.3.0 (2013-03-31)
|
2
|
+
* Make Twitter API 1.1 endpoint the default. This will be a breaking change if you expect 1.0 out of the box
|
3
|
+
|
4
|
+
== 0.2.2 (2013-01-24, Unreleased)
|
5
|
+
* Add :v1_1 api endpoint to client mapping to api.twitter.com/1.1; the default is still :v1. (Thanks @jcsalterego)
|
6
|
+
|
1
7
|
== 0.2.1 (2012-08-14)
|
2
8
|
* Add :valid_http_codes option that tells grackle not to raise an error when encountering those statuses.
|
3
9
|
|
data/README.rdoc
CHANGED
@@ -3,22 +3,22 @@ by Hayes Davis
|
|
3
3
|
- http://twitter.com/hayesdavis
|
4
4
|
- hayes [at] unionmetrics [dot] com
|
5
5
|
- http://unionmetrics.com
|
6
|
-
- http://hayesdavis.
|
6
|
+
- http://hayesdavis.tumblr.com
|
7
7
|
|
8
8
|
== DESCRIPTION
|
9
|
-
Grackle is a lightweight Ruby wrapper around the Twitter REST
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
9
|
+
Grackle is a lightweight Ruby wrapper around the Twitter REST API. It's based on
|
10
|
+
my experience using the Twitter API to build http://tweetreach.com. The main
|
11
|
+
goal of Grackle is to never require a release when the Twitter API changes
|
12
|
+
(which it often does) or in the face of a particular Twitter API bug. As such
|
13
|
+
it's somewhat different from other Twitter API libraries. It doesn't try to hide
|
14
|
+
the Twitter "methods" under an access layer nor does it introduce concrete
|
15
|
+
classes for the various objects returned by Twitter. Instead, calls to the
|
16
|
+
Grackle client map directly to Twitter API URLs. The objects returned by API
|
17
|
+
calls are generated as OpenStructs on the fly and make no assumptions about the
|
18
|
+
presence or absence of any particular attributes. Taking this approach means
|
19
|
+
that changes to URLs used by Twitter, parameters required by those URLs or
|
20
|
+
return values will not require a new release. It will potentially require,
|
21
|
+
however, some modifications to your code that uses Grackle.
|
22
22
|
|
23
23
|
=== Support and Announcements
|
24
24
|
The preferred forum for questions and discussions is the Google group at
|
@@ -26,7 +26,14 @@ http://groups.google.com/group/gracklerb. You can email me directly or @reply me
|
|
26
26
|
on Twitter, but the group is better since the questions and responses will be
|
27
27
|
available to everyone. I'll also make announcements there. There are some
|
28
28
|
examples on the wiki at http://wiki.github.com/hayesdavis/grackle. If you prefer
|
29
|
-
your information in 140 characters, follow
|
29
|
+
your information in 140 characters, follow
|
30
|
+
@gracklerb[http://twitter.com/gracklerb].
|
31
|
+
|
32
|
+
=== Twitter API 1.1 and Grackle 0.3.0
|
33
|
+
Grackle 0.3.0 defaults to Twitter API 1.1 out of the box. If you have code that
|
34
|
+
still relies on API 1.0, you can upgrade Grackle and still use API 1.0 by
|
35
|
+
specifying that the client use the :v1 API:
|
36
|
+
client = Grackle::Client.new(:api=>:v1)
|
30
37
|
|
31
38
|
==USING GRACKLE
|
32
39
|
|
@@ -40,12 +47,15 @@ Before you do anything else, you'll need to
|
|
40
47
|
:consumer_key=>'SOMECONSUMERKEYFROMTWITTER', :consumer_secret=>'SOMECONSUMERTOKENFROMTWITTER',
|
41
48
|
:token=>'ACCESSTOKENACQUIREDONUSERSBEHALF', :token_secret=>'SUPERSECRETACCESSTOKENSECRET'
|
42
49
|
})
|
43
|
-
|
44
|
-
OAuth can be a bit complicated. See the wiki[http://wiki.github.com/hayesdavis/grackle/grackle-and-oauth]
|
45
|
-
for more information on acquiring the keys, tokens and secrets needed to
|
50
|
+
|
51
|
+
OAuth can be a bit complicated. See the wiki[http://wiki.github.com/hayesdavis/grackle/grackle-and-oauth]
|
52
|
+
for more information on acquiring the keys, tokens and secrets needed to
|
46
53
|
successfully authenticate with OAuth.
|
47
54
|
|
48
|
-
====Using No Auth
|
55
|
+
====Using No Auth (DEPRECATED)
|
56
|
+
As of May 7th, 2013, Twitter will be shutting down all API 1 endpoints and
|
57
|
+
requiring all clients to use API 1.1 which requires OAuth authentication for all
|
58
|
+
API calls.
|
49
59
|
client = Grackle::Client.new
|
50
60
|
|
51
61
|
====Using Basic Auth (DEPRECATED)
|
@@ -55,23 +65,24 @@ As of August 31st, 2010, Twitter has deprecated basic authentication in favor of
|
|
55
65
|
See Grackle::Client for more information about valid arguments to the constructor. It's quite configurable. Among other things, you can turn on ssl and specify custom headers. The calls below are pretty much as simple as it gets.
|
56
66
|
|
57
67
|
===Grackle Method Syntax
|
58
|
-
Grackle uses a method syntax that corresponds to the Twitter API URLs with a few
|
59
|
-
a Twitter URL, that becomes a "." in a
|
60
|
-
|
61
|
-
|
68
|
+
Grackle uses a method syntax that corresponds to the Twitter API URLs with a few
|
69
|
+
twists. Where you would have a slash in a Twitter URL, that becomes a "." in a
|
70
|
+
chained set of Grackle method calls. Each call in the method chain is used to
|
71
|
+
build Twitter URL path until a particular call is encountered which causes the
|
72
|
+
request to be sent. Methods which will cause a request to be execute include:
|
62
73
|
- A method call ending in "?" will cause an HTTP GET to be executed
|
63
74
|
- A method call ending in "!" will cause an HTTP POST to be executed
|
64
75
|
- If a valid format such as .json, .xml, .rss or .atom is encounted, a get will be executed with that format
|
65
76
|
- A format method can also include a ? or ! to determine GET or POST in that format respectively
|
66
77
|
|
67
78
|
===GETting Data
|
68
|
-
The preferred and simplest way of executing a GET is to use the "?" method notation. This will use the default client
|
79
|
+
The preferred and simplest way of executing a GET is to use the "?" method notation. This will use the default client
|
69
80
|
format (usually JSON, but see Formats section below):
|
70
81
|
client.users.show? :screen_name=>'some_user' #http://twitter.com/users/show.json?screen_name=some_user
|
71
82
|
|
72
83
|
You can force XML format by doing:
|
73
84
|
client.users.show.xml? :screen_name=>'some_user' #http://twitter.com/users/show.xml?screen_name=some_user
|
74
|
-
|
85
|
+
|
75
86
|
You can force JSON:
|
76
87
|
client.users.show.json? :screen_name=>'some_user' #http://twitter.com/users/show.json?screen_name=some_user
|
77
88
|
|
@@ -92,37 +103,42 @@ You can force a format. To update the authenticated user's status using the XML
|
|
92
103
|
|
93
104
|
Or, with JSON
|
94
105
|
client.statuses.update.json! :status=>'this status is from grackle' #POST to http://twitter.com/statuses/update.json
|
95
|
-
|
106
|
+
|
96
107
|
===Using Other HTTP Verbs
|
97
108
|
To use HTTP verbs like DELETE or PUT, Grackle provides a slightly different syntax:
|
98
109
|
client.put{ hayesdavis.lists.my_list :name=>'New Name' } #HTTP PUT
|
99
110
|
client.delete{ direct_messages.destroy :id=>1 } #HTTP DELETE
|
100
|
-
|
101
|
-
You may specify any method chain you wish in the block. Note that if your method chain inside the block
|
111
|
+
|
112
|
+
You may specify any method chain you wish in the block. Note that if your method chain inside the block
|
102
113
|
ends in a ! or ?, that the HTTP verb for the block will still be used. This means that
|
103
114
|
client.delete{ direct_messages.destroy! :id=>1 } #Uses HTTP DELETE, not POST
|
104
115
|
client.direct_messages.destroy! :id=>1 #Uses HTTP POST
|
105
116
|
|
106
|
-
If for some reason you don't like the preferred block syntax above, you may specify a
|
117
|
+
If for some reason you don't like the preferred block syntax above, you may specify a
|
107
118
|
parameter to your method chain called :__method (note the double underscores) to specify the HTTP verb:
|
108
119
|
client.direct_messages.destroy! :id=>1, :__method=>:delete #HTTP DELETE
|
109
120
|
|
110
121
|
===Toggling APIs
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
122
|
+
As of Grackle 0.3.0, the Grackle::Client sends all requests to the 1.1 Twitter
|
123
|
+
API by default. If you want to send requests to the Twitter 1.0 API (which has
|
124
|
+
been deprecated by Twitter and will be unavailable after May 7th, 2013), just
|
125
|
+
use the Grackle::Client#api= method and set it to :v1. To toggle back, set it
|
126
|
+
to :v1_1. All requests made after setting this attribute will go to that API.
|
115
127
|
|
116
|
-
|
117
|
-
|
118
|
-
after setting this attribute will go to that API.
|
128
|
+
For convenience, you can also set the desired API in the Client constructor:
|
129
|
+
client = Grackle::Client.new(:api=>:v1)
|
119
130
|
|
120
|
-
If you want to make a specific request to one API and not change the Client's
|
121
|
-
bracket syntax like so:
|
122
|
-
client[:
|
123
|
-
client[:
|
124
|
-
|
125
|
-
|
131
|
+
If you want to make a specific request to one API and not change the Client's
|
132
|
+
overall api setting beyond that request, you can use the bracket syntax like so:
|
133
|
+
client[:v1].users.show? :screen_name=>'hayesdavis'
|
134
|
+
client[:v1_1].users.show? :screen_name=>'hayesdavis'
|
135
|
+
|
136
|
+
All APIs use the same method chaining and termination conventions.
|
137
|
+
|
138
|
+
DEPRECATION NOTICE: The :rest API key (pointing to twitter.com), the :search API
|
139
|
+
key (pointing to search.twitter.com) and the :v1 API key
|
140
|
+
(pointing to api.twitter.com/1) have all been deprecated in favor of the
|
141
|
+
the :v1_1 API (pointing to api.twitter.com/1.1).
|
126
142
|
|
127
143
|
===Parameter handling
|
128
144
|
- All parameters are URL encoded as necessary.
|
@@ -130,8 +146,9 @@ Search and REST requests are all built using the same method chaining and termin
|
|
130
146
|
- If you use a Time object as a parameter, .httpdate will be called on it and that value will be used
|
131
147
|
|
132
148
|
===Return Values
|
133
|
-
Regardless of the format used, Grackle returns an OpenStruct (actually a
|
134
|
-
available on these structs
|
149
|
+
Regardless of the format used, Grackle returns an OpenStruct (actually a
|
150
|
+
Grackle::TwitterStruct) of data. The attributes available on these structs
|
151
|
+
correspond to the data returned by Twitter.
|
135
152
|
|
136
153
|
===Rate Limits and the Response
|
137
154
|
The Grackle client has a response method which is populated with information
|
@@ -142,7 +159,13 @@ because they can be used to retrieve the rate limit information that Twitter
|
|
142
159
|
includes in a response.
|
143
160
|
|
144
161
|
user = client.users.show.hayesdavis?
|
145
|
-
client.response.headers["X-
|
162
|
+
client.response.headers["X-Rate-Limit-Remaining"] # 1.1 API
|
163
|
+
|
164
|
+
user = client[:v1].users.show.hayesdavis?
|
165
|
+
client.response.headers["X-Ratelimit-Remaining"] # 1.0 API
|
166
|
+
|
167
|
+
Note that Twitter has renamed the rate limit headers in API 1.1 to use
|
168
|
+
"rate-limit" instead of API 1.0's "ratelimit".
|
146
169
|
|
147
170
|
Not all headers returned by Twitter are included by default. You can control
|
148
171
|
which headers are accessible with the response_headers attribute on the Client.
|
@@ -151,28 +174,33 @@ header values will be Strings so you'll need to convert rate limits, etc to ints
|
|
151
174
|
in your code.
|
152
175
|
|
153
176
|
===Dealing with Errors
|
154
|
-
If the request to Twitter does not return a status code of 200, then a
|
155
|
-
|
156
|
-
|
177
|
+
If the request to Twitter does not return a status code of 200, then a
|
178
|
+
TwitterError is thrown. This contains the HTTP method used, the full request
|
179
|
+
URI, the response status, the response body in text and a response object build
|
180
|
+
by parsing the formatted error returned by Twitter. It's a good idea to wrap
|
181
|
+
your API calls with rescue clauses for Grackle::TwitterError.
|
157
182
|
|
158
|
-
If there is an unexpected connection error or Twitter returns data in the wrong
|
183
|
+
If there is an unexpected connection error or Twitter returns data in the wrong
|
184
|
+
format (which it can do), you'll still get a TwitterError.
|
159
185
|
|
160
186
|
===Formats
|
161
|
-
Twitter allows you to request data in particular formats. Grackle automatically
|
162
|
-
parses JSON and XML formatted responses and returns an OpenStruct. The
|
163
|
-
Grackle::Client has a default_format you can specify. By default, the
|
164
|
-
default_format is :json. If you don't include a named format in your method
|
165
|
-
chain as described above, but use a "?" or "!" then the
|
187
|
+
Twitter allows you to request data in particular formats. Grackle automatically
|
188
|
+
parses JSON and XML formatted responses and returns an OpenStruct. The
|
189
|
+
Grackle::Client has a default_format you can specify. By default, the
|
190
|
+
default_format is :json. If you don't include a named format in your method
|
191
|
+
chain as described above, but use a "?" or "!" then the
|
166
192
|
Grackle::Client.default_format is used.
|
167
193
|
|
168
|
-
If you specify a format that Grackle doesn't parse for you, you'll receive a
|
169
|
-
string containing the raw response body. If you want to receive the raw
|
170
|
-
response body even for XML or JSON formatted responses, tell the Grackle client
|
171
|
-
to use the +StringHandler+ handler. For example, the following code sets the
|
194
|
+
If you specify a format that Grackle doesn't parse for you, you'll receive a
|
195
|
+
string containing the raw response body. If you want to receive the raw
|
196
|
+
response body even for XML or JSON formatted responses, tell the Grackle client
|
197
|
+
to use the +StringHandler+ handler. For example, the following code sets the
|
172
198
|
Grackle client to return JSON instead of an OpenStruct:
|
173
199
|
|
174
200
|
client = Grackle::Client.new(:handlers=>{:json=>Grackle::Handlers::StringHandler.new })
|
175
201
|
|
202
|
+
DEPRECATION NOTICE: As to Twitter API 1.1, XML is no longer an accepted format.
|
203
|
+
|
176
204
|
===Odds and Ends
|
177
205
|
If you need to append something to the request path that isn't a valid ruby method, e.g.
|
178
206
|
/1user/lists.json #1user isn't a valid Ruby method
|
@@ -183,7 +211,7 @@ you can use the Grackle::Client#_ method like so:
|
|
183
211
|
|
184
212
|
You'll need the following gems to use all features of Grackle:
|
185
213
|
- json
|
186
|
-
- oauth
|
214
|
+
- oauth
|
187
215
|
- mime-types
|
188
216
|
|
189
217
|
=== Ruby Version Support
|
data/lib/grackle/client.rb
CHANGED
@@ -87,16 +87,23 @@ module Grackle
|
|
87
87
|
# refer to it wherever Grackle::Client uses an API symbol. You may wish
|
88
88
|
# to do this when Twitter introduces API versions greater than 1.
|
89
89
|
TWITTER_API_HOSTS = {
|
90
|
-
:
|
90
|
+
:v1=>'api.twitter.com/1', :v1_1=>'api.twitter.com/1.1',
|
91
|
+
:search=>'search.twitter.com',
|
91
92
|
:upload=>'upload.twitter.com/1'
|
92
93
|
}
|
93
94
|
TWITTER_API_HOSTS[:rest] = TWITTER_API_HOSTS[:v1]
|
95
|
+
DEFAULT_API_HOST = :v1_1
|
94
96
|
|
95
97
|
# Contains the response headers from twitter
|
96
|
-
DEFAULT_RESPONSE_HEADERS =[
|
98
|
+
DEFAULT_RESPONSE_HEADERS = [
|
99
|
+
# These are API 1 rate limit header names
|
97
100
|
'x-ratelimit-limit',
|
98
101
|
'x-ratelimit-remaining',
|
99
|
-
'x-ratelimit-reset'
|
102
|
+
'x-ratelimit-reset',
|
103
|
+
# These are API 1.1 rate limit header names
|
104
|
+
'x-rate-limit-limit',
|
105
|
+
'x-rate-limit-remaining',
|
106
|
+
'x-rate-limit-reset'
|
100
107
|
]
|
101
108
|
|
102
109
|
#Basic OAuth information needed to communicate with Twitter
|
@@ -117,10 +124,10 @@ module Grackle
|
|
117
124
|
# - :default_format - Symbol of format to use when no format is specified in an API call (e.g. :json, :xml)
|
118
125
|
# - :headers - Hash of string keys and values for headers to pass in the HTTP request to twitter
|
119
126
|
# - :ssl - true or false to turn SSL on or off. Default is off (i.e. http://)
|
120
|
-
# - :api - one of :rest, :search or :
|
127
|
+
# - :api - one of :rest, :search, :v1 or :v1_1. :v1_1 is the default. :rest and :search are now deprecated
|
121
128
|
# - :auth - Hash of authentication type and credentials. Must have :type key with value one of :basic or :oauth
|
122
|
-
# - :type=>:basic - Include :username and :password keys
|
123
129
|
# - :type=>:oauth - Include :consumer_key, :consumer_secret, :token and :token_secret keys
|
130
|
+
# - :type=>:basic - DEPRECATED. Include :username and :password keys
|
124
131
|
# - :auto_append_format - true or false to include format in URI (e.g. /test.json). Default is true
|
125
132
|
# - :response_headers - array of headers to return from the response
|
126
133
|
# - :valid_http_codes - array of HTTP codes to consider valid (non-error)
|
@@ -128,11 +135,11 @@ module Grackle
|
|
128
135
|
self.transport = Transport.new
|
129
136
|
self.handlers = {:json=>Handlers::JSONHandler.new,:xml=>Handlers::XMLHandler.new,:unknown=>Handlers::StringHandler.new}
|
130
137
|
self.handlers.merge!(options[:handlers]||{})
|
131
|
-
self.default_format = options[:default_format] || :json
|
138
|
+
self.default_format = options[:default_format] || :json
|
132
139
|
self.auto_append_format = options[:auto_append_format] == false ? false : true
|
133
140
|
self.headers = {"User-Agent"=>"Grackle/#{Grackle::VERSION}"}.merge!(options[:headers]||{})
|
134
141
|
self.ssl = options[:ssl] == true
|
135
|
-
self.api = options[:api] ||
|
142
|
+
self.api = options[:api] || DEFAULT_API_HOST
|
136
143
|
self.api_hosts = TWITTER_API_HOSTS.clone
|
137
144
|
self.timeout = options[:timeout] || 60
|
138
145
|
self.auto_append_ids = options[:auto_append_ids] == false ? false : true
|
@@ -140,7 +147,7 @@ module Grackle
|
|
140
147
|
self.response_headers = options[:response_headers] || DEFAULT_RESPONSE_HEADERS.clone
|
141
148
|
self.valid_http_codes = options[:valid_http_codes] || VALID_HTTP_CODES.clone
|
142
149
|
if options.has_key?(:username) || options.has_key?(:password)
|
143
|
-
#Use basic auth if :username and :password args are passed in
|
150
|
+
# DEPRECATED: Use basic auth if :username and :password args are passed in
|
144
151
|
self.auth.merge!({:type=>:basic,:username=>options[:username],:password=>options[:password]})
|
145
152
|
end
|
146
153
|
#Handle auth mechanism that permits basic or oauth
|
@@ -151,7 +158,7 @@ module Grackle
|
|
151
158
|
end
|
152
159
|
end
|
153
160
|
end
|
154
|
-
|
161
|
+
|
155
162
|
def method_missing(name,*args,&block)
|
156
163
|
if block_given?
|
157
164
|
return request_with_http_method_block(name,&block)
|
data/lib/grackle/version.rb
CHANGED
data/test/client_test.rb
CHANGED
@@ -119,7 +119,7 @@ class ClientTest < Test::Unit::TestCase
|
|
119
119
|
assert_equal('http',client.transport.url.scheme)
|
120
120
|
assert(!Net::HTTP.last_instance.use_ssl?,'Net::HTTP instance should not be set to use SSL')
|
121
121
|
assert_equal('api.twitter.com',client.transport.url.host)
|
122
|
-
assert_equal('/1/users/show.json',client.transport.url.path)
|
122
|
+
assert_equal('/1.1/users/show.json',client.transport.url.path)
|
123
123
|
assert_equal('test_user',client.transport.options[:params][:screen_name])
|
124
124
|
assert_equal('screen_name=test_user',Net::HTTP.request.path.split(/\?/)[1])
|
125
125
|
assert_equal(12345,value.id)
|
@@ -167,30 +167,47 @@ class ClientTest < Test::Unit::TestCase
|
|
167
167
|
client.statuses.public_timeline?
|
168
168
|
assert_match(/\.xml$/,client.transport.url.path)
|
169
169
|
end
|
170
|
-
|
171
|
-
def test_api
|
172
|
-
client = new_client(200,'[{"id":1,"text":"test 1"}]',:api=>:search)
|
173
|
-
client.search? :q=>'test'
|
174
|
-
assert_equal('search.twitter.com',client.transport.url.host)
|
175
170
|
|
176
|
-
|
177
|
-
|
171
|
+
def test_api_selection_with_api_accessor_changes_api_for_subsequent_requests
|
172
|
+
client = new_client(200,'[{"id":1,"text":"test 1"}]')
|
173
|
+
|
174
|
+
# :rest and :v1 are DEPRECATED
|
175
|
+
{:rest=>"1", :v1=>"1",:v1_1=>"1.1"}.each do |api_key,version|
|
176
|
+
client.api = api_key
|
177
|
+
client.users.show.some_user?
|
178
|
+
assert_equal('api.twitter.com',client.transport.url.host)
|
179
|
+
assert_equal("/#{version}/users/show/some_user.json",client.transport.url.path)
|
180
|
+
assert_equal(api_key,client.api,"API changed for all requests")
|
181
|
+
end
|
178
182
|
|
183
|
+
# :search is DEPRECATED
|
179
184
|
client.api = :search
|
180
185
|
client.trends?
|
181
186
|
assert_equal('search.twitter.com',client.transport.url.host)
|
182
|
-
|
183
|
-
client.api
|
184
|
-
|
185
|
-
assert_equal('api.twitter.com',client.transport.url.host)
|
186
|
-
assert_match(%r{^/1/search},client.transport.url.path)
|
187
|
+
assert_equal("/trends.json",client.transport.url.path)
|
188
|
+
assert_equal(:search,client.api,"API changed to search for all requests")
|
189
|
+
end
|
187
190
|
|
188
|
-
|
189
|
-
client[:
|
190
|
-
|
191
|
-
|
191
|
+
def test_api_selection_with_api_override_changes_api_for_specific_request
|
192
|
+
client = new_client(200,'[{"id":1,"text":"test 1"}]')
|
193
|
+
|
194
|
+
original_api = client.api
|
195
|
+
|
196
|
+
# :rest and :v1 are DEPRECATED
|
197
|
+
{:rest=>"1", :v1=>"1",:v1_1=>"1.1"}.each do |api_key,version|
|
198
|
+
client[api_key].users.show.some_user?
|
199
|
+
assert_equal('api.twitter.com',client.transport.url.host)
|
200
|
+
assert_equal("/#{version}/users/show/some_user.json",client.transport.url.path)
|
201
|
+
assert_equal(original_api,client.api,"API should not change")
|
202
|
+
end
|
203
|
+
|
204
|
+
# :search is DEPRECATED
|
205
|
+
client[:search].trends?
|
206
|
+
assert_equal('search.twitter.com',client.transport.url.host)
|
207
|
+
assert_equal("/trends.json",client.transport.url.path)
|
208
|
+
assert_equal(original_api,client.api,"API should not change")
|
192
209
|
end
|
193
|
-
|
210
|
+
|
194
211
|
def test_headers
|
195
212
|
client = new_client(200,'[{"id":1,"text":"test 1"}]',:headers=>{'User-Agent'=>'TestAgent/1.0','X-Test-Header'=>'Header Value'})
|
196
213
|
client.statuses.public_timeline?
|
@@ -259,14 +276,14 @@ class ClientTest < Test::Unit::TestCase
|
|
259
276
|
client = new_client(200,'[{"id":1,"text":"test 1"}]')
|
260
277
|
time = Time.now-60*60
|
261
278
|
client.statuses.public_timeline? :since=>time
|
262
|
-
assert_equal("/1/statuses/public_timeline.json?since=#{CGI::escape(time.httpdate)}",Net::HTTP.request.path)
|
279
|
+
assert_equal("/1.1/statuses/public_timeline.json?since=#{CGI::escape(time.httpdate)}",Net::HTTP.request.path)
|
263
280
|
end
|
264
281
|
|
265
282
|
def test_simple_http_method_block
|
266
283
|
client = new_client(200,'[{"id":1,"text":"test 1"}]')
|
267
284
|
client.delete { direct_messages.destroy :id=>1, :other=>'value' }
|
268
285
|
assert_equal(:delete,client.transport.method, "delete block should use delete method")
|
269
|
-
assert_equal("/1/direct_messages/destroy/1.json",Net::HTTP.request.path)
|
286
|
+
assert_equal("/1.1/direct_messages/destroy/1.json",Net::HTTP.request.path)
|
270
287
|
assert_equal('value',client.transport.options[:params][:other])
|
271
288
|
|
272
289
|
client = new_client(200,'{"id":54321,"screen_name":"test_user"}')
|
@@ -275,7 +292,7 @@ class ClientTest < Test::Unit::TestCase
|
|
275
292
|
assert_equal('http',client.transport.url.scheme)
|
276
293
|
assert(!Net::HTTP.last_instance.use_ssl?,'Net::HTTP instance should not be set to use SSL')
|
277
294
|
assert_equal('api.twitter.com',client.transport.url.host)
|
278
|
-
assert_equal('/1/users/show.json',client.transport.url.path)
|
295
|
+
assert_equal('/1.1/users/show.json',client.transport.url.path)
|
279
296
|
assert_equal('test_user',client.transport.options[:params][:screen_name])
|
280
297
|
assert_equal('screen_name=test_user',Net::HTTP.request.path.split(/\?/)[1])
|
281
298
|
assert_equal(54321,value.id)
|
@@ -308,7 +325,7 @@ class ClientTest < Test::Unit::TestCase
|
|
308
325
|
assert_equal('http',client.transport.url.scheme)
|
309
326
|
assert(!Net::HTTP.last_instance.use_ssl?,'Net::HTTP instance should not be set to use SSL')
|
310
327
|
assert_equal('api.twitter.com',client.transport.url.host)
|
311
|
-
assert_equal('/1/users/show/12345.json',client.transport.url.path)
|
328
|
+
assert_equal('/1.1/users/show/12345.json',client.transport.url.path)
|
312
329
|
assert_equal(12345,value.id)
|
313
330
|
end
|
314
331
|
|
@@ -333,10 +350,10 @@ class ClientTest < Test::Unit::TestCase
|
|
333
350
|
def test_auto_append_ids_is_honored
|
334
351
|
client = new_client(200,'{"id":12345,"screen_name":"test_user"}')
|
335
352
|
client.users.show.json? :id=>12345
|
336
|
-
assert_equal('/1/users/show/12345.json',client.transport.url.path,"Id should be appended by default")
|
353
|
+
assert_equal('/1.1/users/show/12345.json',client.transport.url.path,"Id should be appended by default")
|
337
354
|
client.auto_append_ids = false
|
338
355
|
client.users.show.json? :id=>12345
|
339
|
-
assert_equal('/1/users/show.json',client.transport.url.path,"Id should not be appended")
|
356
|
+
assert_equal('/1.1/users/show.json',client.transport.url.path,"Id should not be appended")
|
340
357
|
assert_equal(12345,client.transport.options[:params][:id], "Id should be treated as a parameter")
|
341
358
|
assert_equal("id=#{12345}",Net::HTTP.request.path.split(/\?/)[1],"id should be part of the query string")
|
342
359
|
end
|
@@ -344,7 +361,7 @@ class ClientTest < Test::Unit::TestCase
|
|
344
361
|
def test_auto_append_ids_can_be_set_in_constructor
|
345
362
|
client = new_client(200,'{"id":12345,"screen_name":"test_user"}',:auto_append_ids=>false)
|
346
363
|
client.users.show.json? :id=>12345
|
347
|
-
assert_equal('/1/users/show.json',client.transport.url.path,"Id should not be appended")
|
364
|
+
assert_equal('/1.1/users/show.json',client.transport.url.path,"Id should not be appended")
|
348
365
|
assert_equal(12345,client.transport.options[:params][:id], "Id should be treated as a parameter")
|
349
366
|
assert_equal("id=#{12345}",Net::HTTP.request.path.split(/\?/)[1],"id should be part of the query string")
|
350
367
|
end
|
@@ -352,23 +369,23 @@ class ClientTest < Test::Unit::TestCase
|
|
352
369
|
def test_auto_append_format_is_honored
|
353
370
|
client = new_client(200,'{"id":12345,"screen_name":"test_user"}')
|
354
371
|
client.users.show.hayesdavis?
|
355
|
-
assert_equal('/1/users/show/hayesdavis.json',client.transport.url.path,"Format should be appended by default")
|
372
|
+
assert_equal('/1.1/users/show/hayesdavis.json',client.transport.url.path,"Format should be appended by default")
|
356
373
|
client.auto_append_format = false
|
357
374
|
client.users.show.hayesdavis?
|
358
|
-
assert_equal('/1/users/show/hayesdavis',client.transport.url.path,"Format should not be appended to the URI")
|
375
|
+
assert_equal('/1.1/users/show/hayesdavis',client.transport.url.path,"Format should not be appended to the URI")
|
359
376
|
end
|
360
377
|
|
361
378
|
def test_auto_append_format_can_be_set_in_constructor
|
362
379
|
client = new_client(200,'{"id":12345,"screen_name":"test_user"}',:auto_append_format=>false)
|
363
380
|
client.users.show.hayesdavis?
|
364
|
-
assert_equal('/1/users/show/hayesdavis',client.transport.url.path,"Format should not be appended to the URI")
|
381
|
+
assert_equal('/1.1/users/show/hayesdavis',client.transport.url.path,"Format should not be appended to the URI")
|
365
382
|
end
|
366
383
|
|
367
384
|
def test_default_api
|
368
385
|
client = Grackle::Client.new
|
369
|
-
assert_equal(:
|
386
|
+
assert_equal(:v1_1,client.api,":v1_1 should be default api")
|
370
387
|
end
|
371
|
-
|
388
|
+
|
372
389
|
# Methods like Twitter's DELETE list membership expect that the user id will
|
373
390
|
# be form encoded like a POST request in the body. Net::HTTP seems to think
|
374
391
|
# that DELETEs can't have body parameters so we have to work around that.
|
@@ -378,7 +395,7 @@ class ClientTest < Test::Unit::TestCase
|
|
378
395
|
assert_equal(:delete,client.transport.method,"Expected delete request")
|
379
396
|
assert_equal('http',client.transport.url.scheme,"Expected scheme to be http")
|
380
397
|
assert_equal('api.twitter.com',client.transport.url.host,"Expected request to be against twitter.com")
|
381
|
-
assert_equal('/1/some_user/some_list/members.json',client.transport.url.path)
|
398
|
+
assert_equal('/1.1/some_user/some_list/members.json',client.transport.url.path)
|
382
399
|
assert_match(/user_id=12345/,Net::HTTP.request.body,"Parameters should be form encoded")
|
383
400
|
end
|
384
401
|
|
@@ -414,7 +431,7 @@ class ClientTest < Test::Unit::TestCase
|
|
414
431
|
assert_equal(:post,client.transport.method,"Expected post request")
|
415
432
|
assert_equal('http',client.transport.url.scheme,"Expected scheme to be http")
|
416
433
|
assert_equal('api.twitter.com',client.transport.url.host,"Expected request to be against twitter.com")
|
417
|
-
assert_equal('/1/statuses/update.json',client.transport.url.path)
|
434
|
+
assert_equal('/1.1/statuses/update.json',client.transport.url.path)
|
418
435
|
|
419
436
|
if RUBY_VERSION >= "1.9.3"
|
420
437
|
# 1.9.3 encodes a space with a + instead of %20
|
metadata
CHANGED
@@ -1,73 +1,75 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: grackle
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 19
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Hayes Davis
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2013-03-31 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
15
22
|
name: json
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ! '>='
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '0'
|
22
|
-
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ! '>='
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '0'
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: mime-types
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
33
25
|
none: false
|
34
|
-
requirements:
|
35
|
-
- -
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
38
33
|
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: mime-types
|
39
37
|
prerelease: false
|
40
|
-
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ! '>='
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: '0'
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: oauth
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
49
39
|
none: false
|
50
|
-
requirements:
|
51
|
-
- -
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
54
47
|
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: oauth
|
55
51
|
prerelease: false
|
56
|
-
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
53
|
none: false
|
58
|
-
requirements:
|
59
|
-
- -
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
|
62
|
-
|
63
|
-
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
|
+
description: " Grackle is a lightweight library for the Twitter REST API designed to be\n resilient to Twitter API changes or errors.\n"
|
64
64
|
email: hayes@unionmetrics.com
|
65
65
|
executables: []
|
66
|
+
|
66
67
|
extensions: []
|
67
|
-
|
68
|
+
|
69
|
+
extra_rdoc_files:
|
68
70
|
- README.rdoc
|
69
71
|
- CHANGELOG.rdoc
|
70
|
-
files:
|
72
|
+
files:
|
71
73
|
- README.rdoc
|
72
74
|
- CHANGELOG.rdoc
|
73
75
|
- lib/grackle/client.rb
|
@@ -79,28 +81,39 @@ files:
|
|
79
81
|
- test/client_test.rb
|
80
82
|
- test/handlers_test.rb
|
81
83
|
- test/test_helper.rb
|
84
|
+
has_rdoc: true
|
82
85
|
homepage: http://github.com/hayesdavis/grackle
|
83
86
|
licenses: []
|
87
|
+
|
84
88
|
post_install_message:
|
85
89
|
rdoc_options: []
|
86
|
-
|
90
|
+
|
91
|
+
require_paths:
|
87
92
|
- lib
|
88
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
94
|
none: false
|
90
|
-
requirements:
|
91
|
-
- -
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
|
94
|
-
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
hash: 3
|
99
|
+
segments:
|
100
|
+
- 0
|
101
|
+
version: "0"
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
103
|
none: false
|
96
|
-
requirements:
|
97
|
-
- -
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
hash: 3
|
108
|
+
segments:
|
109
|
+
- 0
|
110
|
+
version: "0"
|
100
111
|
requirements: []
|
112
|
+
|
101
113
|
rubyforge_project:
|
102
|
-
rubygems_version: 1.
|
114
|
+
rubygems_version: 1.3.7
|
103
115
|
signing_key:
|
104
116
|
specification_version: 3
|
105
|
-
summary: Grackle is a lightweight library for the Twitter REST
|
117
|
+
summary: Grackle is a lightweight library for the Twitter REST API.
|
106
118
|
test_files: []
|
119
|
+
|