¶ ↑
grackleby Hayes Davis
-
hayes [at] appozite [dot] com
¶ ↑
DESCRIPTIONGrackle is a lightweight Ruby wrapper around the Twitter REST and Search APIs. It’s based on my experience using the Twitter API to build cheaptweet.com. The main goal of Grackle is to never require a release when the Twitter API changes (which it often does) or in the face of a particular Twitter API bug. As such it’s somewhat different from other Twitter API libraries. It doesn’t try to hide the Twitter “methods” under an access layer nor does it introduce concrete classes for the various objects returned by Twitter. Instead, calls to the Grackle client map directly to Twitter API URLs. The objects returned by API calls are generated as OpenStructs on the fly and make no assumptions about the presence or absence of any particular attributes. Taking this approach means that changes to URLs used by Twitter, parameters required by those URLs or return values will not require a new release. It will potentially require, however, some modifications to your code that uses Grackle.
Grackle supports both OAuth and HTTP basic authentication.
¶ ↑
Support and AnnouncementsThe preferred forum for questions and discussions is the Google group at groups.google.com/group/gracklerb. You can email me directly or @reply me on Twitter, but the group is better since the questions and responses will be available to everyone. I’ll also make announcements there. There are some examples on the wiki at wiki.github.com/hayesdavis/grackle. If you prefer your information in 140 characters, follow @gracklerb.
¶ ↑
USING GRACKLEBefore you do anything else, you’ll need to
require 'grackle'
¶ ↑
Creating a Grackle::Client¶ ↑
Using Basic Authclient = Grackle::Client.new(:auth=>{:type=>:basic,:username=>'your_user',:password=>'yourpass'})
¶ ↑
Using OAuthclient = Grackle::Client.new(:auth=>{ :type=>:oauth, :consumer_key=>'SOMECONSUMERKEYFROMTWITTER', :consumer_secret=>'SOMECONSUMERTOKENFROMTWITTER', :token=>'ACCESSTOKENACQUIREDONUSERSBEHALF', :token_secret=>'SUPERSECRETACCESSTOKENSECRET' })
¶ ↑
Using No Authclient = Grackle::Client.new
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.
¶ ↑
Grackle Method SyntaxGrackle uses a method syntax that corresponds to the Twitter API URLs with a few twists. Where you would have a slash in a Twitter URL, that becomes a “.” in a chained set of Grackle method calls. Each call in the method chain is used to build Twitter URL path until a particular call is encountered which causes the request to be sent. Methods which will cause a request to be execute include:
-
A method call ending in “?” will cause an HTTP GET to be executed
-
A method call ending in “!” will cause an HTTP POST to be executed
-
If a valid format such as .json, .xml, .rss or .atom is encounted, a get will be executed with that format
-
A format method can also include a ? or ! to determine GET or POST in that format respectively
¶ ↑
GETting DataThe preferred and simplest way of executing a GET is to use the “?” method notation. This will use the default client format (usually JSON, but see Formats section below):
client.users.show? :screen_name=>'some_user' #http://twitter.com/users/show.json?screen_name=some_user
You can force XML format by doing:
client.users.show.xml? :screen_name=>'some_user' #http://twitter.com/users/show.xml?scren_name=some_user
You can force JSON:
client.users.show.json? :screen_name=>'some_user' #http://twitter.com/users/show.json?screen_name=some_user
Or, since Twitter also allows certain ids/screen_names to be part of their URLs, this works:
client.users.show.some_user? #http://twitter.com/users/show/some_user.json
If you use an explicit format, you can leave off the “?” like so:
client.users.show.xml :screen_name=>'some_user' #http://twitter.com/users/show.xml?scren_name=some_user
¶ ↑
POSTing dataTo use Twitter API methods that require an HTTP POST, you need to end your method chain with a bang (!)
The preferred way is to use the Client’s default format (usually JSON, but see Formats section below):
client.statuses.update! :status=>'this status is from grackle' #POST to http://twitter.com/statuses/update.json
You can force a format. To update the authenticated user’s status using the XML format:
client.statuses.update.xml! :status=>'this status is from grackle' #POST to http://twitter.com/statuses/update.xml
Or, with JSON
client.statuses.update.json! :status=>'this status is from grackle' #POST to http://twitter.com/statuses/update.json
¶ ↑
Using Other HTTP VerbsTo use HTTP verbs like DELETE or PUT, Grackle provides a slightly different syntax:
client.put{ hayesdavis.lists.my_list :name=>'New Name' } #HTTP PUT client.delete{ direct_messages.destroy :id=>1 } #HTTP DELETE
You may specify any method chain you wish in the block. Note that if your method chain inside the block ends in a ! or ?, that the HTTP verb for the block will still be used. This means that
client.delete{ direct_messages.destroy! :id=>1 } #Uses HTTP DELETE, not POST client.direct_messages.destroy! :id=>1 #Uses HTTP POST
If for some reason you don’t like the preferred block syntax above, you may specify a parameter to your method chain called :__method (note the double underscores) to specify the HTTP verb:
client.direct_messages.destroy! :id=>1, :__method=>:delete #HTTP DELETE
¶ ↑
Toggling APIsBy default, the Grackle::Client sends all requests to the unversioned Twitter REST API. If you want to send requests to the Twitter Search API, just set Grackle::Client.api to :search. To toggle back, set it to be :rest. All requests made after setting this attribute will go to that API.
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 bracket syntax like so:
client[:search].trends.daily? :exclude=>'hashtags' client[:rest].users.show? :id=>'hayesdavis'
Search and REST requests are all built using the same method chaining and termination conventions.
Twitter is introducing API versioning. Grackle now supports the version 1 API using the :v1 API name. When using the :v1 API, resources that were previously separated between the search and REST APIs are available under one unified API. To use the :v1 API, do the following:
client[:v1].search? :q=>'grackle' client[:v1].users.show? :id=>'hayesdavis'
If you want to use the :v1 API for all requests, you may set Grackle::Client.api to :v1 or specify the :api option in the Grackle::Client constructor like:
client = Grackle::Client.new(:api=>:v1)
¶ ↑
Parameter handling-
All parameters are URL encoded as necessary.
-
If you use a File object as a parameter it will be POSTed to Twitter in a multipart request.
-
If you use a Time object as a parameter, .httpdate will be called on it and that value will be used
¶ ↑
Return ValuesRegardless of the format used, Grackle returns an OpenStruct (actually a Grackle::TwitterStruct) of data. The attributes available on these structs correspond to the data returned by Twitter.
¶ ↑
Dealing with ErrorsIf the request to Twitter does not return a status code of 200, then a TwitterError is thrown. This contains the HTTP method used, the full request URI, the response status, the response body in text and a response object build by parsing the formatted error returned by Twitter. It’s a good idea to wrap your API calls with rescue clauses for Grackle::TwitterError.
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.
¶ ↑
FormatsTwitter allows you to request data in particular formats. Grackle automatically parses JSON and XML formatted responses and returns an OpenStruct. If you specify a format that Grackle doesn’t parse for you, you’ll receive a string containing the raw response body. The Grackle::Client has a default_format you can specify. By default, the default_format is :json. If you don’t include a named format in your method chain as described above, but use a “?” or “!” then the Grackle::Client.default_format is used.
¶ ↑
Odds and EndsIf you need to append something to the request path that isn’t a valid ruby method, e.g.
/1user/lists.json #1user isn't a valid Ruby method
you can use the Grackle::Client#_ method like so:
client._('1user').lists.json
¶ ↑
REQUIREMENTSYou’ll need the following gems to use all features of Grackle:
-
json
-
oauth
-
mime-types
¶ ↑
Ruby Version SupportGrackle works just fine on Ruby 1.8.x. It is also known to work on 1.9.1 with the exception of OAuth. The OAuth gem used by Grackle has not been updated fully to support 1.9. Please see this thread for more information.
Once the OAuth gem has been updated, Grackle will work fully on 1.9. If you aren’t using OAuth it should be fine for use on 1.9 as is.
¶ ↑
INSTALLThe grackle gem is now hosted at gemcutter.org. If you’ve already setup gemcutter in your sources, you can do the following:
sudo gem install grackle
If you haven’t yet setup gemcutter in your sources, go to gemcutter.org and follow the instructions there. They will likely tell you to do the following:
sudo gem install gemcutter sudo gem tumble
Once you’ve done that you can do:
sudo gem install grackle
¶ ↑
LICENSE(The MIT License)
Copyright © 2009
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.