grackle 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,7 @@
1
+ == 0.1.6 (2009-10-29)
2
+ * Added support for HTTP methods beside GET and POST using block syntax
3
+ * Added method for appending to the request path something that's not a valid ruby method
4
+
1
5
  == 0.1.5 (2009-10-28)
2
6
  Added support for the Twitter version 1 API as a API symbol :v1
3
7
 
data/README.rdoc CHANGED
@@ -79,6 +79,20 @@ You can force a format. To update the authenticated user's status using the XML
79
79
 
80
80
  Or, with JSON
81
81
  client.statuses.update.json! :status=>'this status is from grackle' #POST to http://twitter.com/statuses/update.json
82
+
83
+ ===Using Other HTTP Verbs
84
+ To use HTTP verbs like DELETE or PUT, Grackle provides a slightly different syntax:
85
+ client.put{ hayesdavis.lists.my_list :name=>'New Name' } #HTTP PUT
86
+ client.delete{ direct_messages.destroy :id=>1 } #HTTP DELETE
87
+
88
+ You may specify any method chain you wish in the block. Note that if your method chain inside the block
89
+ ends in a ! or ?, that the HTTP verb for the block will still be used. This means that
90
+ client.delete{ direct_messages.destroy! :id=>1 } #Uses HTTP DELETE, not POST
91
+ client.direct_messages.destroy! :id=>1 #Uses HTTP POST
92
+
93
+ If for some reason you don't like the preferred block syntax above, you may specify a
94
+ parameter to your method chain called :__method (note the double underscores) to specify the HTTP verb:
95
+ client.direct_messages.destroy! :id=>1, :__method=>:delete #HTTP DELETE
82
96
 
83
97
  ===Toggling APIs
84
98
  By default, the Grackle::Client sends all requests to the unversioned Twitter REST API. If you want to send requests to
@@ -125,6 +139,12 @@ the raw response body. The Grackle::Client has a default_format you can specify.
125
139
  If you don't include a named format in your method chain as described above, but use a "?" or "!" then the
126
140
  Grackle::Client.default_format is used.
127
141
 
142
+ ===Odds and Ends
143
+ If you need to append something to the request path that isn't a valid ruby method, e.g.
144
+ /1user/lists.json #1user isn't a valid Ruby method
145
+ you can use the Grackle::Client#_ method like so:
146
+ client._('1user').lists.json
147
+
128
148
  == REQUIREMENTS:
129
149
 
130
150
  You'll need the following gems to use all features of Grackle:
data/grackle.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{grackle}
5
- s.version = "0.1.5"
5
+ s.version = "0.1.6"
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-05-23}
9
+ s.date = %q{2009-10-29}
10
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 = ["CHANGELOG.rdoc", "README.rdoc", "grackle.gemspec", "lib/grackle.rb", "lib/grackle/client.rb", "lib/grackle/handlers.rb", "lib/grackle/transport.rb", "lib/grackle/utils.rb", "test/test_grackle.rb", "test/test_helper.rb", "test/test_client.rb", "test/test_handlers.rb"]
@@ -45,13 +45,12 @@ module Grackle
45
45
  class Client
46
46
 
47
47
  class Request #:nodoc:
48
- attr_accessor :client, :path, :method, :api, :ssl
48
+ attr_accessor :client, :path, :method, :api, :ssl, :params
49
49
 
50
50
  def initialize(client,api=:rest,ssl=true)
51
51
  self.client = client
52
52
  self.api = api
53
53
  self.ssl = ssl
54
- self.method = :get
55
54
  self.path = ''
56
55
  end
57
56
 
@@ -74,9 +73,12 @@ module Grackle
74
73
  def scheme
75
74
  ssl ? 'https' :'http'
76
75
  end
76
+
77
+ def params
78
+ @params ||= {}
79
+ end
77
80
  end
78
81
 
79
- VALID_METHODS = [:get,:post,:put,:delete]
80
82
  VALID_FORMATS = [:json,:xml,:atom,:rss]
81
83
 
82
84
  # Contains the mapping of API name symbols to actual host (and path)
@@ -133,26 +135,11 @@ module Grackle
133
135
  end
134
136
  end
135
137
 
136
- def method_missing(name,*args)
137
- #If method is a format name, execute using that format
138
- if format_invocation?(name)
139
- return call_with_format(name,*args)
140
- end
141
- #If method ends in ! or ? use that to determine post or get
142
- if name.to_s =~ /^(.*)(!|\?)$/
143
- name = $1.to_sym
144
- #! is a post, ? is a get
145
- self.request.method = ($2 == '!' ? :post : :get)
146
- if format_invocation?(name)
147
- return call_with_format(name,*args)
148
- else
149
- self.request << "/#{$1}"
150
- return call_with_format(self.default_format,*args)
151
- end
138
+ def method_missing(name,*args,&block)
139
+ if block_given?
140
+ return request_with_http_method_block(name,&block)
152
141
  end
153
- #Else add to the request path
154
- self.request << "/#{name}"
155
- self
142
+ append(name,*args)
156
143
  end
157
144
 
158
145
  # Used to toggle APIs for a particular request without setting the Client's default API
@@ -197,21 +184,53 @@ module Grackle
197
184
  auth[:password] = value
198
185
  end
199
186
 
187
+ def append(name,*args)
188
+ name = name.to_sym
189
+ #The args will be a hash, store them if they're specified
190
+ self.request.params = *args
191
+ #If method is a format name, execute using that format
192
+ if format_invocation?(name)
193
+ return call_with_format(name)
194
+ end
195
+ #If method ends in ! or ? use that to determine post or get
196
+ if name.to_s =~ /^(.*)(!|\?)$/
197
+ name = $1.to_sym
198
+ #! is a post, ? is a get - only set this if the method hasn't been set
199
+ self.request.method ||= ($2 == '!' ? :post : :get)
200
+ if format_invocation?(name)
201
+ return call_with_format(name)
202
+ else
203
+ self.request << "/#{$1}"
204
+ return call_with_format(self.default_format)
205
+ end
206
+ end
207
+ #Else add to the request path
208
+ self.request << "/#{name}"
209
+ self
210
+ end
211
+
212
+ alias_method :_, :append
213
+
200
214
  protected
201
- def call_with_format(format,params={})
202
- id = params.delete(:id)
215
+ def call_with_format(format)
216
+ id = request.params.delete(:id)
203
217
  request << "/#{id}" if id
204
218
  request << ".#{format}"
205
- res = send_request(params)
219
+ res = send_request
206
220
  process_response(format,res)
207
221
  ensure
208
222
  clear
209
223
  end
210
224
 
211
- def send_request(params)
225
+ def send_request
212
226
  begin
227
+ http_method = (
228
+ request.params.delete(:__method) or request.method or :get
229
+ )
213
230
  transport.request(
214
- request.method,request.url,:auth=>auth,:headers=>headers,:params=>params, :timeout => timeout
231
+ http_method, request.url,
232
+ :auth=>auth,:headers=>headers,
233
+ :params=>request.params,:timeout => timeout
215
234
  )
216
235
  rescue => e
217
236
  puts e
@@ -251,5 +270,19 @@ module Grackle
251
270
  def format_invocation?(name)
252
271
  self.request.path? && VALID_FORMATS.include?(name)
253
272
  end
273
+
274
+ def pending_request?
275
+ !@request.nil?
276
+ end
277
+
278
+ def request_with_http_method_block(method,&block)
279
+ request.method = method
280
+ response = instance_eval(&block)
281
+ if pending_request?
282
+ call_with_format(self.default_format)
283
+ else
284
+ response
285
+ end
286
+ end
254
287
  end
255
288
  end
@@ -19,12 +19,7 @@ module Grackle
19
19
  DEFAULT_REDIRECT_LIMIT = 5
20
20
 
21
21
  def req_class(method)
22
- case method
23
- when :get then Net::HTTP::Get
24
- when :post then Net::HTTP::Post
25
- when :put then Net::HTTP::Put
26
- when :delete then Net::HTTP::Delete
27
- end
22
+ Net::HTTP.const_get(method.to_s.capitalize)
28
23
  end
29
24
 
30
25
  # Options are one of
data/lib/grackle.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Grackle
2
2
 
3
3
  # :stopdoc:
4
- VERSION = '0.1.5'
4
+ VERSION = '0.1.6'
5
5
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
6
6
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
7
7
  # :startdoc:
data/test/test_client.rb CHANGED
@@ -195,6 +195,45 @@ class TestClient < Test::Unit::TestCase
195
195
  client.statuses.public_timeline? :since=>time
196
196
  assert_equal("/statuses/public_timeline.json?since=#{CGI::escape(time.httpdate)}",Net::HTTP.request.path)
197
197
  end
198
+
199
+ def test_simple_http_method_block
200
+ client = new_client(200,'[{"id":1,"text":"test 1"}]')
201
+ client.delete { direct_messages.destroy :id=>1, :other=>'value' }
202
+ assert_equal(:delete,client.transport.method, "delete block should use delete method")
203
+ assert_equal("/direct_messages/destroy/1.json",Net::HTTP.request.path)
204
+ assert_equal('value',client.transport.options[:params][:other])
205
+
206
+ client = new_client(200,'{"id":54321,"screen_name":"test_user"}')
207
+ value = client.get { users.show.json? :screen_name=>'test_user' }
208
+ assert_equal(:get,client.transport.method)
209
+ assert_equal('http',client.transport.url.scheme)
210
+ assert(!Net::HTTP.last_instance.use_ssl?,'Net::HTTP instance should not be set to use SSL')
211
+ assert_equal('twitter.com',client.transport.url.host)
212
+ assert_equal('/users/show.json',client.transport.url.path)
213
+ assert_equal('test_user',client.transport.options[:params][:screen_name])
214
+ assert_equal('screen_name=test_user',Net::HTTP.request.path.split(/\?/)[1])
215
+ assert_equal(54321,value.id)
216
+ end
217
+
218
+ def test_http_method_blocks_choose_right_method
219
+ client = new_client(200,'[{"id":1,"text":"test 1"}]')
220
+ client.get { search :q=>'test' }
221
+ assert_equal(:get,client.transport.method, "Get block should choose get method")
222
+ client.delete { direct_messages.destroy :id=>1 }
223
+ assert_equal(:delete,client.transport.method, "Delete block should choose delete method")
224
+ client.post { direct_messages.destroy :id=>1 }
225
+ assert_equal(:post,client.transport.method, "Post block should choose post method")
226
+ client.put { direct_messages :id=>1 }
227
+ assert_equal(:put,client.transport.method, "Put block should choose put method")
228
+ end
229
+
230
+ def test_http_method_selection_precedence
231
+ client = new_client(200,'[{"id":1,"text":"test 1"}]')
232
+ client.get { search! :q=>'test' }
233
+ assert_equal(:get,client.transport.method, "Get block should override method even if post bang is used")
234
+ client.delete { search? :q=>'test', :__method=>:post }
235
+ assert_equal(:post,client.transport.method, ":__method=>:post should override block setting and method suffix")
236
+ end
198
237
 
199
238
  private
200
239
  def with_http_responder(responder)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grackle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
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-05-23 00:00:00 -05:00
12
+ date: 2009-10-29 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency